Use select() from FreeBSD

This commit is contained in:
Sebastian Huber 2013-10-23 16:10:26 +02:00
parent 0967858024
commit facf9dcea6
4 changed files with 129 additions and 26 deletions

View File

@ -94,9 +94,7 @@ static int pollrescan(struct thread *);
#endif /* __rtems__ */ #endif /* __rtems__ */
static int selscan(struct thread *, fd_mask **, fd_mask **, int); static int selscan(struct thread *, fd_mask **, fd_mask **, int);
static int selrescan(struct thread *, fd_mask **, fd_mask **); static int selrescan(struct thread *, fd_mask **, fd_mask **);
#ifndef __rtems__
static void selfdalloc(struct thread *, void *); static void selfdalloc(struct thread *, void *);
#endif /* __rtems__ */
static void selfdfree(struct seltd *, struct selfd *); static void selfdfree(struct seltd *, struct selfd *);
#ifndef __rtems__ #ifndef __rtems__
static int dofileread(struct thread *, int, struct file *, struct uio *, static int dofileread(struct thread *, int, struct file *, struct uio *,
@ -851,9 +849,7 @@ int
kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou, kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou,
fd_set *fd_ex, struct timeval *tvp, int abi_nfdbits) fd_set *fd_ex, struct timeval *tvp, int abi_nfdbits)
{ {
#ifndef __rtems__
struct filedesc *fdp; struct filedesc *fdp;
#endif /* __rtems__ */
/* /*
* The magic 2048 here is chosen to be just enough for FD_SETSIZE * The magic 2048 here is chosen to be just enough for FD_SETSIZE
* infds with the new FD_SETSIZE of 1024, and more than enough for * infds with the new FD_SETSIZE of 1024, and more than enough for
@ -866,10 +862,6 @@ kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou,
int error, timo; int error, timo;
u_int nbufbytes, ncpbytes, ncpubytes, nfdbits; u_int nbufbytes, ncpbytes, ncpubytes, nfdbits;
#ifdef __rtems__
if (td == NULL)
return (ENOMEM);
#endif /* __rtems__ */
if (nd < 0) if (nd < 0)
return (EINVAL); return (EINVAL);
#ifndef __rtems__ #ifndef __rtems__
@ -877,6 +869,7 @@ kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou,
if (nd > fdp->fd_lastfile + 1) if (nd > fdp->fd_lastfile + 1)
nd = fdp->fd_lastfile + 1; nd = fdp->fd_lastfile + 1;
#else /* __rtems__ */ #else /* __rtems__ */
(void) fdp;
if (nd > rtems_libio_number_iops) if (nd > rtems_libio_number_iops)
nd = rtems_libio_number_iops; nd = rtems_libio_number_iops;
#endif /* __rtems__ */ #endif /* __rtems__ */
@ -1019,12 +1012,18 @@ done:
} }
#ifdef __rtems__ #ifdef __rtems__
int int
select(int nfds, fd_set *restrict readfds, fd_set *__restrict writefds, fd_set select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds,
*__restrict errorfds, struct timeval *__restrict timeout) struct timeval *timeout)
{ {
struct thread *td = rtems_bsd_get_curthread_or_null(); struct thread *td = rtems_bsd_get_curthread_or_null();
int error = kern_select(td, nfds, readfds, writefds, errorfds, timeout, int error;
NFDBITS);
if (td != NULL) {
error = kern_select(td, nfds, readfds, writefds, errorfds,
timeout, NFDBITS);
} else {
error = ENOMEM;
}
if (error == 0) { if (error == 0) {
return td->td_retval[0]; return td->td_retval[0];
@ -1033,7 +1032,7 @@ select(int nfds, fd_set *restrict readfds, fd_set *__restrict writefds, fd_set
} }
} }
#endif /* __rtems__ */ #endif /* __rtems__ */
#ifndef __rtems__
/* /*
* Convert a select bit set to poll flags. * Convert a select bit set to poll flags.
* *
@ -1099,7 +1098,6 @@ selsetbits(fd_mask **ibits, fd_mask **obits, int idx, fd_mask bit, int events)
return (n); return (n);
} }
#endif /* __rtems__ */
/* /*
* Traverse the list of fds attached to this thread's seltd and check for * Traverse the list of fds attached to this thread's seltd and check for
@ -1108,7 +1106,6 @@ selsetbits(fd_mask **ibits, fd_mask **obits, int idx, fd_mask bit, int events)
static int static int
selrescan(struct thread *td, fd_mask **ibits, fd_mask **obits) selrescan(struct thread *td, fd_mask **ibits, fd_mask **obits)
{ {
#ifndef __rtems__
struct filedesc *fdp; struct filedesc *fdp;
struct selinfo *si; struct selinfo *si;
struct seltd *stp; struct seltd *stp;
@ -1118,7 +1115,11 @@ selrescan(struct thread *td, fd_mask **ibits, fd_mask **obits)
fd_mask bit; fd_mask bit;
int fd, ev, n, idx; int fd, ev, n, idx;
#ifndef __rtems__
fdp = td->td_proc->p_fd; fdp = td->td_proc->p_fd;
#else /* __rtems__ */
fdp = NULL;
#endif /* __rtems__ */
stp = td->td_sel; stp = td->td_sel;
n = 0; n = 0;
STAILQ_FOREACH_SAFE(sfp, &stp->st_selq, sf_link, sfn) { STAILQ_FOREACH_SAFE(sfp, &stp->st_selq, sf_link, sfn) {
@ -1140,9 +1141,6 @@ selrescan(struct thread *td, fd_mask **ibits, fd_mask **obits)
stp->st_flags = 0; stp->st_flags = 0;
td->td_retval[0] = n; td->td_retval[0] = n;
return (0); return (0);
#else /* __rtems__ */
return (ENOMEM);
#endif /* __rtems__ */
} }
/* /*
@ -1155,14 +1153,17 @@ selscan(td, ibits, obits, nfd)
fd_mask **ibits, **obits; fd_mask **ibits, **obits;
int nfd; int nfd;
{ {
#ifndef __rtems__
struct filedesc *fdp; struct filedesc *fdp;
struct file *fp; struct file *fp;
fd_mask bit; fd_mask bit;
int ev, flags, end, fd; int ev, flags, end, fd;
int n, idx; int n, idx;
#ifndef __rtems__
fdp = td->td_proc->p_fd; fdp = td->td_proc->p_fd;
#else /* __rtems__ */
fdp = NULL;
#endif /* __rtems__ */
n = 0; n = 0;
for (idx = 0, fd = 0; fd < nfd; idx++) { for (idx = 0, fd = 0; fd < nfd; idx++) {
end = imin(fd + NFDBITS, nfd); end = imin(fd + NFDBITS, nfd);
@ -1183,9 +1184,6 @@ selscan(td, ibits, obits, nfd)
td->td_retval[0] = n; td->td_retval[0] = n;
return (0); return (0);
#else /* __rtems__ */
return (ENOMEM);
#endif /* __rtems__ */
} }
#ifndef __rtems__ #ifndef __rtems__
@ -1466,6 +1464,7 @@ selsocket(struct socket *so, int events, struct timeval *tvp, struct thread *td)
error = 0; error = 0;
return (error); return (error);
} }
#endif /* __rtems__ */
/* /*
* Preallocate two selfds associated with 'cookie'. Some fo_poll routines * Preallocate two selfds associated with 'cookie'. Some fo_poll routines
@ -1486,7 +1485,6 @@ selfdalloc(struct thread *td, void *cookie)
stp->st_free2->sf_td = stp; stp->st_free2->sf_td = stp;
stp->st_free2->sf_cookie = cookie; stp->st_free2->sf_cookie = cookie;
} }
#endif /* __rtems__ */
static void static void
selfdfree(struct seltd *stp, struct selfd *sfp) selfdfree(struct seltd *stp, struct selfd *sfp)

