--- libaitsched/src/aitsched.c 2012/03/13 10:01:59 1.6 +++ libaitsched/src/aitsched.c 2012/05/15 15:47:12 1.7.2.1 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: aitsched.c,v 1.6 2012/03/13 10:01:59 misho Exp $ +* $Id: aitsched.c,v 1.7.2.1 2012/05/15 15:47:12 misho Exp $ * ************************************************************************** The ELWIX and AITNET software is distributed under the following @@ -93,8 +93,7 @@ sched_SetErr(int eno, char *estr, ...) int schedRegisterHooks(sched_root_task_t * __restrict root) { - if (!root || (root->root_data.iov_base && root->root_data.iov_len)) - return -1; + assert(root); if (root->root_hooks.hook_root.fini) root->root_hooks.hook_root.fini(root, NULL); @@ -191,7 +190,7 @@ schedInit(void ** __restrict data, size_t datlen) int schedEnd(sched_root_task_t ** __restrict root) { - sched_task_t *task; + sched_task_t *task, *tmp; #ifdef HAVE_LIBPTHREAD register int i; #endif @@ -199,22 +198,22 @@ schedEnd(sched_root_task_t ** __restrict root) if (!root || !*root) return -1; - TAILQ_FOREACH(task, &(*root)->root_read, task_node) { + TAILQ_FOREACH_SAFE(task, &(*root)->root_read, task_node, tmp) { schedCancel(task); } - TAILQ_FOREACH(task, &(*root)->root_write, task_node) { + TAILQ_FOREACH_SAFE(task, &(*root)->root_write, task_node, tmp) { schedCancel(task); } - TAILQ_FOREACH(task, &(*root)->root_timer, task_node) { + TAILQ_FOREACH_SAFE(task, &(*root)->root_timer, task_node, tmp) { schedCancel(task); } - TAILQ_FOREACH(task, &(*root)->root_event, task_node) { + TAILQ_FOREACH_SAFE(task, &(*root)->root_event, task_node, tmp) { schedCancel(task); } - TAILQ_FOREACH(task, &(*root)->root_eventlo, task_node) { + TAILQ_FOREACH_SAFE(task, &(*root)->root_eventlo, task_node, tmp) { schedCancel(task); } - TAILQ_FOREACH(task, &(*root)->root_ready, task_node) { + TAILQ_FOREACH_SAFE(task, &(*root)->root_ready, task_node, tmp) { schedCancel(task); } @@ -348,7 +347,7 @@ schedCancel(sched_task_t * __restrict task) * * @root = root task * @type = cancel from queue type, if =taskMAX cancel same task from all queues - * @criteria = find task by criteria [CRITERIA_CALL|CRITERIA_ARG|CRITERIA_FD|CRITERIA_VAL|CRITERIA_TV] + * @criteria = find task by criteria [CRITERIA_CALL|CRITERIA_ARG|CRITERIA_FD|CRITERIA_VAL|CRITERIA_TS] * @param = search parameter * @hook = custom cleanup hook function, may be NULL * return: -1 error, -2 error in sub-stage cancel execution, -3 error from custom hook or 0 ok @@ -357,9 +356,9 @@ int schedCancelby(sched_root_task_t * __restrict root, sched_task_type_t type, u_char criteria, void *param, sched_hook_func_t hook) { - sched_task_t *task; + sched_task_t *task, *tmp; sched_queue_t *queue; - int flg = 0; + register int flg = 0; if (!root) return -1; @@ -404,63 +403,60 @@ schedCancelby(sched_root_task_t * __restrict root, sch #ifdef HAVE_LIBPTHREAD pthread_mutex_lock(&root->root_mtx[type]); #endif - TAILQ_FOREACH(task, queue, task_node) - if (criteria == CRITERIA_CALL) { - if (task->task_func == (sched_task_func_t) param) { - flg++; + TAILQ_FOREACH_SAFE(task, queue, task_node, tmp) { + flg ^= flg; + switch (criteria) { + case CRITERIA_CALL: + if (TASK_FUNC(task) == (sched_task_func_t) param) + flg = 1; break; - } - } else if (criteria == CRITERIA_ARG) { - if (task->task_arg == param) { - flg++; + case CRITERIA_ARG: + if (TASK_ARG(task) == param) + flg = 1; break; - } - } else if (criteria == CRITERIA_FD) { - if (TASK_FD(task) == (intptr_t) param) { - flg++; + case CRITERIA_FD: + if (TASK_FD(task) == (intptr_t) param) + flg = 1; break; - } - } else if (criteria == CRITERIA_VAL) { - if (TASK_VAL(task) == (u_long) param) { - flg++; + case CRITERIA_VAL: + if (TASK_VAL(task) == (u_long) param) + flg = 1; break; - } - } else if (criteria == CRITERIA_TV) { - if (!sched_timespeccmp(&TASK_TS(task), (struct timespec*) param, -)) { - flg++; + case CRITERIA_TS: + if (!sched_timespeccmp(&TASK_TS(task), (struct timespec*) param, -)) + flg = 1; break; - } - } else { -#ifdef HAVE_LIBPTHREAD - pthread_mutex_unlock(&root->root_mtx[type]); -#endif - sched_SetErr(EINVAL, "Invalid parameter criteria %d", criteria); - return -1; + default: + sched_SetErr(EINVAL, "Invalid parameter criteria %d", criteria); + flg = -1; } -#ifdef HAVE_LIBPTHREAD - pthread_mutex_unlock(&root->root_mtx[type]); -#endif - if (!flg || !task) /* task not found */ - return 0; + if (flg < 0) + break; + /* cancel choosen task */ + if (flg > 0) { + if (TASK_ROOT(task)->root_hooks.hook_exec.cancel) + if (TASK_ROOT(task)->root_hooks.hook_exec.cancel(task, NULL)) { + flg = -1; + break; + } + /* custom hook */ + if (hook) + if (hook(task, NULL)) { + flg = -3; + break; + } - if (TASK_ROOT(task)->root_hooks.hook_exec.cancel) - if (TASK_ROOT(task)->root_hooks.hook_exec.cancel(task, NULL)) - return -1; - if (hook) - if (hook(task, NULL)) - return -3; + TAILQ_REMOVE(queue, task, task_node); + if (TASK_TYPE(task) != taskUNUSE) + _sched_unuseTask(task); + flg ^= flg; /* ok */ + } + } #ifdef HAVE_LIBPTHREAD - pthread_mutex_lock(&TASK_ROOT(task)->root_mtx[type]); + pthread_mutex_unlock(&root->root_mtx[type]); #endif - TAILQ_REMOVE(queue, task, task_node); -#ifdef HAVE_LIBPTHREAD - pthread_mutex_unlock(&TASK_ROOT(task)->root_mtx[type]); -#endif - - if (TASK_TYPE(task) != taskUNUSE) - _sched_unuseTask(task); - return 0; + return flg; } /* @@ -471,7 +467,7 @@ schedCancelby(sched_root_task_t * __restrict root, sch * return: -1 error or 0 ok */ int -schedRun(sched_root_task_t * __restrict root, volatile intptr_t * __restrict killState) +schedRun(sched_root_task_t *root, volatile intptr_t * __restrict killState) { sched_task_t *task; @@ -481,22 +477,27 @@ schedRun(sched_root_task_t * __restrict root, volatile if (root->root_hooks.hook_exec.run) if (root->root_hooks.hook_exec.run(root, NULL)) return -1; - if (root->root_hooks.hook_exec.fetch) { - if (killState) { - if (root->root_hooks.hook_exec.condition) - while (root->root_hooks.hook_exec.condition(root, (void*) killState)) { - if ((task = root->root_hooks.hook_exec.fetch(root, NULL))) - schedCall(task); - } - else - while (!*killState) { - if ((task = root->root_hooks.hook_exec.fetch(root, NULL))) - schedCall(task); - } - } else - while ((task = root->root_hooks.hook_exec.fetch(root, NULL))) + + if (killState) { + if (root->root_hooks.hook_exec.condition) + /* condition scheduler loop */ + while (root && root->root_hooks.hook_exec.fetch && + root->root_hooks.hook_exec.condition && + root->root_hooks.hook_exec.condition(root, (void*) killState)) { + if ((task = root->root_hooks.hook_exec.fetch(root, NULL))) + schedCall(task); + } + else + /* trigger scheduler loop */ + while (!*killState && root && root->root_hooks.hook_exec.fetch) { + if ((task = root->root_hooks.hook_exec.fetch(root, NULL))) + schedCall(task); + } + } else + /* infinite scheduler loop */ + while (root && root->root_hooks.hook_exec.fetch) + if ((task = root->root_hooks.hook_exec.fetch(root, NULL))) schedCall(task); - } return 0; }