source: rtems/cpukit/libnetworking/rtems/rtems_select.c @ da10694

4.115
Last change on this file since da10694 was 14876018, checked in by Daniel Ramirez <javamonn@…>, on 11/21/13 at 00:24:48

select.h, rtems_select.c, nds select: Add restrict keyword

  • Property mode set to 100644
File size: 4.0 KB
Line 
1#if HAVE_CONFIG_H
2#include "config.h"
3#endif
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 <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_snd.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 *__restrict readfds, fd_set *__restrict writefds,
114        fd_set *__restrict exceptfds, struct timeval *__restrict tv)
115{
116        fd_mask *ibits[3], *obits[3];
117        fd_set ob[3];
118        int error, timo;
119        int retval = 0;
120        rtems_id tid;
121        rtems_interval then = 0, now;
122        rtems_event_set events;
123
124        if (nfds < 0)
125                return (EINVAL);
126        if (tv) {
127                timo = tv->tv_sec * hz + tv->tv_usec / tick;
128                if (timo == 0)
129                        timo = 1;
130                then = rtems_clock_get_ticks_since_boot();
131        }
132        else {
133                timo = 0;
134        }
135
136#define getbits(name,i) if (name) { \
137                ibits[i] = &name->fds_bits[0]; \
138                obits[i] = &ob[i].fds_bits[0]; \
139                FD_ZERO(&ob[i]); \
140        } \
141        else ibits[i] = NULL
142        getbits (readfds, 0);
143        getbits (writefds, 1);
144        getbits (exceptfds, 2);
145#undef getbits
146
147        rtems_task_ident (RTEMS_SELF, 0, &tid);
148        rtems_event_system_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
149        for (;;) {
150                rtems_bsdnet_semaphore_obtain ();
151                error = selscan(tid, ibits, obits, nfds, &retval);
152                rtems_bsdnet_semaphore_release ();
153                if (error || retval)
154                        break;
155                if (timo) {
156                        now = rtems_clock_get_ticks_since_boot();
157                        timo -= now - then;
158                        if (timo <= 0)
159                                break;
160                        then = now;
161                }
162                rtems_event_system_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, timo, &events);
163        }
164
165#define putbits(name,i) if (name) *name = ob[i]
166        putbits (readfds, 0);
167        putbits (writefds, 1);
168        putbits (exceptfds, 2);
169#undef putbits
170        if (error) {
171                errno = error;
172                retval = -1;
173        }
174        return (retval);
175}
Note: See TracBrowser for help on using the repository browser.