head 1.67; access; symbols PTH_2_0_7:1.66 PTH_2_0_6:1.65 PTH_2_0_5:1.65 PTH_2_0_4:1.65 PTH_2_0_3:1.64 PTH_2_0_2:1.64 PTH_2_0_1:1.63 PTH_2_0_0:1.61 PTH_2_0b2:1.60 PTH_2_0b1:1.60 PTH_2_0b0:1.60 PTH_1_4:1.58.0.2 PTH_1_4_1:1.58 PTH_1_4_0:1.55 PTH_1_3_7:1.54 PTH_1_4a3:1.54 PTH_1_3_6:1.54 PTH_1_4a2:1.54 PTH_1_3_5:1.54 PTH_1_4a1:1.54 PTH_1_3_4:1.54 PTH_1_3:1.54.0.2 PTH_1_3_3:1.54 PTH_1_3_2:1.54 PTH_1_3_1:1.53 PTH_1_3_0:1.53 PTH_1_3b3:1.53 PTH_1_2_3:1.45.2.2 PTH_1_3b2:1.51 PTH_1_3b1:1.51 PTH_1_3a5:1.51 PTH_1_3a4:1.51 PTH_1_3a3:1.51 PTH_1_2_2:1.45.2.2 PTH_1_3a2:1.49 PTH_1_2_1:1.45.2.1 PTH_1_3a1:1.46 PTH_1_2:1.45.0.2 PTH_1_2_0:1.45 PTH_1_2b8:1.44 PTH_1_2b7:1.44 PTH_1_1_6:1.43 PTH_1_2b6:1.44 PTH_1_2b5:1.44 PTH_1_2b4:1.44 PTH_1_2b3:1.44 PTH_1_2b2:1.43 PTH_1_2b1:1.43 PTH_1_1_5:1.43 PTH_1_0_6:1.37 PTH_1_0_5:1.37 PTH_1_0:1.37.0.2 PTH_1_1:1.43.0.2 PTH_1_1_4:1.43 PTH_1_1_3:1.43 PTH_1_1_2:1.43 PTH_1_1_1:1.43 PTH_1_1_0:1.41 PTH_1_1b7:1.40 PTH_1_1b6:1.40 PTH_1_1b5:1.40 PTH_1_1b4:1.39 PTH_1_1b3:1.38 PTH_1_1b2:1.38 PTH_1_1b1:1.38 PTH_1_0_4:1.37 PTH_1_0_3:1.37 PTH_1_0_2:1.37 PTH_1_0_1:1.36 PTH_1_0_0:1.36 PTH_1_0b8:1.36 PTH_1_0b7:1.36 PTH_1_0b6:1.36 PTH_1_0b5:1.36 PTH_1_0b4:1.34 PTH_1_0b3:1.30 PTH_1_0b2:1.29 PTH_1_0b1:1.28 PTH_0_9_21:1.26 PTH_0_9_20:1.25 PTH_0_9_19:1.23 PTH_0_9_18:1.21 PTH_0_9_17:1.19 PTH_0_9_16:1.19 PTH_0_9_15:1.19 PTH_0_9_14:1.17 PTH_0_9_13:1.15 PTH_0_9_12:1.14 PTH_0_9_11:1.11 PTH_0_9_10:1.10 PTH_0_9_9:1.9 PTH_0_9_8:1.9 PTH_0_9_7:1.5 PTH_0_9_6:1.5 PTH_0_9_5:1.4 PTH_0_9_4:1.3 PTH_0_9_3:1.2 PTH_0_9_2:1.2 PTH_0_9_1:1.1.1.1 PTH_0_9_0:1.1.1.1 RSE:1.1.1; locks; strict; comment @ * @; 1.67 date 2007.01.01.18.23.53; author rse; state Exp; branches; next 1.66; commitid 9DhdiirNzQPBIP0s; 1.66 date 2006.06.08.17.54.52; author rse; state Exp; branches; next 1.65; commitid x8N3mLVdQgkbdeAr; 1.65 date 2004.12.31.19.34.45; author rse; state Exp; branches; next 1.64; 1.64 date 2004.09.12.11.27.32; author rse; state Exp; branches; next 1.63; 1.63 date 2004.07.13.11.00.43; author rse; state Exp; branches; next 1.62; 1.62 date 2004.07.13.10.50.49; author rse; state Exp; branches; next 1.61; 1.61 date 2003.01.01.15.49.11; author rse; state Exp; branches; next 1.60; 1.60 date 2002.11.05.19.39.09; author rse; state Exp; branches; next 1.59; 1.59 date 2002.10.24.15.21.13; author rse; state Exp; branches; next 1.58; 1.58 date 2002.01.27.13.15.28; author rse; state Exp; branches; next 1.57; 1.57 date 2002.01.27.11.03.40; author rse; state Exp; branches; next 1.56; 1.56 date 2001.11.30.12.37.29; author rse; state Exp; branches; next 1.55; 1.55 date 2001.03.24.14.51.04; author rse; state Exp; branches; next 1.54; 1.54 date 2000.02.24.12.35.01; author rse; state Exp; branches; next 1.53; 1.53 date 2000.02.13.17.24.02; author rse; state Exp; branches; next 1.52; 1.52 date 2000.02.13.12.52.15; author rse; state Exp; branches; next 1.51; 1.51 date 2000.01.07.22.26.04; author rse; state Exp; branches; next 1.50; 1.50 date 2000.01.07.21.40.13; author rse; state Exp; branches; next 1.49; 1.49 date 99.12.30.21.59.00; author rse; state Exp; branches; next 1.48; 1.48 date 99.11.09.09.29.46; author rse; state Exp; branches; next 1.47; 1.47 date 99.11.09.08.11.31; author rse; state Exp; branches; next 1.46; 1.46 date 99.11.01.10.27.19; author rse; state Exp; branches; next 1.45; 1.45 date 99.10.31.11.46.12; author rse; state Exp; branches 1.45.2.1; next 1.44; 1.44 date 99.09.17.08.01.55; author rse; state Exp; branches; next 1.43; 1.43 date 99.08.20.07.20.27; author rse; state Exp; branches; next 1.42; 1.42 date 99.08.20.07.17.09; author rse; state Exp; branches; next 1.41; 1.41 date 99.08.19.15.08.52; author rse; state Exp; branches; next 1.40; 1.40 date 99.08.17.08.08.36; author rse; state Exp; branches; next 1.39; 1.39 date 99.08.13.15.40.07; author rse; state Exp; branches; next 1.38; 1.38 date 99.08.07.10.35.18; author rse; state Exp; branches; next 1.37; 1.37 date 99.07.23.14.16.37; author rse; state Exp; branches; next 1.36; 1.36 date 99.07.11.11.58.38; author rse; state Exp; branches; next 1.35; 1.35 date 99.07.09.08.06.41; author rse; state Exp; branches; next 1.34; 1.34 date 99.07.08.10.34.01; author rse; state Exp; branches; next 1.33; 1.33 date 99.07.08.10.19.11; author rse; state Exp; branches; next 1.32; 1.32 date 99.07.08.08.00.50; author rse; state Exp; branches; next 1.31; 1.31 date 99.07.08.07.45.34; author rse; state Exp; branches; next 1.30; 1.30 date 99.07.07.19.02.28; author rse; state Exp; branches; next 1.29; 1.29 date 99.07.04.12.05.35; author rse; state Exp; branches; next 1.28; 1.28 date 99.06.28.11.36.26; author rse; state Exp; branches; next 1.27; 1.27 date 99.06.27.15.40.30; author rse; state Exp; branches; next 1.26; 1.26 date 99.06.26.12.30.55; author rse; state Exp; branches; next 1.25; 1.25 date 99.06.24.12.24.46; author rse; state Exp; branches; next 1.24; 1.24 date 99.06.24.10.54.29; author rse; state Exp; branches; next 1.23; 1.23 date 99.06.21.14.24.47; author rse; state Exp; branches; next 1.22; 1.22 date 99.06.21.09.42.57; author rse; state Exp; branches; next 1.21; 1.21 date 99.06.20.09.44.28; author rse; state Exp; branches; next 1.20; 1.20 date 99.06.19.15.54.35; author rse; state Exp; branches; next 1.19; 1.19 date 99.06.04.10.47.42; author rse; state Exp; branches; next 1.18; 1.18 date 99.06.03.09.30.51; author rse; state Exp; branches; next 1.17; 1.17 date 99.06.01.15.29.22; author rse; state Exp; branches; next 1.16; 1.16 date 99.06.01.14.36.33; author rse; state Exp; branches; next 1.15; 1.15 date 99.06.01.09.55.26; author rse; state Exp; branches; next 1.14; 1.14 date 99.05.30.13.08.37; author rse; state Exp; branches; next 1.13; 1.13 date 99.05.30.10.11.24; author rse; state Exp; branches; next 1.12; 1.12 date 99.05.30.09.28.56; author rse; state Exp; branches; next 1.11; 1.11 date 99.05.28.16.23.14; author rse; state Exp; branches; next 1.10; 1.10 date 99.05.28.09.05.11; author rse; state Exp; branches; next 1.9; 1.9 date 99.05.24.11.45.15; author rse; state Exp; branches; next 1.8; 1.8 date 99.05.24.10.54.27; author rse; state Exp; branches; next 1.7; 1.7 date 99.05.24.10.24.24; author rse; state Exp; branches; next 1.6; 1.6 date 99.05.24.07.58.13; author rse; state Exp; branches; next 1.5; 1.5 date 99.05.22.14.37.52; author rse; state Exp; branches; next 1.4; 1.4 date 99.05.21.15.22.32; author rse; state Exp; branches; next 1.3; 1.3 date 99.05.21.09.44.10; author rse; state Exp; branches; next 1.2; 1.2 date 99.05.14.09.40.05; author rse; state Exp; branches; next 1.1; 1.1 date 99.05.13.12.18.16; author rse; state Exp; branches 1.1.1.1; next ; 1.45.2.1 date 99.11.01.10.24.59; author rse; state Exp; branches; next 1.45.2.2; 1.45.2.2 date 2000.01.07.23.00.35; author rse; state Exp; branches; next ; 1.1.1.1 date 99.05.13.12.18.16; author rse; state Exp; branches; next ; desc @@ 1.67 log @Adjusted all copyright messages for new year 2007. @ text @/* ** GNU Pth - The GNU Portable Threads ** Copyright (c) 1999-2007 Ralf S. Engelschall ** ** This file is part of GNU Pth, a non-preemptive thread scheduling ** library which can be found at http://www.gnu.org/software/pth/. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ** USA, or contact Ralf S. Engelschall . ** ** pth_event.c: Pth event handling */ /* ``Those of you who think they know everything are very annoying to those of us who do.'' -- Unknown */ #include "pth_p.h" #if cpp /* pre-declare type of function event callback (mainly to workaround va_arg(3) problems below) */ typedef int (*pth_event_func_t)(void *); /* event structure */ struct pth_event_st { struct pth_event_st *ev_next; struct pth_event_st *ev_prev; pth_status_t ev_status; int ev_type; int ev_goal; union { struct { int fd; } FD; struct { int *n; int nfd; fd_set *rfds, *wfds, *efds; } SELECT; struct { sigset_t *sigs; int *sig; } SIGS; struct { pth_time_t tv; } TIME; struct { pth_msgport_t mp; } MSG; struct { pth_mutex_t *mutex; } MUTEX; struct { pth_cond_t *cond; } COND; struct { pth_t tid; } TID; struct { pth_event_func_t func; void *arg; pth_time_t tv; } FUNC; } ev_args; }; #endif /* cpp */ /* event structure destructor */ static void pth_event_destructor(void *vp) { /* free this single(!) event. That it is just a single event is a requirement for pth_event(PTH_MODE_STATIC, ...), or else we would get into horrible trouble on asychronous cleanups */ pth_event_free((pth_event_t)vp, PTH_FREE_THIS); return; } /* event structure constructor */ pth_event_t pth_event(unsigned long spec, ...) { pth_event_t ev; pth_key_t *ev_key; va_list ap; va_start(ap, spec); /* allocate new or reuse static or supplied event structure */ if (spec & PTH_MODE_REUSE) { /* reuse supplied event structure */ ev = va_arg(ap, pth_event_t); } else if (spec & PTH_MODE_STATIC) { /* reuse static event structure */ ev_key = va_arg(ap, pth_key_t *); if (*ev_key == PTH_KEY_INIT) pth_key_create(ev_key, pth_event_destructor); ev = (pth_event_t)pth_key_getdata(*ev_key); if (ev == NULL) { ev = (pth_event_t)malloc(sizeof(struct pth_event_st)); pth_key_setdata(*ev_key, ev); } } else { /* allocate new dynamic event structure */ ev = (pth_event_t)malloc(sizeof(struct pth_event_st)); } if (ev == NULL) return pth_error((pth_event_t)NULL, errno); /* create new event ring out of event or insert into existing ring */ if (spec & PTH_MODE_CHAIN) { pth_event_t ch = va_arg(ap, pth_event_t); ev->ev_prev = ch->ev_prev; ev->ev_next = ch; ev->ev_prev->ev_next = ev; ev->ev_next->ev_prev = ev; } else { ev->ev_prev = ev; ev->ev_next = ev; } /* initialize common ingredients */ ev->ev_status = PTH_STATUS_PENDING; /* initialize event specific ingredients */ if (spec & PTH_EVENT_FD) { /* filedescriptor event */ int fd = va_arg(ap, int); if (!pth_util_fd_valid(fd)) return pth_error((pth_event_t)NULL, EBADF); ev->ev_type = PTH_EVENT_FD; ev->ev_goal = (int)(spec & (PTH_UNTIL_FD_READABLE|\ PTH_UNTIL_FD_WRITEABLE|\ PTH_UNTIL_FD_EXCEPTION)); ev->ev_args.FD.fd = fd; } else if (spec & PTH_EVENT_SELECT) { /* filedescriptor set select event */ int *n = va_arg(ap, int *); int nfd = va_arg(ap, int); fd_set *rfds = va_arg(ap, fd_set *); fd_set *wfds = va_arg(ap, fd_set *); fd_set *efds = va_arg(ap, fd_set *); ev->ev_type = PTH_EVENT_SELECT; ev->ev_goal = (int)(spec & (PTH_UNTIL_OCCURRED)); ev->ev_args.SELECT.n = n; ev->ev_args.SELECT.nfd = nfd; ev->ev_args.SELECT.rfds = rfds; ev->ev_args.SELECT.wfds = wfds; ev->ev_args.SELECT.efds = efds; } else if (spec & PTH_EVENT_SIGS) { /* signal set event */ sigset_t *sigs = va_arg(ap, sigset_t *); int *sig = va_arg(ap, int *); ev->ev_type = PTH_EVENT_SIGS; ev->ev_goal = (int)(spec & (PTH_UNTIL_OCCURRED)); ev->ev_args.SIGS.sigs = sigs; ev->ev_args.SIGS.sig = sig; } else if (spec & PTH_EVENT_TIME) { /* interrupt request event */ pth_time_t tv = va_arg(ap, pth_time_t); ev->ev_type = PTH_EVENT_TIME; ev->ev_goal = (int)(spec & (PTH_UNTIL_OCCURRED)); ev->ev_args.TIME.tv = tv; } else if (spec & PTH_EVENT_MSG) { /* message port event */ pth_msgport_t mp = va_arg(ap, pth_msgport_t); ev->ev_type = PTH_EVENT_MSG; ev->ev_goal = (int)(spec & (PTH_UNTIL_OCCURRED)); ev->ev_args.MSG.mp = mp; } else if (spec & PTH_EVENT_MUTEX) { /* mutual exclusion lock */ pth_mutex_t *mutex = va_arg(ap, pth_mutex_t *); ev->ev_type = PTH_EVENT_MUTEX; ev->ev_goal = (int)(spec & (PTH_UNTIL_OCCURRED)); ev->ev_args.MUTEX.mutex = mutex; } else if (spec & PTH_EVENT_COND) { /* condition variable */ pth_cond_t *cond = va_arg(ap, pth_cond_t *); ev->ev_type = PTH_EVENT_COND; ev->ev_goal = (int)(spec & (PTH_UNTIL_OCCURRED)); ev->ev_args.COND.cond = cond; } else if (spec & PTH_EVENT_TID) { /* thread id event */ pth_t tid = va_arg(ap, pth_t); int goal; ev->ev_type = PTH_EVENT_TID; if (spec & PTH_UNTIL_TID_NEW) goal = PTH_STATE_NEW; else if (spec & PTH_UNTIL_TID_READY) goal = PTH_STATE_READY; else if (spec & PTH_UNTIL_TID_WAITING) goal = PTH_STATE_WAITING; else if (spec & PTH_UNTIL_TID_DEAD) goal = PTH_STATE_DEAD; else goal = PTH_STATE_READY; ev->ev_goal = goal; ev->ev_args.TID.tid = tid; } else if (spec & PTH_EVENT_FUNC) { /* custom function event */ ev->ev_type = PTH_EVENT_FUNC; ev->ev_goal = (int)(spec & (PTH_UNTIL_OCCURRED)); ev->ev_args.FUNC.func = va_arg(ap, pth_event_func_t); ev->ev_args.FUNC.arg = va_arg(ap, void *); ev->ev_args.FUNC.tv = va_arg(ap, pth_time_t); } else return pth_error((pth_event_t)NULL, EINVAL); va_end(ap); /* return event */ return ev; } /* determine type of event */ unsigned long pth_event_typeof(pth_event_t ev) { if (ev == NULL) return pth_error(0, EINVAL); return (ev->ev_type | ev->ev_goal); } /* event extractor */ int pth_event_extract(pth_event_t ev, ...) { va_list ap; if (ev == NULL) return pth_error(FALSE, EINVAL); va_start(ap, ev); /* extract event specific ingredients */ if (ev->ev_type & PTH_EVENT_FD) { /* filedescriptor event */ int *fd = va_arg(ap, int *); *fd = ev->ev_args.FD.fd; } else if (ev->ev_type & PTH_EVENT_SIGS) { /* signal set event */ sigset_t **sigs = va_arg(ap, sigset_t **); int **sig = va_arg(ap, int **); *sigs = ev->ev_args.SIGS.sigs; *sig = ev->ev_args.SIGS.sig; } else if (ev->ev_type & PTH_EVENT_TIME) { /* interrupt request event */ pth_time_t *tv = va_arg(ap, pth_time_t *); *tv = ev->ev_args.TIME.tv; } else if (ev->ev_type & PTH_EVENT_MSG) { /* message port event */ pth_msgport_t *mp = va_arg(ap, pth_msgport_t *); *mp = ev->ev_args.MSG.mp; } else if (ev->ev_type & PTH_EVENT_MUTEX) { /* mutual exclusion lock */ pth_mutex_t **mutex = va_arg(ap, pth_mutex_t **); *mutex = ev->ev_args.MUTEX.mutex; } else if (ev->ev_type & PTH_EVENT_COND) { /* condition variable */ pth_cond_t **cond = va_arg(ap, pth_cond_t **); *cond = ev->ev_args.COND.cond; } else if (ev->ev_type & PTH_EVENT_TID) { /* thread id event */ pth_t *tid = va_arg(ap, pth_t *); *tid = ev->ev_args.TID.tid; } else if (ev->ev_type & PTH_EVENT_FUNC) { /* custom function event */ pth_event_func_t *func = va_arg(ap, pth_event_func_t *); void **arg = va_arg(ap, void **); pth_time_t *tv = va_arg(ap, pth_time_t *); *func = ev->ev_args.FUNC.func; *arg = ev->ev_args.FUNC.arg; *tv = ev->ev_args.FUNC.tv; } else return pth_error(FALSE, EINVAL); va_end(ap); return TRUE; } /* concatenate one or more events or event rings */ pth_event_t pth_event_concat(pth_event_t evf, ...) { pth_event_t evc; /* current event */ pth_event_t evn; /* next event */ pth_event_t evl; /* last event */ pth_event_t evt; /* temporary event */ va_list ap; if (evf == NULL) return pth_error((pth_event_t)NULL, EINVAL); /* open ring */ va_start(ap, evf); evc = evf; evl = evc->ev_next; /* attach additional rings */ while ((evn = va_arg(ap, pth_event_t)) != NULL) { evc->ev_next = evn; evt = evn->ev_prev; evn->ev_prev = evc; evc = evt; } /* close ring */ evc->ev_next = evl; evl->ev_prev = evc; va_end(ap); return evf; } /* isolate one event from a possible appended event ring */ pth_event_t pth_event_isolate(pth_event_t ev) { pth_event_t ring; if (ev == NULL) return pth_error((pth_event_t)NULL, EINVAL); ring = NULL; if (!(ev->ev_next == ev && ev->ev_prev == ev)) { ring = ev->ev_next; ev->ev_prev->ev_next = ev->ev_next; ev->ev_next->ev_prev = ev->ev_prev; ev->ev_prev = ev; ev->ev_next = ev; } return ring; } /* 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_status; } /* walk to next or previous event in an event ring */ pth_event_t pth_event_walk(pth_event_t ev, unsigned int direction) { if (ev == NULL) return pth_error((pth_event_t)NULL, EINVAL); do { if (direction & PTH_WALK_NEXT) ev = ev->ev_next; else if (direction & PTH_WALK_PREV) ev = ev->ev_prev; else return pth_error((pth_event_t)NULL, EINVAL); } while ((direction & PTH_UNTIL_OCCURRED) && (ev->ev_status != PTH_STATUS_OCCURRED)); return ev; } /* deallocate an event structure */ int pth_event_free(pth_event_t ev, int mode) { pth_event_t evc; pth_event_t evn; if (ev == NULL) return pth_error(FALSE, EINVAL); if (mode == PTH_FREE_THIS) { ev->ev_prev->ev_next = ev->ev_next; ev->ev_next->ev_prev = ev->ev_prev; free(ev); } else if (mode == PTH_FREE_ALL) { evc = ev; do { evn = evc->ev_next; free(evc); evc = evn; } while (evc != ev); } return TRUE; } /* wait for one or more events */ int pth_wait(pth_event_t ev_ring) { int nonpending; pth_event_t ev; /* at least a waiting ring is required */ if (ev_ring == NULL) return pth_error(-1, EINVAL); pth_debug2("pth_wait: enter from thread \"%s\"", pth_current->name); /* mark all events in waiting ring as still pending */ ev = ev_ring; do { 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); /* link event ring to current thread */ pth_current->events = ev_ring; /* move thread into waiting state and transfer control to scheduler */ pth_current->state = PTH_STATE_WAITING; pth_yield(NULL); /* check for cancellation */ pth_cancel_point(); /* unlink event ring from current thread */ pth_current->events = NULL; /* count number of actually occurred (or failed) events */ ev = ev_ring; nonpending = 0; do { 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 nonpending; } @ 1.66 log @Adjusted all copyright messages for new year 2006 @ text @d3 1 a3 1 ** Copyright (c) 1999-2006 Ralf S. Engelschall @ 1.65 log @Adjusted all copyright messages for new year 2005. @ text @d3 1 a3 1 ** Copyright (c) 1999-2005 Ralf S. Engelschall @ 1.64 log @Workaround GCC 2.x and 3.5 (3.4 worked fine) macro parsing behaviour by using a pre-declared function pointer type "typedef int (*pth_event_func_t)(void *);" instead of using an inlined "int (*)(void *)". Triggered by a report from: Robert Anderson @ text @d3 1 a3 1 ** Copyright (c) 1999-2004 Ralf S. Engelschall @ 1.63 log @Fix handling/casting of "int (*)(void *)" callback functions @ text @d33 4 d45 9 a53 9 struct { int fd; } FD; struct { int *n; int nfd; fd_set *rfds, *wfds, *efds; } SELECT; struct { sigset_t *sigs; int *sig; } SIGS; struct { pth_time_t tv; } TIME; struct { pth_msgport_t mp; } MSG; struct { pth_mutex_t *mutex; } MUTEX; struct { pth_cond_t *cond; } COND; struct { pth_t tid; } TID; struct { int (*func)(void *); void *arg; pth_time_t tv; } FUNC; d203 1 a203 1 ev->ev_args.FUNC.func = va_arg(ap, int (*)(void *)); d273 3 a275 3 int (**func)(void *) = va_arg(ap, int (**)(void *)); void **arg = va_arg(ap, void **); pth_time_t *tv = va_arg(ap, pth_time_t *); @ 1.62 log @Adjusted all copyright messages for new year 2004. @ text @d199 1 a199 1 ev->ev_args.FUNC.func = (int (*)(void *))va_arg(ap, void *); d269 4 a272 4 void **func = va_arg(ap, void **); void **arg = va_arg(ap, void **); pth_time_t *tv = va_arg(ap, pth_time_t *); *func = (int (**)(void *))ev->ev_args.FUNC.func; @ 1.61 log @Adjusted all copyright messages for new year 2003. @ text @d3 1 a3 1 ** Copyright (c) 1999-2003 Ralf S. Engelschall @ 1.60 log @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 @ text @d3 1 a3 1 ** Copyright (c) 1999-2002 Ralf S. Engelschall @ 1.59 log @Internally switch from "errno_shield {...}" to "pth_shield {...}" and from "return_errno(..)" to "return pth_error(...)" in order to make the internal error handling a little bit more consistent. @ text @d37 1 a37 1 int ev_occurred; d111 1 a111 1 ev->ev_occurred = FALSE; d333 2 a334 2 /* determine whether the event is occurred */ int pth_event_occurred(pth_event_t ev) d338 1 a338 1 return ev->ev_occurred; d353 1 a353 1 } while ((direction & PTH_UNTIL_OCCURRED) && !(ev->ev_occurred)); d384 1 a384 1 int occurred; d392 1 a392 1 /* mark all events in waiting ring as still not occurred */ d395 1 a395 1 ev->ev_occurred = FALSE; d414 1 a414 1 /* count number of actually occurred events */ d416 1 a416 1 occurred = 0; d418 3 a420 3 if (ev->ev_occurred) { pth_debug2("pth_wait: occurred event 0x%lx", (unsigned long)ev); occurred++; d427 1 a427 1 return occurred; @ 1.58 log @Internally make sure an invalid file-descriptor (integer not between 0 and (FD_SETSIZE-1) does not lead to any segfaults or other undefined behaviour. Instead an error is returned and errno is set to EBADF, similar to what the OS functions do. Especially pth_poll() now return with this error (instead of skipping the fd) if an fd in the "struct pollfd" is invalid. Hint by: Archie Cobbs @ text @d95 1 a95 1 return NULL; /* errno is already set */ d118 1 a118 1 return_errno(NULL, EBADF); d204 1 a204 1 return_errno(NULL, EINVAL); d216 1 a216 1 return_errno(0, EINVAL); d226 1 a226 1 return_errno(FALSE, EINVAL); d277 1 a277 1 return_errno(FALSE, EINVAL); d292 1 a292 1 return_errno(NULL, EINVAL); d321 1 a321 1 return_errno(NULL, EINVAL); d337 1 a337 1 return_errno(FALSE, EINVAL); d345 1 a345 1 return_errno(NULL, EINVAL); d352 1 a352 1 return_errno(NULL, EINVAL); d364 1 a364 1 return_errno(FALSE, EINVAL); d389 1 a389 1 return_errno(-1, EINVAL); @ 1.57 log @bump copyright year @ text @d117 2 @ 1.56 log @*** empty log message *** @ text @d3 1 a3 1 ** Copyright (c) 1999-2001 Ralf S. Engelschall @ 1.55 log @*** empty log message *** @ text @d416 4 a419 2 occurred++; pth_debug2("pth_wait: occurred event 0x%lx", (unsigned long)ev); @ 1.54 log @*** empty log message *** @ text @d3 1 a3 1 ** Copyright (c) 1999-2000 Ralf S. Engelschall @ 1.53 log @*** empty log message *** @ text @a341 2 pth_event_t evC; a343 1 evC = ev; @ 1.52 log @*** empty log message *** @ text @d49 1 a49 2 struct { pid_t pid; int *status; int flags; } PID; struct { int (*func)(void *); void *func_arg; } FUNC; a192 8 else if (spec & PTH_EVENT_PID) { /* process id event */ ev->ev_type = PTH_EVENT_PID; ev->ev_goal = (int)(spec & (PTH_UNTIL_OCCURRED)); ev->ev_args.PID.pid = va_arg(ap, pid_t); ev->ev_args.PID.status = va_arg(ap, int *); ev->ev_args.PID.flags = va_arg(ap, int); } d197 3 a199 2 ev->ev_args.FUNC.func = (int (*)(void *))va_arg(ap, void *); ev->ev_args.FUNC.func_arg = va_arg(ap, void *); a264 9 else if (ev->ev_type & PTH_EVENT_PID) { /* process id event */ pid_t *pid = va_arg(ap, pid_t *); int **status = va_arg(ap, int **); int *flags = va_arg(ap, int *); *pid = ev->ev_args.PID.pid; *status = ev->ev_args.PID.status; *flags = ev->ev_args.PID.flags; } d267 3 a269 2 void **func = va_arg(ap, void **); void **arg = va_arg(ap, void **); d271 2 a272 1 *arg = ev->ev_args.FUNC.func_arg; @ 1.51 log @*** empty log message *** @ text @d50 1 a50 1 struct { int (*func)(void*); void *func_arg; } FUNC; @ 1.50 log @*** empty log message *** @ text @d59 4 a62 1 pth_event_free((pth_event_t)vp, PTH_FREE_ALL); @ 1.49 log @*** empty log message *** @ text @d409 1 a409 1 pth_debug2("pth_wait: waiting event 0x%lx", (unsigned long)ev); @ 1.48 log @*** empty log message *** @ text @d3 1 a3 1 ** Copyright (c) 1999 Ralf S. Engelschall @ 1.47 log @*** empty log message *** @ text @d56 1 a56 1 /* event structure constructor */ d62 2 @ 1.46 log @*** empty log message *** @ text @d69 1 a69 1 d373 1 a373 1 d414 1 a414 1 /* move thread into waiting state d436 1 a436 1 return occurred; @ 1.45 log @*** empty log message *** @ text @d2 1 a2 2 ** pth_event.c -- Pth event handling ** d22 2 @ 1.45.2.1 log @*** empty log message *** @ text @d2 2 a3 1 ** GNU Pth - The GNU Portable Threads a22 2 ** ** pth_event.c: Pth event handling @ 1.45.2.2 log @*** empty log message *** @ text @d59 1 a59 4 /* free this single(!) event. That it is just a single event is a requirement for pth_event(PTH_MODE_STATIC, ...), or else we would get into horrible trouble on asychronous cleanups */ pth_event_free((pth_event_t)vp, PTH_FREE_THIS); @ 1.44 log @*** empty log message *** @ text @d12 1 a12 1 ** version 2 of the License, or (at your option) any later version. @ 1.43 log @*** empty log message *** @ text @d10 1 a10 1 ** modify it under the terms of the GNU Library General Public d17 1 a17 1 ** Library General Public License for more details. d19 1 a19 1 ** You should have received a copy of the GNU Library General Public @ 1.42 log @*** empty log message *** @ text @d90 1 a90 1 return_errno(NULL, EINVAL); d203 2 d283 2 d361 2 @ 1.41 log @*** empty log message *** @ text @d90 1 a90 1 return NULL; @ 1.40 log @*** empty log message *** @ text @d24 4 a27 1 @ 1.39 log @*** empty log message *** @ text @d78 1 a78 1 ev = malloc(sizeof(struct pth_event_st)); d84 1 a84 1 ev = malloc(sizeof(struct pth_event_st)); @ 1.38 log @*** empty log message *** @ text @d397 1 a398 1 pth_debug2("pth_wait: waiting event 0x%lx", (unsigned long)ev); @ 1.37 log @*** empty log message *** @ text @d172 10 a181 10 switch (spec & (PTH_UNTIL_TID_NEW|\ PTH_UNTIL_TID_READY|\ PTH_UNTIL_TID_WAITING|\ PTH_UNTIL_TID_DEAD)) { case PTH_UNTIL_TID_NEW: goal = PTH_STATE_NEW; break; case PTH_UNTIL_TID_READY: goal = PTH_STATE_READY; break; case PTH_UNTIL_TID_WAITING: goal = PTH_STATE_WAITING; break; case PTH_UNTIL_TID_DEAD: goal = PTH_STATE_DEAD; break; default: goal = PTH_STATE_READY; } @ 1.36 log @*** empty log message *** @ text @d37 1 a37 1 struct { int fd; int was_blocking; } FD; a113 4 if (pth_nonblocking(fd)) ev->ev_args.FD.was_blocking = FALSE; else ev->ev_args.FD.was_blocking = TRUE; @ 1.35 log @*** empty log message *** @ text @d402 1 a402 1 pth_debug2("pth_wait: waiting event 0x%x", ev); d424 1 a424 1 pth_debug2("pth_wait: occurred event 0x%x", ev); @ 1.34 log @*** empty log message *** @ text @d37 10 a46 9 struct { int fd; int was_blocking; } FD; struct { sigset_t *sigs; int *sig; } SIGS; struct { pth_time_t tv; } TIME; struct { pth_msgport_t mp; } MSG; struct { pth_mutex_t *mutex; } MUTEX; struct { pth_cond_t *cond; } COND; struct { pth_t tid; } TID; struct { pid_t pid; int *status; int flags; } PID; struct { int (*func)(void*); void *func_arg; } FUNC; d118 15 @ 1.33 log @*** empty log message *** @ text @d2 1 a2 1 ** pth_event.c -- PTH event handling @ 1.32 log @*** empty log message *** @ text @d6 2 a7 2 ** This file is part of PTH, a non-preemptive thread scheduling library ** which can be found at http://www.gnu.org/software/pth/. @ 1.31 log @*** empty log message *** @ text @d289 1 a290 3 evt->ev_next = evl; evl->ev_prev = evt; evc->ev_next = evn; d292 1 a292 2 evc = evn; evl = evc->ev_next; @ 1.30 log @*** empty log message *** @ text @d283 1 a283 1 evl = evf->ev_next; d285 1 a287 1 va_start(ap, evf); d295 1 a296 1 va_end(ap); d301 1 @ 1.29 log @*** empty log message *** @ text @d195 75 d273 4 a276 3 pth_event_t evc; pth_event_t evn; pth_event_t evl; d286 1 a286 1 /* insert new elements */ d289 3 @ 1.28 log @*** empty log message *** @ text @d7 1 a7 1 ** which can be found at http://www.engelschall.com/sw/pth/. @ 1.27 log @*** empty log message *** @ text @d248 1 a248 1 return_errno(NULL, EINVAL); @ 1.26 log @*** empty log message *** @ text @d164 5 a168 5 case PTH_UNTIL_TID_NEW: goal = pth_state_new; break; case PTH_UNTIL_TID_READY: goal = pth_state_ready; break; case PTH_UNTIL_TID_WAITING: goal = pth_state_waiting; break; case PTH_UNTIL_TID_DEAD: goal = pth_state_dead; break; default: goal = pth_state_ready; d317 1 a317 1 pth_current->state = pth_state_waiting; @ 1.25 log @*** empty log message *** @ text @d77 1 a77 1 ev = (pth_event_t)malloc(sizeof(struct pth_event_st)); d83 1 a83 1 ev = (pth_event_t)malloc(sizeof(struct pth_event_st)); @ 1.24 log @*** empty log message *** @ text @d203 3 d231 2 d247 2 d258 1 a258 1 return NULL; d270 1 a270 1 void pth_event_free(pth_event_t ev, int mode) d276 1 a276 1 return; d290 1 a290 1 return; @ 1.23 log @*** empty log message *** @ text @d311 1 a311 1 pth_yield(); @ 1.22 log @*** empty log message *** @ text @d42 1 d142 1 a142 1 /* message port event */ d147 7 @ 1.21 log @*** empty log message *** @ text @d41 1 d139 7 @ 1.20 log @*** empty log message *** @ text @a275 3 /* check for cancellation */ pth_cancel_point(); d297 1 a297 1 /* check again for cancellation */ @ 1.19 log @*** empty log message *** @ text @d276 3 d299 3 @ 1.18 log @*** empty log message *** @ text @d38 1 a38 1 struct { int sig; } SIG; d116 5 a120 4 else if (spec & PTH_EVENT_SIG) { /* interrupt request event */ int sig = va_arg(ap, int); ev->ev_type = PTH_EVENT_SIG; d122 2 a123 1 ev->ev_args.SIG.sig = sig; @ 1.17 log @*** empty log message *** @ text @d228 1 a228 1 pth_event_t pth_event_walk(pth_event_t ev, int direction) d230 3 a232 5 if (direction == PTH_WALK_NEXT) return ev->ev_next; else if (direction == PTH_WALK_PREV) return ev->ev_prev; else d234 8 @ 1.16 log @*** empty log message *** @ text @d38 1 a38 1 struct { int sig; } IRQ; d116 1 a116 1 else if (spec & PTH_EVENT_IRQ) { d119 1 a119 1 ev->ev_type = PTH_EVENT_IRQ; d121 1 a121 1 ev->ev_args.IRQ.sig = sig; d132 1 d135 1 a135 1 ev->ev_args.MSG.mp = va_arg(ap, pth_msgport_t); d139 1 d153 1 a153 1 ev->ev_args.TID.tid = va_arg(ap, pth_t); @ 1.15 log @*** empty log message *** @ text @d107 3 a109 1 ev->ev_goal = (int)(spec & (PTH_UNTIL_READABLE|PTH_UNTIL_WRITEABLE|PTH_UNTIL_EXCEPTION)); d127 1 a127 1 ev->ev_goal = (int)(spec & (PTH_UNTIL_ELAPSED)); d133 1 a133 1 ev->ev_goal = (int)(spec & (PTH_UNTIL_RECEIVED)); d140 9 a148 6 switch (spec & (PTH_UNTIL_NEW|PTH_UNTIL_READY|PTH_UNTIL_WAITING|PTH_UNTIL_DEAD)) { case PTH_UNTIL_NEW: goal = pth_state_new; break; case PTH_UNTIL_READY: goal = pth_state_ready; break; case PTH_UNTIL_WAITING: goal = pth_state_waiting; break; case PTH_UNTIL_DEAD: goal = pth_state_dead; break; default: goal = pth_state_ready; d156 1 a156 1 ev->ev_goal = (int)(spec & (PTH_UNTIL_AVAILABLE)); d164 1 a164 1 ev->ev_goal = (int)(spec & (PTH_UNTIL_FULFILLED)); @ 1.14 log @*** empty log message *** @ text @d20 1 a20 1 ** License along with this library; if not, write to the Free @ 1.13 log @*** empty log message *** @ text @d208 2 d256 1 a256 1 int pth_wait(pth_event_t *ev_waiting, pth_event_t *ev_occurred_external) a259 2 pth_event_t ev_occurred_local; pth_event_t *ev_occurred; d262 2 a263 2 if (ev_waiting == NULL) return -1; a265 6 /* support external/real and internal/dummy occurrence rings */ if (ev_occurred_external != NULL) ev_occurred = ev_occurred_external; else ev_occurred = &ev_occurred_local; d267 1 a267 1 ev = *ev_waiting; d271 2 a272 4 } while (ev != *ev_waiting); /* initialize occurrence ring */ *ev_occurred = NULL; d274 2 a275 3 /* link waiting and occurred ring to current thread */ pth_current->events_occurred = ev_occurred; pth_current->events_waiting = ev_waiting; d282 2 a283 3 /* unlink waiting and occurred ring from current thread */ pth_current->events_occurred = NULL; pth_current->events_waiting = NULL; d286 1 d288 5 a292 17 if (*ev_occurred != NULL) { ev = *ev_occurred; do { occurred++; ev = ev->ev_next; } while (ev != *ev_occurred); } /* when using an internal occurange ring, move events back from internal occurange ring to waiting ring, so the caller can easily reuse them */ if (ev_occurred_external == NULL) { if (*ev_waiting == NULL) *ev_waiting = ev_occurred_local; else if (*ev_waiting != NULL && ev_occurred_local != NULL) *ev_waiting = pth_event_concat(*ev_waiting, ev_occurred_local, NULL); } @ 1.12 log @*** empty log message *** @ text @d284 1 a284 1 pth_current->events_waiting = ev_waiting; a291 1 pth_current->events_waiting = NULL; d293 1 @ 1.11 log @*** empty log message *** @ text @d312 1 a312 1 *ev_waiting = pth_event_concat(*ev_waiting, ev_occurred_local); @ 1.10 log @*** empty log message *** @ text @d50 5 d58 1 d62 4 a65 3 /* allocate new or reuse existing event structure */ if (spec & PTH_MODE_REUSE) d67 14 a80 1 else d82 1 @ 1.9 log @*** empty log message *** @ text @d27 22 @ 1.8 log @*** empty log message *** @ text @d64 1 a64 1 ev->ev_goal = (spec & (PTH_UNTIL_READABLE|PTH_UNTIL_WRITEABLE|PTH_UNTIL_EXCEPTION)); d75 1 a75 1 ev->ev_goal = (spec & (PTH_UNTIL_OCCURRED)); d82 1 a82 1 ev->ev_goal = (spec & (PTH_UNTIL_ELAPSED)); d88 1 a88 1 ev->ev_goal = (spec & (PTH_UNTIL_RECEIVED)); d108 1 a108 1 ev->ev_goal = (spec & (PTH_UNTIL_AVAILABLE)); d116 1 a116 1 ev->ev_goal = (spec & (PTH_UNTIL_FULFILLED)); @ 1.7 log @*** empty log message *** @ text @d95 1 a95 1 switch (spec & (PTH_UNTIL_NEW|PTH_UNTIL_READY|PTH_UNTIL_RUNNING|PTH_UNTIL_WAITING|PTH_UNTIL_DEAD)) { a97 1 case PTH_UNTIL_RUNNING: goal = pth_state_running; break; @ 1.6 log @*** empty log message *** @ text @d57 1 a57 1 ev->ev_occured = FALSE; d75 1 a75 1 ev->ev_goal = (spec & (PTH_UNTIL_OCCURED)); d170 2 a171 2 /* determine whether the event is occured */ int pth_event_occured(pth_event_t ev) d173 1 a173 1 return ev->ev_occured; d212 1 a212 1 int pth_wait(pth_event_t *ev_waiting, pth_event_t *ev_occured_external) d214 1 a214 1 int occured; d216 2 a217 2 pth_event_t ev_occured_local; pth_event_t *ev_occured; d225 2 a226 2 if (ev_occured_external != NULL) ev_occured = ev_occured_external; d228 1 a228 1 ev_occured = &ev_occured_local; d230 1 a230 1 /* mark all events in waiting ring as still not occured */ d233 1 a233 1 ev->ev_occured = FALSE; d238 1 a238 1 *ev_occured = NULL; d240 2 a241 2 /* link waiting and occured ring to current thread */ pth_current->events_occured = ev_occured; d249 1 a249 1 /* unlink waiting and occured ring from current thread */ d251 1 a251 1 pth_current->events_occured = NULL; d253 4 a256 4 /* count number of actually occured events */ occured = 0; if (*ev_occured != NULL) { ev = *ev_occured; d258 1 a258 1 occured++; d260 1 a260 1 } while (ev != *ev_occured); d266 1 a266 1 if (ev_occured_external == NULL) { d268 3 a270 3 *ev_waiting = ev_occured_local; else if (*ev_waiting != NULL && ev_occured_local != NULL) *ev_waiting = pth_event_concat(*ev_waiting, ev_occured_local); d273 1 a273 1 /* leave to current thread with number of occured events */ d275 1 a275 1 return occured; @ 1.5 log @*** empty log message *** @ text @d6 1 a6 1 ** This file is part of PTH, a non-preemtive thread scheduling library @ 1.4 log @*** empty log message *** @ text @a0 40 /* ==================================================================== * Copyright (c) 1999 Ralf S. Engelschall. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by * Ralf S. Engelschall ." * * 4. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by * Ralf S. Engelschall ." * * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== */ d2 21 a22 2 ** Non-Preemtive Scheduler Library (PTH) ** pth_event.c -- event handling code @ 1.3 log @*** empty log message *** @ text @d177 14 @ 1.2 log @*** empty log message *** @ text @d157 1 d160 2 d169 2 d173 1 d226 6 d237 6 a242 2 if (ev_waiting == NULL) return -1; d244 2 a245 1 pth_debug2("pth_wait: enter from thread \"%s\"", pth_current->name); d247 1 a247 1 *ev_occured = NULL; d250 3 a253 1 d256 1 d260 1 d270 3 d280 1 @ 1.1 log @Initial revision @ text @d87 2 a88 2 if (pth_asynchronize(fd)) ev->ev_args.FD.was_async = TRUE; d90 1 a90 1 ev->ev_args.FD.was_async = FALSE; d249 6 a254 2 if (ev_occured_external == NULL && ev_occured_local != NULL) pth_event_free(ev_occured_local, PTH_FREE_ALL); @ 1.1.1.1 log @Import of PTH into CVS @ text @@