OSSP CVS Repository

ossp - Check-in [2742]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 2742
Date: 2002-Nov-05 20:39:08 (local)
2002-Nov-05 19:39:08 (UTC)
User:rse
Branch:
Comment: 1. 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.

2. 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).

Parts submitted by: Thanh Luu <tluu@synapcity.com>

Tickets:
Inspections:
Files:
ossp-pkg/pth/ChangeLog      1.587 -> 1.588     20 inserted, 0 deleted
ossp-pkg/pth/pth.h.in      1.137 -> 1.138     13 inserted, 1 deleted
ossp-pkg/pth/pth.pod      1.159 -> 1.160     15 inserted, 11 deleted
ossp-pkg/pth/pth_event.c      1.59 -> 1.60     15 inserted, 15 deleted
ossp-pkg/pth/pth_high.c      1.94 -> 1.95     14 inserted, 12 deleted
ossp-pkg/pth/pth_sched.c      1.82 -> 1.83     67 inserted, 9 deleted
ossp-pkg/pth/pth_sync.c      1.37 -> 1.38     1 inserted, 1 deleted
ossp-pkg/pth/pthread.c      1.61 -> 1.62     1 inserted, 1 deleted
ossp-pkg/pth/test_mp.c      1.41 -> 1.42     1 inserted, 1 deleted

ossp-pkg/pth/ChangeLog 1.587 -> 1.588

--- 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 <tluu@synapcity.com>]
+
+   *) 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.


ossp-pkg/pth/pth.h.in 1.137 -> 1.138

--- 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_ */
 


ossp-pkg/pth/pth.pod 1.159 -> 1.160

--- 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<Key-Based Storage>
@@ -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<ev>)
-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<ev>
-argument is a I<pointer> 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<ev> argument is a I<pointer> 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_cancel>(pth_t I<tid>);
 
@@ -1236,12 +1237,15 @@
 OR-ed into I<direction> to walk to the next/previous occurred event in the
 ring I<ev>.
 
-=item int B<pth_event_occurred>(pth_event_t I<ev>);
+=item pth_status_t B<pth_event_status>(pth_event_t I<ev>);
 
-This checks whether the event I<ev> occurred. This is a fast operation because
-only a tag on I<ev> 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<ev>. This is a fast operation
+because only a tag on I<ev> 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<PTH_STATUS_PENDING> (event is
+still pending), C<PTH_STATUS_OCCURRED> (event successfully occurred),
+C<PTH_STATUS_FAILED> (event failed).
 
 =item int B<pth_event_free>(pth_event_t I<ev>, int I<mode>);
 


ossp-pkg/pth/pth_event.c 1.59 -> 1.60

--- 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;
 }
 


ossp-pkg/pth/pth_high.c 1.94 -> 1.95

--- 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);
                     }


ossp-pkg/pth/pth_sched.c 1.82 -> 1.83

--- 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);
         }


ossp-pkg/pth/pth_sync.c 1.37 -> 1.38

--- 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))


ossp-pkg/pth/pthread.c 1.61 -> 1.62

--- 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;
 }


ossp-pkg/pth/test_mp.c 1.41 -> 1.42

--- 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;
         }

CVSTrac 2.0.1