--- libaitsched/src/tasks.c 2012/08/22 23:43:36 1.13.2.3 +++ libaitsched/src/tasks.c 2012/08/23 02:09:54 1.13.2.4 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: tasks.c,v 1.13.2.3 2012/08/22 23:43:36 misho Exp $ +* $Id: tasks.c,v 1.13.2.4 2012/08/23 02:09:54 misho Exp $ * ************************************************************************** The ELWIX and AITNET software is distributed under the following @@ -57,18 +57,18 @@ sched_useTask(sched_root_task_t * __restrict root) { sched_task_t *task, *tmp; - TAILQ_FOREACH_SAFE(task, &root->root_unuse, task_node, tmp) { - if (!TASK_ISLOCKED(task)) { #ifdef HAVE_LIBPTHREAD - pthread_mutex_lock(&root->root_mtx[taskUNUSE]); + pthread_mutex_lock(&root->root_mtx[taskUNUSE]); #endif + TAILQ_FOREACH_SAFE(task, &root->root_unuse, task_node, tmp) { + if (!TASK_ISLOCKED(task)) { TAILQ_REMOVE(&root->root_unuse, task, task_node); -#ifdef HAVE_LIBPTHREAD - pthread_mutex_unlock(&root->root_mtx[taskUNUSE]); -#endif break; } } +#ifdef HAVE_LIBPTHREAD + pthread_mutex_unlock(&root->root_mtx[taskUNUSE]); +#endif if (!task) { task = malloc(sizeof(sched_task_t)); @@ -108,26 +108,39 @@ sched_unuseTask(sched_task_t * __restrict task) #pragma GCC visibility push(hidden) +#ifdef HAVE_LIBPTHREAD +static void +_sched_threadCleanup(sched_task_t *t) +{ + if (!t || !TASK_ROOT(t)) + return; + + if (TASK_FLAG(t) == PTHREAD_CREATE_JOINABLE) + pthread_detach(pthread_self()); + + sched_unuseTask(t); +} void * -_sched_threadJoin(sched_task_t *task) +_sched_threadWrapper(sched_task_t *t) { void *ret = NULL; - if (!task) - return NULL; + if (!t || !TASK_ROOT(t)) + pthread_exit(ret); -#ifdef HAVE_LIBPTHREAD - if (pthread_kill((pthread_t) TASK_VAL(task), 0)) { - pthread_join((pthread_t) TASK_VAL(task), &ret); - TASK_ROOT(task)->root_ret = ret; - } else { - usleep(10000); - schedTaskSelf(task); - } -#endif + pthread_cleanup_push((void (*)(void*)) _sched_threadCleanup, t); - return NULL; + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + pthread_testcancel(); + + ret = TASK_FUNC(t)(t); + + pthread_cleanup_pop(42); + TASK_ROOT(t)->root_ret = ret; + pthread_exit(ret); } +#endif #pragma GCC visibility pop @@ -148,17 +161,6 @@ sched_taskExit(sched_task_t *task, intptr_t retcode) TASK_ROOT(task)->root_hooks.hook_exec.exit(task, (void*) retcode); TASK_ROOT(task)->root_ret = (void*) retcode; - -#ifdef HAVE_LIBPTHREAD - if (TASK_TYPE(task) == taskTHREAD) { - if (TASK_FLAG(task) == PTHREAD_CREATE_JOINABLE) /* joinable thread */ - schedTask(TASK_ROOT(task), _sched_threadJoin, TASK_ARG(task), - TASK_VAL(task), TASK_DATA(task), TASK_DATLEN(task)); - sched_unuseTask(task); - pthread_exit((void*) retcode); - } -#endif - return (void*) retcode; }