source: rtems-libbsd/rtemsbsd/rtems/rtems-bsd-generic.c @ dd35ec5

55-freebsd-126-freebsd-12
Last change on this file since dd35ec5 was 3c967ca, checked in by Sebastian Huber <sebastian.huber@…>, on 06/08/17 at 11:15:12

Use <sys/lock.h> provided by Newlib

  • Property mode set to 100644
File size: 5.6 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup rtems_bsd_rtems
5 *
6 * @brief TODO.
7 */
8
9/*
10 * Copyright (c) 2009, 2010 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Obere Lagerstr. 30
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 *    notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 *    notice, this list of conditions and the following disclaimer in the
25 *    documentation and/or other materials provided with the distribution.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 */
39
40#include <sys/types.h> //needed for fd_mask and such
41#include <machine/rtems-bsd-kernel-space.h>
42
43#include <sys/types.h>
44#include <sys/systm.h>
45#include <sys/selinfo.h>
46#include <sys/fcntl.h>
47#include <sys/socket.h>
48#include <sys/socketvar.h>
49#include <sys/protosw.h>
50#include <sys/select.h>
51#include <sys/kernel.h>
52#include <sys/lock.h>
53#include <sys/mutex.h>
54#include <sys/malloc.h>
55
56void selrecord(struct thread *selector, struct selinfo *sip)
57{
58        BSD_PANIC("not implemented");
59}
60
61void selwakeup(struct selinfo *sip)
62{
63        BSD_PANIC("not implemented");
64}
65
66void selwakeuppri(struct selinfo *sip, int pri)
67{
68        BSD_PANIC("not implemented");
69}
70
71void seltdfini(struct thread *td)
72{
73        BSD_PANIC("not implemented");
74}
75
76/*
77 *********************************************************************
78 *            RTEMS implementation of select() system call           *
79 *********************************************************************
80 */
81
82/*
83 * This implementation is quite restricted:
84 *      Works on sockets only -- no support for other devices!
85 *      A given socket can be in a read-select or a read/recv* by only
86 *              one task at a time.
87 *      A given socket can be in a write-select or a write/send* by only
88 *              one task at a time.
89 *
90 * NOTE - select() is a very expensive system call.  It should be avoided
91 *        if at all possible.  In many cases, rewriting the application
92 *        to use multiple tasks (one per socket) is a better solution.
93 */
94
95struct socket *rtems_bsdnet_fdToSocket(int fd);
96
97static int
98socket_select (struct socket *so, int which, rtems_id tid)
99{
100        switch (which) {
101
102        case FREAD:
103                if (soreadable(so))
104                        return (1);
105                SOCK_LOCK(so);
106                so->so_rcv.sb_flags |= SB_WAIT;
107                so->so_rcv.sb_sel.si_pid = tid;
108                SOCK_UNLOCK(so);
109                break;
110
111        case FWRITE:
112                if (sowriteable(so))
113                        return (1);
114                SOCK_LOCK(so);
115                so->so_snd.sb_flags |= SB_WAIT;
116                so->so_snd.sb_sel.si_pid = tid;
117                SOCK_UNLOCK(so);
118                break;
119
120        case 0:
121                if (so->so_oobmark || (so->so_state & SBS_RCVATMARK))
122                        return (1);
123                SOCK_LOCK(so);
124                so->so_rcv.sb_sel.si_pid = tid;
125                SOCK_UNLOCK(so);
126                break;
127        }
128        return (0);
129}
130
131static int
132selscan (rtems_id tid, fd_mask **ibits, fd_mask **obits, int nfd, int *retval)
133{
134        struct socket *so;
135        int msk, i, fd;
136        fd_mask bits, bit;
137        int n = 0;
138        static int flag[3] = { FREAD, FWRITE, 0 };
139
140        for (msk = 0; msk < 3; msk++) {
141                if (ibits[msk] == NULL)
142                        continue;
143                for (i = 0; i < nfd; i += NFDBITS) {
144                        bits = ibits[msk][i/NFDBITS];
145                        for (fd = i, bit = 1 ; bits && (fd < nfd) ; fd++, bit <<= 1) {
146                                if ((bits & bit) == 0)
147                                        continue;
148                                bits &= ~bit;
149                                so = rtems_bsdnet_fdToSocket (fd);
150                                if (so == NULL)
151                                        return (EBADF);
152                                if (socket_select (so, flag[msk], tid)) {
153                                        obits[msk][fd/NFDBITS] |=
154                                                        (1 << (fd % NFDBITS));
155                                        n++;
156                                }
157                        }
158                }
159        }
160        *retval = n;
161        return (0);
162}
163
164int
165select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *tv)
166{
167        fd_mask *ibits[3], *obits[3];
168        fd_set ob[3];
169        int error, timo;
170        int retval = 0;
171        rtems_id tid;
172        rtems_interval then = 0, now;
173        rtems_event_set events;
174
175        if (nfds < 0)
176                return (EINVAL);
177        if (tv) {
178                timo = tv->tv_sec * hz + tv->tv_usec / tick;
179                if (timo == 0)
180                        timo = 1;
181                then = rtems_clock_get_ticks_since_boot();
182        }
183        else {
184                timo = 0;
185        }
186
187#define getbits(name,i) if (name) { \
188                ibits[i] = &name->fds_bits[0]; \
189                obits[i] = &ob[i].fds_bits[0]; \
190                FD_ZERO(&ob[i]); \
191        } \
192        else ibits[i] = NULL
193        getbits (readfds, 0);
194        getbits (writefds, 1);
195        getbits (exceptfds, 2);
196#undef getbits
197
198        //rtems_task_ident (RTEMS_SELF, 0, &tid);
199        //rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
200        for (;;) {
201                error = selscan(tid, ibits, obits, nfds, &retval);
202                if (error || retval)
203                        break;
204                if (timo) {
205                        now = rtems_clock_get_ticks_since_boot();
206                        timo -= now - then;
207                        if (timo <= 0)
208                                break;
209                        then = now;
210                }
211                //rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, timo, &events);
212        }
213
214#define putbits(name,i) if (name) *name = ob[i]
215        putbits (readfds, 0);
216        putbits (writefds, 1);
217        putbits (exceptfds, 2);
218#undef putbits
219        if (error) {
220                errno = error;
221                retval = -1;
222        }
223        return (retval);
224}
Note: See TracBrowser for help on using the repository browser.