Index: ossp-pkg/pth/ChangeLog RCS File: /v/ossp/cvs/ossp-pkg/pth/ChangeLog,v rcsdiff -q -kk '-r1.587' '-r1.588' -u '/v/ossp/cvs/ossp-pkg/pth/ChangeLog,v' 2>/dev/null --- ChangeLog 2002/11/03 19:06:19 1.587 +++ ChangeLog 2002/11/05 19:39:08 1.588 @@ -21,6 +21,26 @@ Changes between 1.4.1 and 1.5.0 (27-Jan-2002 to xx-Nov-2002) + *) Use the new PTH_STATUS_FAILED event status in the scheduler's + event-manager for filedescriptor events if the internal select(2) + call returned with an error. Additionally this PTH_STATUS_FAILED + is recognized by the high-level API functions (pth_select, etc) + and produce the necessary POSIX conforming return codes (usually + -1 and errno == EBADF). + [Ralf S. Engelschall, Thanh Luu ] + + *) The function "int pth_event_occurred(pth_event_t)" was replaced + with "pth_status_t pth_event_status(pth_event_t)" where pth_status_t + can have values of PTH_STATUS_PENDING (replacing the old FALSE return + value of pth_event_occurred), PTH_STATUS_OCCURRED (replacing + the old TRUE return value of pth_event_occurred), and + PTH_STATUS_FAILED (a new return value indicating an error in + processing the event). This was scheduler/event-manager errors can + be indicated which happended while processing the event. For + backward compatibility reasons, a macro pth_event_occurred() was + added. This will be removed soon. + [Ralf S. Engelschall] + *) Upgraded to latest version of the OSSP Autoconf macro AC_CHECK_EXTLIB in order to fix problems with the current Autoconf 2.54 environment. Index: ossp-pkg/pth/pth.h.in RCS File: /v/ossp/cvs/ossp-pkg/pth/pth.h.in,v rcsdiff -q -kk '-r1.137' '-r1.138' -u '/v/ossp/cvs/ossp-pkg/pth/pth.h.in,v' 2>/dev/null --- pth.h.in 2002/11/03 16:31:34 1.137 +++ pth.h.in 2002/11/05 19:39:09 1.138 @@ -209,6 +209,13 @@ #define PTH_WALK_NEXT _BIT(1) #define PTH_WALK_PREV _BIT(2) + /* event status codes */ +typedef enum { + PTH_STATUS_PENDING, + PTH_STATUS_OCCURRED, + PTH_STATUS_FAILED +} pth_status_t; + /* the key type and init value */ typedef int pth_key_t; #define PTH_KEY_INIT (-1) @@ -447,7 +454,7 @@ extern pth_event_t pth_event_concat(pth_event_t, ...); extern pth_event_t pth_event_isolate(pth_event_t); extern pth_event_t pth_event_walk(pth_event_t, unsigned int); -extern int pth_event_occurred(pth_event_t); +extern pth_status_t pth_event_status(pth_event_t); extern int pth_event_free(pth_event_t, int); /* key-based storage functions */ @@ -564,5 +571,10 @@ #define pwrite pth_pwrite #endif + /* backward compatibility (Pth < 1.5.0) */ +#define pth_event_occurred(ev) \ + ( pth_event_status(ev) == PTH_STATUS_OCCURRED \ + || pth_event_status(ev) == PTH_STATUS_FAILED ) + #endif /* _PTH_H_ */ Index: ossp-pkg/pth/pth.pod RCS File: /v/ossp/cvs/ossp-pkg/pth/pth.pod,v rcsdiff -q -kk '-r1.159' '-r1.160' -u '/v/ossp/cvs/ossp-pkg/pth/pth.pod,v' 2>/dev/null --- pth.pod 2002/11/03 11:15:04 1.159 +++ pth.pod 2002/11/05 19:39:09 1.160 @@ -93,7 +93,7 @@ pth_event_concat, pth_event_isolate, pth_event_walk, -pth_event_occurred, +pth_event_status, pth_event_free. =item B @@ -970,11 +970,12 @@ This is the link between the scheduler and the event facility (see below for the various pth_event_xxx() functions). It's modeled like select(2), i.e., one gives this function one or more events (in the event ring specified by I) -on which the current thread wants to wait. The scheduler awakes the thread -when one ore more of them occurred after tagging them as occurred. The I -argument is a I to an event ring which isn't changed except for the -tagging. pth_wait(3) returns the number of occurred events and the application -can use pth_event_occurred(3) to test which events occurred. +on which the current thread wants to wait. The scheduler awakes the +thread when one ore more of them occurred or failed after tagging +them as such. The I argument is a I to an event ring +which isn't changed except for the tagging. pth_wait(3) returns the +number of occurred or failed events and the application can use +pth_event_status(3) to test which events occurred or failed. =item int B(pth_t I); @@ -1236,12 +1237,15 @@ OR-ed into I to walk to the next/previous occurred event in the ring I. -=item int B(pth_event_t I); +=item pth_status_t B(pth_event_t I); -This checks whether the event I occurred. This is a fast operation because -only a tag on I is checked which was either set or still not set by the -scheduler. In other words: This doesn't check the event itself, it just checks -the last knowledge of the scheduler. +This returns the status of event I. This is a fast operation +because only a tag on I is checked which was either set or still +not set by the scheduler. In other words: This doesn't check the +event itself, it just checks the last knowledge of the scheduler. The +possible returned status codes are: C (event is +still pending), C (event successfully occurred), +C (event failed). =item int B(pth_event_t I, int I); Index: ossp-pkg/pth/pth_event.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_event.c,v rcsdiff -q -kk '-r1.59' '-r1.60' -u '/v/ossp/cvs/ossp-pkg/pth/pth_event.c,v' 2>/dev/null --- pth_event.c 2002/10/24 15:21:13 1.59 +++ pth_event.c 2002/11/05 19:39:09 1.60 @@ -34,7 +34,7 @@ struct pth_event_st { struct pth_event_st *ev_next; struct pth_event_st *ev_prev; - int ev_occurred; + pth_status_t ev_status; int ev_type; int ev_goal; union { @@ -108,7 +108,7 @@ } /* initialize common ingredients */ - ev->ev_occurred = FALSE; + ev->ev_status = PTH_STATUS_PENDING; /* initialize event specific ingredients */ if (spec & PTH_EVENT_FD) { @@ -330,12 +330,12 @@ return ring; } -/* determine whether the event is occurred */ -int pth_event_occurred(pth_event_t ev) +/* determine status of the event */ +pth_status_t pth_event_status(pth_event_t ev) { if (ev == NULL) return pth_error(FALSE, EINVAL); - return ev->ev_occurred; + return ev->ev_status; } /* walk to next or previous event in an event ring */ @@ -350,7 +350,7 @@ ev = ev->ev_prev; else return pth_error((pth_event_t)NULL, EINVAL); - } while ((direction & PTH_UNTIL_OCCURRED) && !(ev->ev_occurred)); + } while ((direction & PTH_UNTIL_OCCURRED) && (ev->ev_status != PTH_STATUS_OCCURRED)); return ev; } @@ -381,7 +381,7 @@ /* wait for one or more events */ int pth_wait(pth_event_t ev_ring) { - int occurred; + int nonpending; pth_event_t ev; /* at least a waiting ring is required */ @@ -389,10 +389,10 @@ return pth_error(-1, EINVAL); pth_debug2("pth_wait: enter from thread \"%s\"", pth_current->name); - /* mark all events in waiting ring as still not occurred */ + /* mark all events in waiting ring as still pending */ ev = ev_ring; do { - ev->ev_occurred = FALSE; + ev->ev_status = PTH_STATUS_PENDING; pth_debug2("pth_wait: waiting on event 0x%lx", (unsigned long)ev); ev = ev->ev_next; } while (ev != ev_ring); @@ -411,19 +411,19 @@ /* unlink event ring from current thread */ pth_current->events = NULL; - /* count number of actually occurred events */ + /* count number of actually occurred (or failed) events */ ev = ev_ring; - occurred = 0; + nonpending = 0; do { - if (ev->ev_occurred) { - pth_debug2("pth_wait: occurred event 0x%lx", (unsigned long)ev); - occurred++; + if (ev->ev_status != PTH_STATUS_PENDING) { + pth_debug2("pth_wait: non-pending event 0x%lx", (unsigned long)ev); + nonpending++; } ev = ev->ev_next; } while (ev != ev_ring); /* leave to current thread with number of occurred events */ pth_debug2("pth_wait: leave to thread \"%s\"", pth_current->name); - return occurred; + return nonpending; } Index: ossp-pkg/pth/pth_high.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_high.c,v rcsdiff -q -kk '-r1.94' '-r1.95' -u '/v/ossp/cvs/ossp-pkg/pth/pth_high.c,v' 2>/dev/null --- pth_high.c 2002/10/25 11:59:18 1.94 +++ pth_high.c 2002/11/05 19:39:09 1.95 @@ -172,7 +172,7 @@ pth_wait(ev); if (ev_extra != NULL) { pth_event_isolate(ev); - if (!pth_event_occurred(ev)) + if (pth_event_status(ev) != PTH_STATUS_OCCURRED) return pth_error(EINTR, EINTR); } @@ -326,7 +326,7 @@ pth_wait(ev); if (ev_extra != NULL) { pth_event_isolate(ev); - if (!pth_event_occurred(ev)) + if (pth_event_status(ev) != PTH_STATUS_OCCURRED) return pth_error(-1, EINTR); } } @@ -396,11 +396,11 @@ pth_wait(ev); selected = FALSE; pth_event_isolate(ev_select); - if (pth_event_occurred(ev_select)) + if (pth_event_status(ev_select) == PTH_STATUS_OCCURRED) selected = TRUE; if (timeout != NULL) { pth_event_isolate(ev_timeout); - if (pth_event_occurred(ev_timeout)) { + if (pth_event_status(ev_timeout) == PTH_STATUS_OCCURRED) { selected = TRUE; /* POSIX compliance */ if (rfds != NULL) FD_ZERO(rfds); @@ -409,6 +409,8 @@ 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; @@ -608,7 +610,7 @@ pth_wait(ev); if (ev_extra != NULL) { pth_event_isolate(ev); - if (!pth_event_occurred(ev)) + if (pth_event_status(ev) != PTH_STATUS_OCCURRED) return pth_error(-1, EINTR); } errlen = sizeof(err); @@ -663,7 +665,7 @@ /* check for the extra events */ if (ev_extra != NULL) { pth_event_isolate(ev); - if (!pth_event_occurred(ev)) { + if (pth_event_status(ev) != PTH_STATUS_OCCURRED) { pth_fdmode(s, fdmode); return pth_error(-1, EINTR); } @@ -727,7 +729,7 @@ n = pth_wait(ev); if (ev_extra != NULL) { pth_event_isolate(ev); - if (!pth_event_occurred(ev)) + if (pth_event_status(ev) != PTH_STATUS_OCCURRED) return pth_error(-1, EINTR); } } @@ -799,7 +801,7 @@ pth_wait(ev); if (ev_extra != NULL) { pth_event_isolate(ev); - if (!pth_event_occurred(ev)) { + if (pth_event_status(ev) != PTH_STATUS_OCCURRED) { pth_fdmode(fd, fdmode); return pth_error(-1, EINTR); } @@ -889,7 +891,7 @@ n = pth_wait(ev); if (ev_extra != NULL) { pth_event_isolate(ev); - if (!pth_event_occurred(ev)) + if (pth_event_status(ev) != PTH_STATUS_OCCURRED) return pth_error(-1, EINTR); } } @@ -1034,7 +1036,7 @@ pth_wait(ev); if (ev_extra != NULL) { pth_event_isolate(ev); - if (!pth_event_occurred(ev)) { + if (pth_event_status(ev) != PTH_STATUS_OCCURRED) { pth_fdmode(fd, fdmode); if (iovcnt > sizeof(tiov_stack)) free(tiov); @@ -1314,7 +1316,7 @@ n = pth_wait(ev); if (ev_extra != NULL) { pth_event_isolate(ev); - if (!pth_event_occurred(ev)) + if (pth_event_status(ev) != PTH_STATUS_OCCURRED) return pth_error(-1, EINTR); } } @@ -1402,7 +1404,7 @@ pth_wait(ev); if (ev_extra != NULL) { pth_event_isolate(ev); - if (!pth_event_occurred(ev)) { + if (pth_event_status(ev) != PTH_STATUS_OCCURRED) { pth_fdmode(fd, fdmode); return pth_error(-1, EINTR); } Index: ossp-pkg/pth/pth_sched.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_sched.c,v rcsdiff -q -kk '-r1.82' '-r1.83' -u '/v/ossp/cvs/ossp-pkg/pth/pth_sched.c,v' 2>/dev/null --- pth_sched.c 2002/11/03 11:15:05 1.82 +++ pth_sched.c 2002/11/05 19:39:09 1.83 @@ -368,7 +368,7 @@ } /* - * Look whether some events already occurred and move + * Look whether some events already occurred (or failed) and move * corresponding threads from waiting queue back to ready queue. */ intern void pth_sched_eventmanager(pth_time_t *now, int dopoll) @@ -441,7 +441,7 @@ /* ...check whether events occurred */ ev = evh = t->events; do { - if (!ev->ev_occurred) { + if (ev->ev_status == PTH_STATUS_PENDING) { this_occurred = FALSE; /* Filedescriptor I/O */ @@ -559,7 +559,7 @@ /* tag event if it has occurred */ if (this_occurred) { pth_debug2("pth_sched_eventmanager: [non-I/O] event occurred for thread \"%s\"", t->name); - ev->ev_occurred = TRUE; + ev->ev_status = PTH_STATUS_OCCURRED; any_occurred = TRUE; } } @@ -633,7 +633,7 @@ /* it was an explicit timer event, standing for its own */ pth_debug2("pth_sched_eventmanager: [timeout] event occurred for thread \"%s\"", nexttimer_thread->name); - nexttimer_ev->ev_occurred = TRUE; + nexttimer_ev->ev_status = PTH_STATUS_OCCURRED; } } @@ -655,6 +655,9 @@ additionally if a thread has one occurred event, we move it from the waiting queue to the ready queue */ + /* pre-configure a raw polling timeout for later checks (see below) */ + pth_time_set(&delay, PTH_TIME_ZERO); + /* for all threads in the waiting queue... */ t = pth_pqueue_head(&pth_WQ); while (t != NULL) { @@ -668,7 +671,7 @@ /* * Late handling for still not occured events */ - if (!ev->ev_occurred) { + if (ev->ev_status == PTH_STATUS_PENDING) { /* Filedescriptor I/O */ if (ev->ev_type == PTH_EVENT_FD) { if ( ( ev->ev_goal & PTH_UNTIL_FD_READABLE @@ -679,7 +682,33 @@ && FD_ISSET(ev->ev_args.FD.fd, &efds)) ) { pth_debug2("pth_sched_eventmanager: " "[I/O] event occurred for thread \"%s\"", t->name); - ev->ev_occurred = TRUE; + ev->ev_status = PTH_STATUS_OCCURRED; + } + else if (rc < 0) { + /* re-check particular filedescriptor */ + int rc2; + if (ev->ev_goal & PTH_UNTIL_FD_READABLE) + FD_SET(ev->ev_args.FD.fd, &rfds); + if (ev->ev_goal & PTH_UNTIL_FD_WRITEABLE) + FD_SET(ev->ev_args.FD.fd, &wfds); + if (ev->ev_goal & PTH_UNTIL_FD_EXCEPTION) + FD_SET(ev->ev_args.FD.fd, &efds); + while ((rc2 = pth_sc(select)(ev->ev_args.FD.fd+1, &rfds, &wfds, &efds, &delay)) < 0 + && errno == EINTR) ; + if (rc2 > 0) { + /* cleanup afterwards for next iteration */ + FD_CLR(ev->ev_args.FD.fd, &rfds); + FD_CLR(ev->ev_args.FD.fd, &wfds); + FD_CLR(ev->ev_args.FD.fd, &efds); + } else if (rc2 < 0) { + /* cleanup afterwards for next iteration */ + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&efds); + ev->ev_status = PTH_STATUS_FAILED; + pth_debug2("pth_sched_eventmanager: " + "[I/O] event failed for thread \"%s\"", t->name); + } } } /* Filedescriptor Set I/O */ @@ -694,10 +723,39 @@ ev->ev_args.SELECT.efds, &efds); if (ev->ev_args.SELECT.n != NULL) *(ev->ev_args.SELECT.n) = n; - ev->ev_occurred = TRUE; + ev->ev_status = PTH_STATUS_OCCURRED; pth_debug2("pth_sched_eventmanager: " "[I/O] event occurred for thread \"%s\"", t->name); } + else if (rc < 0) { + /* re-check particular filedescriptor set */ + int rc2; + fd_set *prfds = NULL; + fd_set *pwfds = NULL; + fd_set *pefds = NULL; + fd_set trfds; + fd_set twfds; + fd_set tefds; + if (ev->ev_args.SELECT.rfds) { + memcpy(&trfds, ev->ev_args.SELECT.rfds, sizeof(rfds)); + prfds = &trfds; + } + if (ev->ev_args.SELECT.wfds) { + memcpy(&twfds, ev->ev_args.SELECT.wfds, sizeof(wfds)); + pwfds = &twfds; + } + if (ev->ev_args.SELECT.efds) { + memcpy(&tefds, ev->ev_args.SELECT.efds, sizeof(efds)); + pefds = &tefds; + } + while ((rc2 = pth_sc(select)(ev->ev_args.SELECT.nfd+1, prfds, pwfds, pefds, &delay)) < 0 + && errno == EINTR) ; + if (rc2 < 0) { + ev->ev_status = PTH_STATUS_FAILED; + pth_debug2("pth_sched_eventmanager: " + "[I/O] event failed for thread \"%s\"", t->name); + } + } } /* Signal Set */ else if (ev->ev_type == PTH_EVENT_SIGS) { @@ -709,7 +767,7 @@ pth_debug2("pth_sched_eventmanager: " "[signal] event occurred for thread \"%s\"", t->name); sigdelset(&pth_sigraised, sig); - ev->ev_occurred = TRUE; + ev->ev_status = PTH_STATUS_OCCURRED; } } } @@ -731,7 +789,7 @@ } /* local to global mapping */ - if (ev->ev_occurred) + if (ev->ev_status != PTH_STATUS_PENDING) any_occurred = TRUE; } while ((ev = ev->ev_next) != evh); } Index: ossp-pkg/pth/pth_sync.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_sync.c,v rcsdiff -q -kk '-r1.37' '-r1.38' -u '/v/ossp/cvs/ossp-pkg/pth/pth_sync.c,v' 2>/dev/null --- pth_sync.c 2002/10/24 15:21:14 1.37 +++ pth_sync.c 2002/11/05 19:39:09 1.38 @@ -86,7 +86,7 @@ pth_wait(ev); if (ev_extra != NULL) { pth_event_isolate(ev); - if (!pth_event_occurred(ev)) + if (pth_event_status(ev) == PTH_STATUS_PENDING) return pth_error(FALSE, EINTR); } if (!(mutex->mx_state & PTH_MUTEX_LOCKED)) Index: ossp-pkg/pth/pthread.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pthread.c,v rcsdiff -q -kk '-r1.61' '-r1.62' -u '/v/ossp/cvs/ossp-pkg/pth/pthread.c,v' 2>/dev/null --- pthread.c 2002/10/24 15:21:14 1.61 +++ pthread.c 2002/11/05 19:39:09 1.62 @@ -1018,7 +1018,7 @@ ); if (!pth_cond_await((pth_cond_t *)(*cond), (pth_mutex_t *)(*mutex), ev)) return errno; - if (pth_event_occurred(ev)) + if (pth_event_status(ev) == PTH_STATUS_OCCURRED) return ETIMEDOUT; return OK; } Index: ossp-pkg/pth/test_mp.c RCS File: /v/ossp/cvs/ossp-pkg/pth/test_mp.c,v rcsdiff -q -kk '-r1.41' '-r1.42' -u '/v/ossp/cvs/ossp-pkg/pth/test_mp.c,v' 2>/dev/null --- test_mp.c 2002/11/03 09:24:42 1.41 +++ test_mp.c 2002/11/05 19:39:09 1.42 @@ -143,7 +143,7 @@ else evt = pth_event(PTH_EVENT_TIME|PTH_MODE_REUSE, evt, pth_timeout(20,0)); n = pth_readline_ev(STDIN_FILENO, caLine, MAXLINELEN, evt); - if (n == -1 && pth_event_occurred(evt)) { + if (n == -1 && pth_event_status(evt) == PTH_STATUS_OCCURRED) { fprintf(stderr, "main: Hey, what are you waiting for? Type in something!\n"); continue; }