source: rtems-libbsd/rtems/freebsd/rtems/rtems-bsd-generic.c @ a9153ec

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since a9153ec was a9153ec, checked in by Joel Sherrill <joel.sherrill@…>, on 03/07/12 at 15:52:04

Initial import

Code is based on FreeBSD 8.2 with USB support from Sebastian Huber
and Thomas Doerfler. Initial TCP/IP stack work is from Kevel Kirspel.

  • Property mode set to 100644
File size: 4.7 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 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
20 * http://www.rtems.com/license/LICENSE.
21 */
22
23#include <sys/types.h> //needed for fd_mask and such
24#include <rtems/freebsd/machine/rtems-bsd-config.h>
25
26#include <rtems/freebsd/sys/types.h>
27#include <rtems/freebsd/sys/systm.h>
28#include <rtems/freebsd/sys/selinfo.h>
29#include <rtems/freebsd/sys/fcntl.h>
30#include <rtems/freebsd/sys/socket.h>
31#include <rtems/freebsd/sys/socketvar.h>
32#include <rtems/freebsd/sys/protosw.h>
33#include <rtems/freebsd/sys/select.h>
34#include <rtems/freebsd/sys/kernel.h>
35#include <rtems/freebsd/sys/lock.h>
36#include <rtems/freebsd/sys/mutex.h>
37#include <rtems/freebsd/sys/malloc.h>
38
39MALLOC_DEFINE(M_IOV, "iov", "large iov's");
40
41void selrecord(struct thread *selector, struct selinfo *sip)
42{
43        BSD_PANIC("not implemented");
44}
45
46void selwakeup(struct selinfo *sip)
47{
48        BSD_PANIC("not implemented");
49}
50
51void selwakeuppri(struct selinfo *sip, int pri)
52{
53        BSD_PANIC("not implemented");
54}
55
56void seltdfini(struct thread *td)
57{
58        BSD_PANIC("not implemented");
59}
60
61/*
62 *********************************************************************
63 *            RTEMS implementation of select() system call           *
64 *********************************************************************
65 */
66
67/*
68 * This implementation is quite restricted:
69 *      Works on sockets only -- no support for other devices!
70 *      A given socket can be in a read-select or a read/recv* by only
71 *              one task at a time.
72 *      A given socket can be in a write-select or a write/send* by only
73 *              one task at a time.
74 *
75 * NOTE - select() is a very expensive system call.  It should be avoided
76 *        if at all possible.  In many cases, rewriting the application
77 *        to use multiple tasks (one per socket) is a better solution.
78 */
79
80struct socket *rtems_bsdnet_fdToSocket(int fd);
81
82static int
83socket_select (struct socket *so, int which, rtems_id tid)
84{
85        switch (which) {
86
87        case FREAD:
88                if (soreadable(so))
89                        return (1);
90                SOCK_LOCK(so);
91                so->so_rcv.sb_flags |= SB_WAIT;
92                so->so_rcv.sb_sel.si_pid = tid;
93                SOCK_UNLOCK(so);
94                break;
95
96        case FWRITE:
97                if (sowriteable(so))
98                        return (1);
99                SOCK_LOCK(so);
100                so->so_snd.sb_flags |= SB_WAIT;
101                so->so_snd.sb_sel.si_pid = tid;
102                SOCK_UNLOCK(so);
103                break;
104
105        case 0:
106                if (so->so_oobmark || (so->so_state & SBS_RCVATMARK))
107                        return (1);
108                SOCK_LOCK(so);
109                so->so_rcv.sb_sel.si_pid = tid;
110                SOCK_UNLOCK(so);
111                break;
112        }
113        return (0);
114}
115
116static int
117selscan (rtems_id tid, fd_mask **ibits, fd_mask **obits, int nfd, int *retval)
118{
119        struct socket *so;
120        int msk, i, fd;
121        fd_mask bits, bit;
122        int n = 0;
123        static int flag[3] = { FREAD, FWRITE, 0 };
124
125        for (msk = 0; msk < 3; msk++) {
126                if (ibits[msk] == NULL)
127                        continue;
128                for (i = 0; i < nfd; i += NFDBITS) {
129                        bits = ibits[msk][i/NFDBITS];
130                        for (fd = i, bit = 1 ; bits && (fd < nfd) ; fd++, bit <<= 1) {
131                                if ((bits & bit) == 0)
132                                        continue;
133                                bits &= ~bit;
134                                so = rtems_bsdnet_fdToSocket (fd);
135                                if (so == NULL)
136                                        return (EBADF);
137                                if (socket_select (so, flag[msk], tid)) {
138                                        obits[msk][fd/NFDBITS] |=
139                                                        (1 << (fd % NFDBITS));
140                                        n++;
141                                }
142                        }
143                }
144        }
145        *retval = n;
146        return (0);
147}
148
149int
150select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *tv)
151{
152        fd_mask *ibits[3], *obits[3];
153        fd_set ob[3];
154        int error, timo;
155        int retval = 0;
156        rtems_id tid;
157        rtems_interval then = 0, now;
158        rtems_event_set events;
159
160        if (nfds < 0)
161                return (EINVAL);
162        if (tv) {
163                timo = tv->tv_sec * hz + tv->tv_usec / tick;
164                if (timo == 0)
165                        timo = 1;
166                then = rtems_clock_get_ticks_since_boot();
167        }
168        else {
169                timo = 0;
170        }
171
172#define getbits(name,i) if (name) { \
173                ibits[i] = &name->fds_bits[0]; \
174                obits[i] = &ob[i].fds_bits[0]; \
175                FD_ZERO(&ob[i]); \
176        } \
177        else ibits[i] = NULL
178        getbits (readfds, 0);
179        getbits (writefds, 1);
180        getbits (exceptfds, 2);
181#undef getbits
182
183        //rtems_task_ident (RTEMS_SELF, 0, &tid);
184        //rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
185        for (;;) {
186                error = selscan(tid, ibits, obits, nfds, &retval);
187                if (error || retval)
188                        break;
189                if (timo) {
190                        now = rtems_clock_get_ticks_since_boot();
191                        timo -= now - then;
192                        if (timo <= 0)
193                                break;
194                        then = now;
195                }
196                //rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, timo, &events);
197        }
198
199#define putbits(name,i) if (name) *name = ob[i]
200        putbits (readfds, 0);
201        putbits (writefds, 1);
202        putbits (exceptfds, 2);
203#undef putbits
204        if (error) {
205                errno = error;
206                retval = -1;
207        }
208        return (retval);
209}
Note: See TracBrowser for help on using the repository browser.