--- libaitsched/src/tasks.c 2012/08/21 12:54:39 1.13 +++ libaitsched/src/tasks.c 2012/08/23 02:33:12 1.14 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: tasks.c,v 1.13 2012/08/21 12:54:39 misho Exp $ +* $Id: tasks.c,v 1.14 2012/08/23 02:33:12 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)); @@ -106,8 +106,66 @@ sched_unuseTask(sched_task_t * __restrict task) return 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_threadWrapper(sched_task_t *t) +{ + void *ret = NULL; + + if (!t || !TASK_ROOT(t)) + pthread_exit(ret); + + pthread_cleanup_push((void (*)(void*)) _sched_threadCleanup, t); + + 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 + /* + * sched_taskExit() - Exit routine for scheduler task, explicit required for thread tasks + * + * @task = current task + * @retcode = return code + * return: return code + */ +inline void * +sched_taskExit(sched_task_t *task, intptr_t retcode) +{ + if (!task || !TASK_ROOT(task)) + return (void*) -1; + + if (TASK_ROOT(task)->root_hooks.hook_exec.exit) + TASK_ROOT(task)->root_hooks.hook_exec.exit(task, (void*) retcode); + + TASK_ROOT(task)->root_ret = (void*) retcode; + return (void*) retcode; +} + + +/* * schedRead() - Add READ I/O task to scheduler queue * * @root = root task @@ -1176,13 +1234,13 @@ schedThread(sched_root_task_t * __restrict root, sched TASK_ROOT(task) = root; TASK_ARG(task) = arg; + TASK_FLAG(task) = detach ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE; TASK_DATA(task) = opt_data; TASK_DATLEN(task) = opt_dlen; pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, detach ? - PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE); + pthread_attr_setdetachstate(&attr, TASK_FLAG(task)); if (root->root_hooks.hook_add.thread) ptr = root->root_hooks.hook_add.thread(task, &attr); else