--- pth_high.c 2002/11/08 16:20:15 1.102
+++ pth_high.c 2002/11/08 19:12:13 1.103
@@ -297,28 +297,27 @@
pth_implicit_init();
pth_debug2("pth_select_ev: called from thread \"%s\"", pth_current->name);
- /* POSIX compliance */
+ /* POSIX.1-2001/SUSv3 compliance */
if (nfd < 0 || nfd > FD_SETSIZE)
return pth_error(-1, EINVAL);
if (timeout != NULL) {
if ( timeout->tv_sec < 0
- || timeout->tv_sec > 100000000 /* about 3 years */
|| timeout->tv_usec < 0
- || timeout->tv_usec >= 1000000 /* a full second */)
+ || timeout->tv_usec >= 1000000 /* a full second */)
return pth_error(-1, EINVAL);
+ if (timeout->tv_sec > 31*24*60*60)
+ timeout->tv_sec = 31*24*60*60;
}
/* first deal with the special situation of a plain microsecond delay */
if (nfd == 0 && rfds == NULL && wfds == NULL && efds == NULL && timeout != NULL) {
- if (timeout->tv_sec < 0 || timeout->tv_usec < 0)
- return pth_error(-1, EINVAL);
- if (timeout->tv_sec == 0 && timeout->tv_usec < 500000) {
+ if (timeout->tv_sec == 0 && timeout->tv_usec <= 10000 /* 1/100 second */) {
/* very small delays are acceptable to be performed directly */
while ( pth_sc(select)(0, NULL, NULL, NULL, timeout) < 0
&& errno == EINTR) ;
}
else {
- /* larger delays have to use the scheduler */
+ /* larger delays have to go through the scheduler */
ev = pth_event(PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key_timeout,
pth_timeout(timeout->tv_sec, timeout->tv_usec));
if (ev_extra != NULL)
@@ -330,58 +329,57 @@
return pth_error(-1, EINTR);
}
}
- /* POSIX compliance */
+ /* POSIX.1-2001/SUSv3 compliance */
if (rfds != NULL) FD_ZERO(rfds);
if (wfds != NULL) FD_ZERO(wfds);
if (efds != NULL) FD_ZERO(efds);
return 0;
}
- /* now directly poll filedescriptor sets to avoid unneccessary
+ /* now directly poll filedescriptor sets to avoid unnecessary
(and resource consuming because of context switches, etc) event
handling through the scheduler. We've to be carefully here, because not
- all platforms guarranty us that the sets are unmodified if an error
- or timeout occured. */
+ all platforms guaranty us that the sets are unmodified if an error
+ or timeout occurred. */
delay.tv_sec = 0;
delay.tv_usec = 0;
rtmp = NULL;
if (rfds != NULL) {
- rspare = *rfds;
+ memcpy(&rspare, rfds, sizeof(fd_set));
rtmp = &rspare;
}
wtmp = NULL;
if (wfds != NULL) {
- wspare = *wfds;
+ memcpy(&wspare, wfds, sizeof(fd_set));
wtmp = &wspare;
}
etmp = NULL;
if (efds != NULL) {
- espare = *efds;
+ memcpy(&espare, efds, sizeof(fd_set));
etmp = &espare;
}
- while ((rc = pth_sc(select)(nfd, rtmp, wtmp, etmp, &delay)) < 0 && errno == EINTR) ;
- if (rc > 0) {
+ while ((rc = pth_sc(select)(nfd, rtmp, wtmp, etmp, &delay)) < 0
+ && errno == EINTR)
+ ;
+ if (rc < 0)
+ /* pass-through immediate error */
+ return pth_error(-1, errno);
+ else if ( rc > 0
+ || ( rc == 0
+ && timeout != NULL
+ && pth_time_cmp(timeout, PTH_TIME_ZERO) == 0)) {
+ /* pass-through immediate success */
if (rfds != NULL)
- *rfds = rspare;
+ memcpy(rfds, &rspare, sizeof(fd_set));
if (wfds != NULL)
- *wfds = wspare;
+ memcpy(wfds, &wspare, sizeof(fd_set));
if (efds != NULL)
- *efds = espare;
+ memcpy(efds, &espare, sizeof(fd_set));
return rc;
}
- if (rc == 0 && timeout != NULL) {
- if (pth_time_cmp(timeout, PTH_TIME_ZERO) == 0) {
- /* POSIX compliance */
- if (rfds != NULL) FD_ZERO(rfds);
- if (wfds != NULL) FD_ZERO(wfds);
- if (efds != NULL) FD_ZERO(efds);
- return 0;
- }
- }
- if (rc < 0 && (errno == EINVAL || errno == EBADF))
- return pth_error(-1, errno);
- /* suspend current thread until one fd is ready or the timeout occurred */
+ /* suspend current thread until one filedescriptor
+ is ready or the timeout occurred */
rc = -1;
ev = ev_select = pth_event(PTH_EVENT_SELECT|PTH_MODE_STATIC,
&ev_key_select, &rc, nfd, rfds, wfds, efds);
@@ -394,25 +392,29 @@
if (ev_extra != NULL)
pth_event_concat(ev, ev_extra, NULL);
pth_wait(ev);
+ if (ev_extra != NULL)
+ pth_event_isolate(ev_extra);
+ if (timeout != NULL)
+ pth_event_isolate(ev_timeout);
+
+ /* select return code semantics */
+ if (pth_event_status(ev_select) == PTH_STATUS_FAILED)
+ return pth_error(-1, EBADF);
selected = FALSE;
- pth_event_isolate(ev_select);
if (pth_event_status(ev_select) == PTH_STATUS_OCCURRED)
selected = TRUE;
- if (timeout != NULL) {
- pth_event_isolate(ev_timeout);
- if (pth_event_status(ev_timeout) == PTH_STATUS_OCCURRED) {
- selected = TRUE;
- /* POSIX compliance */
- if (rfds != NULL) FD_ZERO(rfds);
- if (wfds != NULL) FD_ZERO(wfds);
- if (efds != NULL) FD_ZERO(efds);
- rc = 0;
- }
+ if ( timeout != NULL
+ && pth_event_status(ev_timeout) == PTH_STATUS_OCCURRED) {
+ selected = TRUE;
+ /* POSIX.1-2001/SUSv3 compliance */
+ if (rfds != NULL) FD_ZERO(rfds);
+ if (wfds != NULL) FD_ZERO(wfds);
+ if (efds != NULL) FD_ZERO(efds);
+ rc = 0;
}
- if (pth_event_status(ev_select) == PTH_STATUS_FAILED)
- return pth_error(-1, EBADF);
if (ev_extra != NULL && !selected)
return pth_error(-1, EINTR);
+
return rc;
}
|