View File

@ -325,7 +325,9 @@ rtems_bsd_soo_ioctl(rtems_libio_t *iop, ioctl_command_t request, void *buffer)
} }
#endif /* __rtems__ */ #endif /* __rtems__ */
#ifndef __rtems__ #ifdef __rtems__
static
#endif /* __rtems__ */
int int
soo_poll(struct file *fp, int events, struct ucred *active_cred, soo_poll(struct file *fp, int events, struct ucred *active_cred,
struct thread *td) struct thread *td)
@ -338,7 +340,27 @@ soo_poll(struct file *fp, int events, struct ucred *active_cred,
if (error) if (error)
return (error); return (error);
#endif #endif
#ifndef __rtems__
return (sopoll(so, events, fp->f_cred, td)); return (sopoll(so, events, fp->f_cred, td));
#else /* __rtems__ */
return (sopoll(so, events, NULL, td));
#endif /* __rtems__ */
}
#ifdef __rtems__
static int
rtems_bsd_soo_poll(rtems_libio_t *iop, int events)
{
struct thread *td = rtems_bsd_get_curthread_or_null();
struct file *fp = rtems_bsd_iop_to_fp(iop);
int error;
if (td != NULL) {
error = soo_poll(fp, events, NULL, td);
} else {
error = ENOMEM;
}
return error;
} }
#endif /* __rtems__ */ #endif /* __rtems__ */
@ -451,6 +473,7 @@ const rtems_filesystem_file_handlers_r socketops = {
.ftruncate_h = rtems_filesystem_default_ftruncate, .ftruncate_h = rtems_filesystem_default_ftruncate,
.fsync_h = rtems_filesystem_default_fsync_or_fdatasync, .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
.fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync, .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
.fcntl_h = rtems_filesystem_default_fcntl .fcntl_h = rtems_filesystem_default_fcntl,
.poll_h = rtems_bsd_soo_poll
}; };
#endif /* __rtems__ */ #endif /* __rtems__ */

