diff options
-rw-r--r-- | otherlibs/unix/select.c | 54 |
1 files changed, 30 insertions, 24 deletions
diff --git a/otherlibs/unix/select.c b/otherlibs/unix/select.c index 8923e130f..e512b3043 100644 --- a/otherlibs/unix/select.c +++ b/otherlibs/unix/select.c @@ -31,25 +31,28 @@ typedef fd_set file_descr_set; -static void fdlist_to_fdset(value fdlist, file_descr_set *fdset) +static void fdlist_to_fdset(value fdlist, fd_set *fdset, int *maxfd) { value l; FD_ZERO(fdset); for (l = fdlist; l != Val_int(0); l = Field(l, 1)) { - FD_SET(Int_val(Field(l, 0)), fdset); + int fd = Int_val(Field(l, 0)); + FD_SET(fd, fdset); + if (fd > *maxfd) *maxfd = fd; } } -static value fdset_to_fdlist(file_descr_set *fdset) +static value fdset_to_fdlist(value fdlist, fd_set *fdset) { - int i; + value l; value res = Val_int(0); - Begin_root(res); - for (i = FD_SETSIZE - 1; i >= 0; i--) { - if (FD_ISSET(i, fdset)) { + Begin_roots2(l, res); + for (l = fdlist; l != Val_int(0); l = Field(l, 1)) { + int fd = Int_val(Field(l, 0)); + if (FD_ISSET(fd, fdset)) { value newres = alloc_small(2, 0); - Field(newres, 0) = Val_int(i); + Field(newres, 0) = Val_int(fd); Field(newres, 1) = res; res = newres; } @@ -58,46 +61,49 @@ static value fdset_to_fdlist(file_descr_set *fdset) return res; } -CAMLprim value unix_select(value readfds, value writefds, value exceptfds, value timeout) +CAMLprim value unix_select(value readfds, value writefds, value exceptfds, + value timeout) { - file_descr_set read, write, except; + fd_set read, write, except; + int maxfd; double tm; struct timeval tv; struct timeval * tvp; int retcode; value res; - value read_list = Val_unit, write_list = Val_unit, except_list = Val_unit; - Begin_roots3 (read_list, write_list, except_list); - fdlist_to_fdset(readfds, &read); - fdlist_to_fdset(writefds, &write); - fdlist_to_fdset(exceptfds, &except); + Begin_roots3 (readfds, writefds, exceptfds); + maxfd = 0; + fdlist_to_fdset(readfds, &read, &maxfd); + fdlist_to_fdset(writefds, &write, &maxfd); + fdlist_to_fdset(exceptfds, &except, &maxfd); tm = Double_val(timeout); if (tm < 0.0) tvp = (struct timeval *) NULL; else { tv.tv_sec = (int) tm; - tv.tv_usec = (int) (1e6 * (tm - (int) tm)); + tv.tv_usec = (int) (1e6 * (tm - tv.tv_sec)); tvp = &tv; } enter_blocking_section(); - retcode = select(FD_SETSIZE, &read, &write, &except, tvp); + retcode = select(maxfd, &read, &write, &except, tvp); leave_blocking_section(); if (retcode == -1) uerror("select", Nothing); - read_list = fdset_to_fdlist(&read); - write_list = fdset_to_fdlist(&write); - except_list = fdset_to_fdlist(&except); + readfds = fdset_to_fdlist(readfds, &read); + writefds = fdset_to_fdlist(writefds, &write); + exceptfds = fdset_to_fdlist(exceptfds, &except); res = alloc_small(3, 0); - Field(res, 0) = read_list; - Field(res, 1) = write_list; - Field(res, 2) = except_list; + Field(res, 0) = readfds; + Field(res, 1) = writefds; + Field(res, 2) = exceptfds; End_roots(); return res; } #else -CAMLprim value unix_select(value readfds, value writefds, value exceptfds, value timeout) +CAMLprim value unix_select(value readfds, value writefds, value exceptfds, + value timeout) { invalid_argument("select not implemented"); } #endif |