Index: ossp-pkg/pth/ChangeLog RCS File: /v/ossp/cvs/ossp-pkg/pth/ChangeLog,v rcsdiff -q -kk '-r1.578' '-r1.579' -u '/v/ossp/cvs/ossp-pkg/pth/ChangeLog,v' 2>/dev/null --- ChangeLog 2002/10/24 09:07:51 1.578 +++ ChangeLog 2002/10/24 14:01:37 1.579 @@ -21,6 +21,9 @@ Changes between 1.4.1 and 1.5.0 (27-Jan-2002 to xx-Oct-2002) + *) Cleaned and speeded up the pth_exit() processing. + [Ralf S. Engelschall] + *) Added POSIX-compliant sanity checks for bad filedescriptors to mostly all filedescriptor-based I/O functions in pth_high.c [Ralf S. Engelschall] Index: ossp-pkg/pth/pth_lib.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_lib.c,v rcsdiff -q -kk '-r1.51' '-r1.52' -u '/v/ossp/cvs/ossp-pkg/pth/pth_lib.c,v' 2>/dev/null --- pth_lib.c 2002/10/20 11:45:10 1.51 +++ pth_lib.c 2002/10/24 14:01:37 1.52 @@ -203,9 +203,11 @@ /* just jump into the start routine */ data = (*pth_current->start_func)(pth_current->start_arg); - /* and do an implicit exit of the tread with the result value */ + + /* and do an implicit exit of the thread with the result value */ pth_exit(data); - /* no return! */ + + /* NOTREACHED */ abort(); } pth_t pth_spawn(pth_attr_t attr, void *(*func)(void *), void *arg) @@ -227,9 +229,9 @@ /* allocate a new thread control block */ stacksize = (attr == PTH_ATTR_DEFAULT ? 64*1024 : attr->a_stacksize); - stackaddr = (attr == PTH_ATTR_DEFAULT ? NULL : attr->a_stackaddr); + stackaddr = (attr == PTH_ATTR_DEFAULT ? NULL : attr->a_stackaddr); if ((t = pth_tcb_alloc(stacksize, stackaddr)) == NULL) - return NULL; /* errno is inherited */ + return NULL; /* configure remaining attributes */ if (attr != PTH_ATTR_DEFAULT) { @@ -281,7 +283,7 @@ t->data_value = NULL; t->data_count = 0; - /* initialize cancellaton stuff */ + /* initialize cancellation stuff */ t->cancelreq = FALSE; t->cleanups = NULL; @@ -376,13 +378,13 @@ return; } -/* terminates the current thread */ +/* terminate the current thread */ static int pth_exit_cb(void *arg) { int rc; - /* NOTICE: THIS FUNCTION EXECUTES - FROM WITHIN THE SCHEDULER THREAD! */ + /* BE CAREFUL HERE: THIS FUNCTION EXECUTES + FROM WITHIN THE _SCHEDULER_ THREAD! */ /* calculate number of still existing threads in system. Only skipped queue is pth_DQ (dead queue). This queue does not @@ -409,41 +411,43 @@ pth_debug2("pth_exit: marking thread \"%s\" as dead", pth_current->name); - /* main thread is special: - wait until it is the last thread */ + /* the main thread is special, because its termination + would terminate the whole process, so we have to delay + its termination until it is really the last thread */ if (pth_current == pth_main) { - ev = pth_event(PTH_EVENT_FUNC, pth_exit_cb); - pth_wait(ev); - pth_event_free(ev, PTH_FREE_THIS); + if (!pth_exit_cb(NULL)) { + ev = pth_event(PTH_EVENT_FUNC, pth_exit_cb); + pth_wait(ev); + pth_event_free(ev, PTH_FREE_THIS); + } } /* execute cleanups */ pth_thread_cleanup(pth_current); - /* mark the current thread as dead, so the scheduler removes us */ - pth_current->join_arg = value; - pth_current->state = PTH_STATE_DEAD; - if (pth_current != pth_main) { /* - * Now we explicitly switch into the scheduler and let it - * reap the current thread structure; we can't free it here, - * or we'd be running on a stack which malloc() regards as - * free memory, which would be a somewhat perilous situation. + * Now mark the current thread as dead, explicitly switch into the + * scheduler and let it reap the current thread structure; we can't + * free it here, or we'd be running on a stack which malloc() regards + * as free memory, which would be a somewhat perilous situation. */ + pth_current->join_arg = value; + pth_current->state = PTH_STATE_DEAD; pth_debug2("pth_exit: switching from thread \"%s\" to scheduler", pth_current->name); pth_mctx_switch(&pth_current->mctx, &pth_sched->mctx); - abort(); /* not reached! */ } else { /* * main thread is special: exit the _process_ - * [double-cast to avoid warnings because of size] + * [double-casted to avoid warnings because of size] */ pth_kill(); exit((int)((long)value)); - abort(); /* not reached! */ } + + /* NOTREACHED */ + abort(); } /* waits for the termination of the specified thread */