View File

@ -408,7 +408,6 @@ fo_ioctl(fp, com, data, active_cred, td)
#endif /* __rtems__ */ #endif /* __rtems__ */
} }
#ifndef __rtems__
static __inline int static __inline int
fo_poll(fp, events, active_cred, td) fo_poll(fp, events, active_cred, td)
struct file *fp; struct file *fp;
@ -417,9 +416,17 @@ fo_poll(fp, events, active_cred, td)
struct thread *td; struct thread *td;
{ {
#ifndef __rtems__
return ((*fp->f_ops->fo_poll)(fp, events, active_cred, td)); return ((*fp->f_ops->fo_poll)(fp, events, active_cred, td));
#else /* __rtems__ */
(void) active_cred;
(void) td;
return ((*fp->f_io.pathinfo.handlers->poll_h)(&fp->f_io, events));
#endif /* __rtems__ */
} }
#ifndef __rtems__
static __inline int static __inline int
fo_stat(fp, sb, active_cred, td) fo_stat(fp, sb, active_cred, td)
struct file *fp; struct file *fp;

View File

@ -32,6 +32,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/filio.h> #include <sys/filio.h>
#include <netinet/in.h> #include <netinet/in.h>
@ -1206,6 +1207,79 @@ test_socket_recv_and_recvfrom_and_recvmsg(void)
assert(rtems_resource_snapshot_check(&snapshot)); assert(rtems_resource_snapshot_check(&snapshot));
} }
static void
no_mem_socket_select(int fd)
{
struct fd_set set;
int nfds;
int rv;
FD_ZERO(&set);
FD_SET(fd, &set);
nfds = fd + 1;
errno = 0;
rv = select(nfds, &set, NULL, NULL, NULL);
assert(rv == -1);
assert(errno == ENOMEM);
}
static void
test_socket_select(void)
{
rtems_resource_snapshot snapshot;
struct fd_set set;
int nfds;
int sd;
int rv;
puts("test socket select");
sd = socket(PF_INET, SOCK_DGRAM, 0);
assert(sd >= 0);
rv = close(sd);
assert(rv == 0);
FD_ZERO(&set);
FD_SET(sd, &set);
nfds = sd + 1;
errno = 0;
rv = select(nfds, &set, NULL, NULL, NULL);
assert(rv == -1);
assert(errno == EBADF);
rtems_resource_snapshot_take(&snapshot);
sd = socket(PF_INET, SOCK_DGRAM, 0);
assert(sd >= 0);
do_no_mem_test(no_mem_socket_select, sd);
FD_ZERO(&set);
nfds = -1;
errno = 0;
rv = select(nfds, &set, NULL, NULL, NULL);
assert(rv == -1);
assert(errno == EINVAL);
rv = close(sd);
assert(rv == 0);
FD_ZERO(&set);
FD_SET(sd, &set);
nfds = sd + 1;
errno = 0;
rv = select(nfds, &set, NULL, NULL, NULL);
assert(rv == -1);
assert(errno == EBADF);
assert(rtems_resource_snapshot_check(&snapshot));
}
static const char prog_name[] = "prog"; static const char prog_name[] = "prog";
static int static int
@ -1412,6 +1486,7 @@ test_main(void)
test_socket_read_and_write(); test_socket_read_and_write();
test_socket_send_and_sendto_and_sendmsg(); test_socket_send_and_sendto_and_sendmsg();
test_socket_recv_and_recvfrom_and_recvmsg(); test_socket_recv_and_recvfrom_and_recvmsg();
test_socket_select();
test_bsd_program(); test_bsd_program();
test_warn(); test_warn();