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