source: rtems/cpukit/libnetworking/rtems/rtems_select.c @ 182813e

4.104.114.84.95
Last change on this file since 182813e was 182813e, checked in by Joel Sherrill <joel.sherrill@…>, on 05/20/05 at 19:58:32

2005-05-20 Sergei Organov <osv@…>

PR networking/772.

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