source: rtems/c/src/libnetworking/rtems/rtems_select.c @ 1b821242

4.104.114.84.95
Last change on this file since 1b821242 was 1b821242, checked in by Joel Sherrill <joel.sherrill@…>, on 10/06/99 at 20:37:26

Modified to avoid conflicts on definitions of malloc. newlib 1.8.2
now prototypes the malloc family in stdlib.h. This causes conflicts
with the way the network stack overrides the definitions of malloc.
As best I (being Joel) can tell, commenting stdlib.h out keeps the
files compiling and referencing the desired malloc/free but results
in more warnings.

  • Property mode set to 100644
File size: 3.9 KB
Line 
1/*
2 *  $Id$
3 */
4
5#include <string.h>
6#include <stdarg.h>
7/* #include <stdlib.h> */
8#include <stdio.h>
9
10#include <rtems.h>
11#include <rtems/libio.h>
12#include <rtems/error.h>
13#include <rtems/rtems_bsdnet.h>
14
15#include <sys/errno.h>
16#include <sys/fcntl.h>
17#include <sys/types.h>
18#include <sys/param.h>
19#include <sys/mbuf.h>
20#include <sys/socket.h>
21#include <sys/socketvar.h>
22#include <sys/protosw.h>
23#include <sys/proc.h>
24#include <sys/filio.h>
25
26#include <net/if.h>
27#include <net/route.h>
28
29/*
30 *********************************************************************
31 *            RTEMS implementation of select() system call           *
32 *********************************************************************
33 */
34
35/*
36 * This implementation is quite restricted:
37 *      Works on sockets only -- no support for other devices!
38 *      A given socket can be in a read-select or a read/recv* by only
39 *              one task at a time.
40 *      A given socket can be in a write-select or a write/send* by only
41 *              one task at a time.
42 *
43 * NOTE - select() is a very expensive system call.  It should be avoided
44 *        if at all possible.  In many cases, rewriting the application
45 *        to use multiple tasks (one per socket) is a better solution.
46 */
47
48static __inline int imin(int a, int b) { return (a < b ? a : b); }
49struct socket *rtems_bsdnet_fdToSocket(int fd);
50
51static int
52socket_select (struct socket *so, int which, rtems_id tid)
53{
54        switch (which) {
55
56        case FREAD:
57                if (soreadable(so))
58                        return (1);
59                so->so_rcv.sb_flags |= SB_WAIT;
60                so->so_rcv.sb_sel.si_pid = tid;
61                break;
62
63        case FWRITE:
64                if (sowriteable(so))
65                        return (1);
66                so->so_rcv.sb_flags |= SB_WAIT;
67                so->so_snd.sb_sel.si_pid = tid;
68                break;
69
70        case 0:
71                if (so->so_oobmark || (so->so_state & SS_RCVATMARK))
72                        return (1);
73                so->so_rcv.sb_sel.si_pid = tid;
74                break;
75        }
76        return (0);
77}
78
79static int
80selscan (rtems_id tid, fd_mask **ibits, fd_mask **obits, int nfd, int *retval)
81{
82        struct socket *so;
83        int msk, i, fd;
84        fd_mask bits, bit;
85        int n = 0;
86        static int flag[3] = { FREAD, FWRITE, 0 };
87
88        for (msk = 0; msk < 3; msk++) {
89                if (ibits[msk] == NULL)
90                        continue;
91                for (i = 0; i < nfd; i += NFDBITS) {
92                        bits = ibits[msk][i/NFDBITS];
93                        for (fd = i, bit = 1 ; bits && (fd < nfd) ; fd++, bit <<= 1) {
94                                if ((bits & bit) == 0)
95                                        continue;
96                                bits &= ~bit;
97                                so = rtems_bsdnet_fdToSocket (fd);
98                                if (so == NULL)
99                                        return (EBADF);
100                                if (socket_select (so, flag[msk], tid)) {
101                                        obits[msk][fd/NFDBITS] |=
102                                                        (1 << (fd % NFDBITS));
103                                        n++;
104                                }
105                        }
106                }
107        }
108        *retval = n;
109        return (0);
110}
111
112int
113select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *tv)
114{
115        fd_mask *ibits[3], *obits[3];
116        fd_set ob[3];
117        int error, timo;
118        int retval;
119        rtems_id tid;
120        rtems_interval then, now;
121        rtems_event_set events;
122
123        if (nfds < 0)
124                return (EINVAL);
125        if (tv) {
126                timo = tv->tv_sec * hz + tv->tv_usec / tick;
127                if (timo == 0)
128                        timo = 1;
129                rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
130        }
131        else {
132                timo = 0;
133        }
134
135#define getbits(name,i) if (name) { \
136                ibits[i] = &name->fds_bits[0]; \
137                obits[i] = &ob[i].fds_bits[0]; \
138                FD_ZERO(&ob[i]); \
139        } \
140        else ibits[i] = NULL
141        getbits (readfds, 0);
142        getbits (writefds, 1);
143        getbits (exceptfds, 2);
144#undef getbits
145
146        rtems_task_ident (RTEMS_SELF, 0, &tid);
147        rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
148        for (;;) {
149                rtems_bsdnet_semaphore_obtain ();
150                error = selscan(tid, ibits, obits, nfds, &retval);
151                rtems_bsdnet_semaphore_release ();
152                if (error || retval)
153                        break;
154                if (timo) {
155                        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
156                        timo -= now - then;
157                        if (timo <= 0)
158                                break;
159                        then = now;
160                }
161                rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, timo, &events);
162        }
163
164#define putbits(name,i) if (name) *name = ob[i]
165        putbits (readfds, 0);
166        putbits (writefds, 1);
167        putbits (exceptfds, 2);
168#undef putbits
169        if (error) {
170                errno = error;
171                retval = -1;
172        }
173        return (retval);
174}
Note: See TracBrowser for help on using the repository browser.