diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 1999-01-21 22:25:43 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 1999-01-21 22:25:43 +0000 |
commit | 94b3ee1366fddb9aca95f2f1ec61d633deb66510 (patch) | |
tree | 343ae71bb853274c8608e0792832a6f72cf33a71 /c/src/lib/libnetworking/rtems | |
parent | Added common problems section after post by Philippe Le Foll (diff) | |
download | rtems-94b3ee1366fddb9aca95f2f1ec61d633deb66510.tar.bz2 |
Made to compile after hacking tftp driver into beginnings of a mini-filesystem.
Diffstat (limited to 'c/src/lib/libnetworking/rtems')
-rw-r--r-- | c/src/lib/libnetworking/rtems/rtems_bsdnet_internal.h | 16 | ||||
-rw-r--r-- | c/src/lib/libnetworking/rtems/rtems_select.c | 171 | ||||
-rw-r--r-- | c/src/lib/libnetworking/rtems/sghostname.c | 4 |
3 files changed, 188 insertions, 3 deletions
diff --git a/c/src/lib/libnetworking/rtems/rtems_bsdnet_internal.h b/c/src/lib/libnetworking/rtems/rtems_bsdnet_internal.h index 453fb23c66..5d355f4a36 100644 --- a/c/src/lib/libnetworking/rtems/rtems_bsdnet_internal.h +++ b/c/src/lib/libnetworking/rtems/rtems_bsdnet_internal.h @@ -166,7 +166,7 @@ extern int rtems_bsdnet_nameserver_count; /* * Some extra prototypes */ -int sethostname (char *name, int namelen); +int sethostname (char *name, size_t namelen); void domaininit (void *); void ifinit (void *); void ipintr (void); @@ -174,5 +174,19 @@ void arpintr (void); void bootpc_init(void); int socket (int, int, int); int ioctl (int, unsigned long, ...); +struct socket *rtems_bsdnet_fdToSocket (int fd); +int rtems_bsdnet_makeFdForSocket (struct socket *); + +/* + * Events used by networking routines. + * Everything will break if the application + * tries to use these events or if the `sleep' + * events are equal to any of the NETISR * events. + */ +#define SBWAIT_EVENT RTEMS_EVENT_24 +#define SOSLEEP_EVENT RTEMS_EVENT_25 +#define NETISR_IP_EVENT (1 << NETISR_IP) +#define NETISR_ARP_EVENT (1 << NETISR_ARP) +#define NETISR_EVENTS (NETISR_IP_EVENT|NETISR_ARP_EVENT) #endif /* _RTEMS_BSDNET_INTERNAL_H_ */ diff --git a/c/src/lib/libnetworking/rtems/rtems_select.c b/c/src/lib/libnetworking/rtems/rtems_select.c new file mode 100644 index 0000000000..2487edf9fc --- /dev/null +++ b/c/src/lib/libnetworking/rtems/rtems_select.c @@ -0,0 +1,171 @@ +/* + * $Id$ + */ + +#include <string.h> +#include <stdarg.h> +#include <stdlib.h> +#include <stdio.h> + +#include <rtems.h> +#include <rtems/libio.h> +#include <rtems/error.h> +#include <rtems/rtems_bsdnet.h> + +#include <sys/errno.h> +#include <sys/fcntl.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/protosw.h> +#include <sys/proc.h> +#include <sys/filio.h> + +#include <net/if.h> +#include <net/route.h> + +/* + ********************************************************************* + * RTEMS implementation of select() system call * + ********************************************************************* + */ + +/* + * This implementation is quite restricted: + * Works on sockets only -- no support for other devices! + * A given socket can be in a read-select or a read/recv* by only + * one task at a time. + * A given socket can be in a write-select or a write/send* by only + * one task at a time. + * + * NOTE - select() is a very expensive system call. It should be avoided + * if at all possible. In many cases, rewriting the application + * to use multiple tasks (one per socket) is a better solution. + */ + +static __inline int imin(int a, int b) { return (a < b ? a : b); } + +static int +socket_select (struct socket *so, int which, rtems_id tid) +{ + switch (which) { + + case FREAD: + if (soreadable(so)) + return (1); + so->so_rcv.sb_sel.si_pid = tid; + break; + + case FWRITE: + if (sowriteable(so)) + return (1); + so->so_snd.sb_sel.si_pid = tid; + break; + + case 0: + if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) + return (1); + so->so_rcv.sb_sel.si_pid = tid; + break; + } + return (0); +} + +static int +selscan (rtems_id tid, fd_mask **ibits, fd_mask **obits, int nfd, int *retval) +{ + struct socket *so; + int msk, i, fd; + fd_mask bits, bit; + int n = 0; + static int flag[3] = { FREAD, FWRITE, 0 }; + + for (msk = 0; msk < 3; msk++) { + if (ibits[msk] == NULL) + continue; + for (i = 0; i < nfd; i += NFDBITS) { + bits = ibits[msk][i/NFDBITS]; + for (fd = i, bit = 1 ; bits && (fd < nfd) ; fd++, bit <<= 1) { + if ((bits & bit) == 0) + continue; + bits &= ~bit; + so = rtems_bsdnet_fdToSocket (fd); + if (so == NULL) + return (EBADF); + if (socket_select (so, flag[msk], tid)) { + obits[msk][fd/NFDBITS] |= + (1 << (fd % NFDBITS)); + n++; + } + } + } + } + *retval = n; + return (0); +} + +int +select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *tv) +{ + fd_mask *ibits[3], *obits[3]; + fd_set ob[3]; + int error, timo; + int retval; + rtems_id tid; + rtems_interval then, now; + rtems_event_set events; + + if (nfds < 0) + return (EINVAL); + if (tv) { + timo = tv->tv_sec * hz + tv->tv_usec / tick; + if (timo == 0) + timo = 1; + rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then); + } + else { + timo = 0; + } + +#define getbits(name,i) if (name) { \ + ibits[i] = &name->fds_bits[0]; \ + obits[i] = &ob[i].fds_bits[0]; \ + FD_ZERO(&ob[i]); \ + } \ + else ibits[i] = NULL + getbits (readfds, 0); + getbits (writefds, 1); + getbits (exceptfds, 2); +#undef getbits + + rtems_task_ident (RTEMS_SELF, 0, &tid); + rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events); + for (;;) { + rtems_bsdnet_semaphore_obtain (); + error = selscan(tid, ibits, obits, nfds, &retval); + rtems_bsdnet_semaphore_release (); + if (error || retval) + break; + if (timo) { + rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now); + timo -= now - then; + if (timo <= 0) + break; + then = now; + } + rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, timo, &events); + } + +#define putbits(name,i) if (name) *name = ob[i] + putbits (readfds, 0); + putbits (writefds, 1); + putbits (exceptfds, 2); +#undef putbits + if (error) { + errno = error; + retval = -1; + } + return (retval); +} diff --git a/c/src/lib/libnetworking/rtems/sghostname.c b/c/src/lib/libnetworking/rtems/sghostname.c index 36894caa86..307f045fbd 100644 --- a/c/src/lib/libnetworking/rtems/sghostname.c +++ b/c/src/lib/libnetworking/rtems/sghostname.c @@ -15,7 +15,7 @@ static char *rtems_hostname; int -gethostname (char *name, int namelen) +gethostname (char *name, size_t namelen) { char *cp = rtems_hostname; @@ -26,7 +26,7 @@ gethostname (char *name, int namelen) } int -sethostname (char *name, int namelen) +sethostname (char *name, size_t namelen) { char *old, *new; |