| version 1.19, 2013/08/15 19:10:48 | version 1.34.2.2, 2023/08/31 15:31:17 | 
| Line 12  terms: | Line 12  terms: | 
 | All of the documentation and software included in the ELWIX and AITNET | All of the documentation and software included in the ELWIX and AITNET | 
 | Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org> | Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org> | 
 |  |  | 
| Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 | Copyright 2004 - 2023 | 
 | by Michael Pounov <misho@elwix.org>.  All rights reserved. | by Michael Pounov <misho@elwix.org>.  All rights reserved. | 
 |  |  | 
 | Redistribution and use in source and binary forms, with or without | Redistribution and use in source and binary forms, with or without | 
| Line 82  sched_SetErr(int eno, char *estr, ...) | Line 82  sched_SetErr(int eno, char *estr, ...) | 
 | va_end(lst); | va_end(lst); | 
 | } | } | 
 |  |  | 
 |  |  | 
 |  | /* string support functions directly imported from OpenBSD */ | 
 |  |  | 
 |  | #ifndef HAVE_STRLCAT | 
 |  | /* | 
 |  | * Appends src to string dst of size siz (unlike strncat, siz is the | 
 |  | * full size of dst, not space left).  At most siz-1 characters | 
 |  | * will be copied.  Always NUL terminates (unless siz <= strlen(dst)). | 
 |  | * Returns strlen(src) + MIN(siz, strlen(initial dst)). | 
 |  | * If retval >= siz, truncation occurred. | 
 |  | */ | 
 |  | size_t | 
 |  | strlcat(char * __restrict dst, const char * __restrict src, size_t siz) | 
 |  | { | 
 |  | char *d = dst; | 
 |  | const char *s = src; | 
 |  | size_t n = siz; | 
 |  | size_t dlen; | 
 |  |  | 
 |  | /* Find the end of dst and adjust bytes left but don't go past end */ | 
 |  | while (n-- != 0 && *d != '\0') | 
 |  | d++; | 
 |  | dlen = d - dst; | 
 |  | n = siz - dlen; | 
 |  |  | 
 |  | if (n == 0) | 
 |  | return(dlen + strlen(s)); | 
 |  | while (*s != '\0') { | 
 |  | if (n != 1) { | 
 |  | *d++ = *s; | 
 |  | n--; | 
 |  | } | 
 |  | s++; | 
 |  | } | 
 |  | *d = '\0'; | 
 |  |  | 
 |  | return(dlen + (s - src));       /* count does not include NUL */ | 
 |  | } | 
 |  | #endif | 
 |  | #ifndef HAVE_STRLCPY | 
 |  | /* | 
 |  | * Copy src to string dst of size siz.  At most siz-1 characters | 
 |  | * will be copied.  Always NUL terminates (unless siz == 0). | 
 |  | * Returns strlen(src); if retval >= siz, truncation occurred. | 
 |  | */ | 
 |  | size_t | 
 |  | strlcpy(char * __restrict dst, const char * __restrict src, size_t siz) | 
 |  | { | 
 |  | char *d = dst; | 
 |  | const char *s = src; | 
 |  | size_t n = siz; | 
 |  |  | 
 |  | /* Copy as many bytes as will fit */ | 
 |  | if (n != 0) { | 
 |  | while (--n != 0) { | 
 |  | if ((*d++ = *s++) == '\0') | 
 |  | break; | 
 |  | } | 
 |  | } | 
 |  |  | 
 |  | /* Not enough room in dst, add NUL and traverse rest of src */ | 
 |  | if (n == 0) { | 
 |  | if (siz != 0) | 
 |  | *d = '\0';              /* NUL-terminate dst */ | 
 |  | while (*s++) | 
 |  | ; | 
 |  | } | 
 |  |  | 
 |  | return(s - src - 1);    /* count does not include NUL */ | 
 |  | } | 
 |  | #endif | 
 |  |  | 
 |  |  | 
 | /* Init and prepare scheduler functions */ | /* Init and prepare scheduler functions */ | 
 |  |  | 
 | /* | /* | 
| Line 101  schedRegisterHooks(sched_root_task_t * __restrict root | Line 174  schedRegisterHooks(sched_root_task_t * __restrict root | 
 |  |  | 
 | root->root_hooks.hook_add.read = sched_hook_read; | root->root_hooks.hook_add.read = sched_hook_read; | 
 | root->root_hooks.hook_add.write = sched_hook_write; | root->root_hooks.hook_add.write = sched_hook_write; | 
| root->root_hooks.hook_add.alarm = sched_hook_alarm; | #if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME) && defined(HAVE_TIMER_DELETE) | 
| #if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME) |  | 
 | root->root_hooks.hook_add.rtc = sched_hook_rtc; | root->root_hooks.hook_add.rtc = sched_hook_rtc; | 
 | #endif | #endif | 
 |  | #if SUP_ENABLE == KQ_SUPPORT | 
 |  | root->root_hooks.hook_add.alarm = sched_hook_alarm; | 
 | root->root_hooks.hook_add.node = sched_hook_node; | root->root_hooks.hook_add.node = sched_hook_node; | 
 | root->root_hooks.hook_add.proc = sched_hook_proc; | root->root_hooks.hook_add.proc = sched_hook_proc; | 
 | root->root_hooks.hook_add.signal = sched_hook_signal; |  | 
 | #ifdef EVFILT_USER | #ifdef EVFILT_USER | 
 | root->root_hooks.hook_add.user = sched_hook_user; | root->root_hooks.hook_add.user = sched_hook_user; | 
 | #endif | #endif | 
 |  | #endif  /* KQ_SUPPORT */ | 
 | #ifdef HAVE_LIBPTHREAD | #ifdef HAVE_LIBPTHREAD | 
 | root->root_hooks.hook_add.thread = sched_hook_thread; | root->root_hooks.hook_add.thread = sched_hook_thread; | 
 | #endif | #endif | 
 |  | root->root_hooks.hook_add.signal = sched_hook_signal; | 
 |  |  | 
 | root->root_hooks.hook_exec.cancel = sched_hook_cancel; | root->root_hooks.hook_exec.cancel = sched_hook_cancel; | 
 | root->root_hooks.hook_exec.fetch = sched_hook_fetch; | root->root_hooks.hook_exec.fetch = sched_hook_fetch; | 
| Line 136  schedInit(void ** __restrict data, size_t datlen) | Line 211  schedInit(void ** __restrict data, size_t datlen) | 
 | { | { | 
 | sched_root_task_t *root = NULL; | sched_root_task_t *root = NULL; | 
 | int (*func)(sched_root_task_t *); | int (*func)(sched_root_task_t *); | 
 |  | #if SUP_ENABLE == KQ_SUPPORT | 
 |  | sigset_t ss; | 
 |  | #endif | 
 | #ifdef HAVE_LIBPTHREAD | #ifdef HAVE_LIBPTHREAD | 
 | register int i; | register int i; | 
 | #endif | #endif | 
 |  |  | 
| root = malloc(sizeof(sched_root_task_t)); | root = e_malloc(sizeof(sched_root_task_t)); | 
 | if (!root) { | if (!root) { | 
 | LOGERR; | LOGERR; | 
 | } else { | } else { | 
| Line 153  schedInit(void ** __restrict data, size_t datlen) | Line 231  schedInit(void ** __restrict data, size_t datlen) | 
 | sched_timespecinf(&root->root_poll); | sched_timespecinf(&root->root_poll); | 
 |  |  | 
 | #ifdef HAVE_LIBPTHREAD | #ifdef HAVE_LIBPTHREAD | 
 |  | if (pthread_mutex_init(&root->root_sigmtx, NULL)) { | 
 |  | LOGERR; | 
 |  | e_free(root); | 
 |  | return NULL; | 
 |  | } | 
 |  |  | 
 | for (i = 0; i < taskMAX; i++) | for (i = 0; i < taskMAX; i++) | 
 | if ((errno = pthread_mutex_init(&root->root_mtx[i], NULL))) { | if ((errno = pthread_mutex_init(&root->root_mtx[i], NULL))) { | 
 | LOGERR; | LOGERR; | 
 | while (i) | while (i) | 
 | pthread_mutex_destroy(&root->root_mtx[--i]); | pthread_mutex_destroy(&root->root_mtx[--i]); | 
| free(root); | e_free(root); | 
 | return NULL; | return NULL; | 
 | } | } | 
 |  |  | 
| Line 187  schedInit(void ** __restrict data, size_t datlen) | Line 271  schedInit(void ** __restrict data, size_t datlen) | 
 | #ifdef HAVE_LIBPTHREAD | #ifdef HAVE_LIBPTHREAD | 
 | for (i = 0; i < taskMAX; i++) | for (i = 0; i < taskMAX; i++) | 
 | pthread_mutex_unlock(&root->root_mtx[i]); | pthread_mutex_unlock(&root->root_mtx[i]); | 
 |  |  | 
 |  | #if SUP_ENABLE == KQ_SUPPORT | 
 |  | sigfillset(&ss); | 
 |  | pthread_sigmask(SIG_BLOCK, &ss, &root->root_oldset); | 
 |  | #else | 
 |  | pthread_sigmask(SIG_BLOCK, NULL, &root->root_oldset); | 
 | #endif | #endif | 
 |  | #else | 
 |  | sigprocmask(SIG_BLOCK, NULL, &root->root_oldset); | 
 |  | #endif | 
 |  |  | 
 | if (data && *data) { | if (data && *data) { | 
 | if (datlen) { | if (datlen) { | 
| Line 224  schedEnd(sched_root_task_t ** __restrict root) | Line 317  schedEnd(sched_root_task_t ** __restrict root) | 
 | if (!root || !*root) | if (!root || !*root) | 
 | return -1; | return -1; | 
 |  |  | 
 |  | #if 0 | 
 | TAILQ_FOREACH_SAFE(task, &(*root)->root_read, task_node, tmp) | TAILQ_FOREACH_SAFE(task, &(*root)->root_read, task_node, tmp) | 
 |  | printf("read=%p\n", task); | 
 |  | TAILQ_FOREACH_SAFE(task, &(*root)->root_write, task_node, tmp) | 
 |  | printf("write=%p\n", task); | 
 |  | TAILQ_FOREACH_SAFE(task, &(*root)->root_timer, task_node, tmp) | 
 |  | printf("timer=%p\n", task); | 
 |  | TAILQ_FOREACH_SAFE(task, &(*root)->root_alarm, task_node, tmp) | 
 |  | printf("alarm=%p\n", task); | 
 |  | TAILQ_FOREACH_SAFE(task, &(*root)->root_rtc, task_node, tmp) | 
 |  | printf("rtc=%p\n", task); | 
 |  | TAILQ_FOREACH_SAFE(task, &(*root)->root_node, task_node, tmp) | 
 |  | printf("node=%p\n", task); | 
 |  | TAILQ_FOREACH_SAFE(task, &(*root)->root_proc, task_node, tmp) | 
 |  | printf("proc=%p\n", task); | 
 |  | TAILQ_FOREACH_SAFE(task, &(*root)->root_signal, task_node, tmp) | 
 |  | printf("signal=%p\n", task); | 
 |  | TAILQ_FOREACH_SAFE(task, &(*root)->root_aio, task_node, tmp) | 
 |  | printf("aio=%p\n", task); | 
 |  | TAILQ_FOREACH_SAFE(task, &(*root)->root_lio, task_node, tmp) | 
 |  | printf("lio=%p\n", task); | 
 |  | TAILQ_FOREACH_SAFE(task, &(*root)->root_user, task_node, tmp) | 
 |  | printf("user=%p\n", task); | 
 |  | TAILQ_FOREACH_SAFE(task, &(*root)->root_event, task_node, tmp) | 
 |  | printf("event=%p\n", task); | 
 |  | TAILQ_FOREACH_SAFE(task, &(*root)->root_suspend, task_node, tmp) | 
 |  | printf("suspend=%p\n", task); | 
 |  | TAILQ_FOREACH_SAFE(task, &(*root)->root_ready, task_node, tmp) | 
 |  | printf("ready=%p\n", task); | 
 |  | TAILQ_FOREACH_SAFE(task, &(*root)->root_thread, task_node, tmp) | 
 |  | printf("thread=%p\n", task); | 
 |  | TAILQ_FOREACH_SAFE(task, &(*root)->root_task, task_node, tmp) | 
 |  | printf("task=%p\n", task); | 
 |  | TAILQ_FOREACH_SAFE(task, &(*root)->root_unuse, task_node, tmp) | 
 |  | printf("unuse=%p\n", task); | 
 |  | fflush(stdout); | 
 |  | #endif | 
 |  |  | 
 |  | TAILQ_FOREACH_SAFE(task, &(*root)->root_read, task_node, tmp) | 
 | schedCancel(task); | schedCancel(task); | 
 | TAILQ_FOREACH_SAFE(task, &(*root)->root_write, task_node, tmp) | TAILQ_FOREACH_SAFE(task, &(*root)->root_write, task_node, tmp) | 
 | schedCancel(task); | schedCancel(task); | 
| Line 257  schedEnd(sched_root_task_t ** __restrict root) | Line 388  schedEnd(sched_root_task_t ** __restrict root) | 
 | TAILQ_FOREACH_SAFE(task, &(*root)->root_task, task_node, tmp) | TAILQ_FOREACH_SAFE(task, &(*root)->root_task, task_node, tmp) | 
 | schedCancel(task); | schedCancel(task); | 
 |  |  | 
| #ifdef HAVE_LIBPTHREAD | SCHED_QLOCK((*root), taskUNUSE); | 
| pthread_mutex_lock(&(*root)->root_mtx[taskUNUSE]); |  | 
| #endif |  | 
 | TAILQ_FOREACH_SAFE(task, &(*root)->root_unuse, task_node, tmp) { | TAILQ_FOREACH_SAFE(task, &(*root)->root_unuse, task_node, tmp) { | 
 | TAILQ_REMOVE(&(*root)->root_unuse, task, task_node); | TAILQ_REMOVE(&(*root)->root_unuse, task, task_node); | 
| free(task); | e_free(task); | 
 | } | } | 
| #ifdef HAVE_LIBPTHREAD | SCHED_QUNLOCK((*root), taskUNUSE); | 
| pthread_mutex_unlock(&(*root)->root_mtx[taskUNUSE]); |  | 
| #endif |  | 
 |  |  | 
 | if ((*root)->root_hooks.hook_root.fini) | if ((*root)->root_hooks.hook_root.fini) | 
 | (*root)->root_hooks.hook_root.fini(*root, NULL); | (*root)->root_hooks.hook_root.fini(*root, NULL); | 
 |  |  | 
 | #ifdef HAVE_LIBPTHREAD | #ifdef HAVE_LIBPTHREAD | 
| for (i = 0; i < taskMAX; i++) | for (i = 0; i < taskMAX; i++) { | 
|  | SCHED_QTRYLOCK(*root, i); | 
|  | SCHED_QUNLOCK(*root, i); | 
 | pthread_mutex_destroy(&(*root)->root_mtx[i]); | pthread_mutex_destroy(&(*root)->root_mtx[i]); | 
 |  | } | 
 |  |  | 
 |  | if ((*root)->root_sigthr) { | 
 |  | pthread_cancel((*root)->root_sigthr); | 
 |  | #ifdef __linux__ | 
 |  | (*root)->root_sigthr = 0L; | 
 |  | #else | 
 |  | (*root)->root_sigthr = NULL; | 
 | #endif | #endif | 
 |  | pthread_sigmask(SIG_SETMASK, &(*root)->root_oldset, NULL); | 
 |  | pthread_mutex_unlock(&(*root)->root_sigmtx); | 
 |  | } | 
 |  | pthread_mutex_destroy(&(*root)->root_sigmtx); | 
 |  | #else | 
 |  | sigprocmask(SIG_SETMASK, &(*root)->root_oldset, NULL); | 
 |  | #endif | 
 |  |  | 
| free(*root); | e_free(*root); | 
 | *root = NULL; | *root = NULL; | 
 | return 0; | return 0; | 
 | } | } | 
| Line 335  schedFetch(sched_root_task_t * __restrict root) | Line 479  schedFetch(sched_root_task_t * __restrict root) | 
 | int | int | 
 | schedTrigger(sched_task_t * __restrict task) | schedTrigger(sched_task_t * __restrict task) | 
 | { | { | 
 |  | #if SUP_ENABLE != KQ_SUPPORT | 
 |  | sched_SetErr(ENOTSUP, "disabled kqueue support"); | 
 |  | return -1; | 
 |  | #else | 
 | #ifndef EVFILT_USER | #ifndef EVFILT_USER | 
 | sched_SetErr(ENOTSUP, "Not supported kevent() filter"); | sched_SetErr(ENOTSUP, "Not supported kevent() filter"); | 
 | return -1; | return -1; | 
| Line 357  schedTrigger(sched_task_t * __restrict task) | Line 505  schedTrigger(sched_task_t * __restrict task) | 
 |  |  | 
 | return 0; | return 0; | 
 | #endif | #endif | 
 |  | #endif  /* KQ_SUPPORT */ | 
 | } | } | 
 |  |  | 
 | /* | /* | 
 |  | * schedQuery() - Query task in scheduler | 
 |  | * | 
 |  | * @task = task | 
 |  | * return: -1 error, 0 found  and 1 not found | 
 |  | */ | 
 |  | int | 
 |  | schedQuery(sched_task_t * __restrict task) | 
 |  | { | 
 |  | sched_queue_t *queue; | 
 |  | sched_task_t *t; | 
 |  |  | 
 |  | if (!task || !TASK_ROOT(task)) | 
 |  | return -1;      /* error */ | 
 |  |  | 
 |  | switch (TASK_TYPE(task)) { | 
 |  | case taskREAD: | 
 |  | queue = &TASK_ROOT(task)->root_read; | 
 |  | break; | 
 |  | case taskWRITE: | 
 |  | queue = &TASK_ROOT(task)->root_write; | 
 |  | break; | 
 |  | case taskTIMER: | 
 |  | queue = &TASK_ROOT(task)->root_timer; | 
 |  | break; | 
 |  | case taskALARM: | 
 |  | queue = &TASK_ROOT(task)->root_alarm; | 
 |  | break; | 
 |  | case taskRTC: | 
 |  | queue = &TASK_ROOT(task)->root_rtc; | 
 |  | break; | 
 |  | case taskNODE: | 
 |  | queue = &TASK_ROOT(task)->root_node; | 
 |  | break; | 
 |  | case taskPROC: | 
 |  | queue = &TASK_ROOT(task)->root_proc; | 
 |  | break; | 
 |  | case taskSIGNAL: | 
 |  | queue = &TASK_ROOT(task)->root_signal; | 
 |  | break; | 
 |  | case taskAIO: | 
 |  | queue = &TASK_ROOT(task)->root_aio; | 
 |  | break; | 
 |  | case taskLIO: | 
 |  | queue = &TASK_ROOT(task)->root_lio; | 
 |  | break; | 
 |  | case taskUSER: | 
 |  | queue = &TASK_ROOT(task)->root_user; | 
 |  | break; | 
 |  | case taskEVENT: | 
 |  | queue = &TASK_ROOT(task)->root_event; | 
 |  | break; | 
 |  | case taskTASK: | 
 |  | queue = &TASK_ROOT(task)->root_task; | 
 |  | break; | 
 |  | case taskSUSPEND: | 
 |  | queue = &TASK_ROOT(task)->root_suspend; | 
 |  | break; | 
 |  | case taskREADY: | 
 |  | queue = &TASK_ROOT(task)->root_ready; | 
 |  | break; | 
 |  | case taskTHREAD: | 
 |  | queue = &TASK_ROOT(task)->root_thread; | 
 |  | break; | 
 |  | default: | 
 |  | return 1;       /* not in queue */ | 
 |  | } | 
 |  | if (queue) | 
 |  | TAILQ_FOREACH(t, queue, task_node) | 
 |  | if (TASK_ID(t) == TASK_ID(task)) | 
 |  | return 0;       /* found */ | 
 |  |  | 
 |  | return 1;       /* not in queue */ | 
 |  | } | 
 |  |  | 
 |  | /* | 
 |  | * schedQueryby() - Query task in scheduler by criteria | 
 |  | * | 
 |  | * @root = root task | 
 |  | * @type = query from queue type, if =taskMAX query same task from all queues | 
 |  | * @criteria = find task by criteria | 
 |  | *      [ CRITERIA_ANY|CRITERIA_CALL|CRITERIA_ARG|CRITERIA_FD|CRITERIA_VAL| | 
 |  | *              CRITERIA_ID|CRITERIA_TS|CRITERIA_DATA|CRITERIA_DATLEN ] | 
 |  | * @param = search parameter | 
 |  | * return: NULL not found or !=NULL task | 
 |  | */ | 
 |  | sched_task_t * | 
 |  | schedQueryby(sched_root_task_t * __restrict root, sched_task_type_t type, | 
 |  | u_char criteria, void *param) | 
 |  | { | 
 |  | sched_task_t *task; | 
 |  | sched_queue_t *queue; | 
 |  |  | 
 |  | if (!root) | 
 |  | return NULL; | 
 |  | /* if type == taskMAX check in all queues */ | 
 |  | if (type == taskMAX) { | 
 |  | if ((task = schedQueryby(root, taskREAD, criteria, param))) | 
 |  | return task; | 
 |  | if ((task = schedQueryby(root, taskWRITE, criteria, param))) | 
 |  | return task; | 
 |  | if ((task = schedQueryby(root, taskTIMER, criteria, param))) | 
 |  | return task; | 
 |  | if ((task = schedQueryby(root, taskALARM, criteria, param))) | 
 |  | return task; | 
 |  | if ((task = schedQueryby(root, taskRTC, criteria, param))) | 
 |  | return task; | 
 |  | if ((task = schedQueryby(root, taskNODE, criteria, param))) | 
 |  | return task; | 
 |  | if ((task = schedQueryby(root, taskPROC, criteria, param))) | 
 |  | return task; | 
 |  | if ((task = schedQueryby(root, taskSIGNAL, criteria, param))) | 
 |  | return task; | 
 |  | if ((task = schedQueryby(root, taskAIO, criteria, param))) | 
 |  | return task; | 
 |  | if ((task = schedQueryby(root, taskLIO, criteria, param))) | 
 |  | return task; | 
 |  | if ((task = schedQueryby(root, taskUSER, criteria, param))) | 
 |  | return task; | 
 |  | if ((task = schedQueryby(root, taskEVENT, criteria, param))) | 
 |  | return task; | 
 |  | if ((task = schedQueryby(root, taskTASK, criteria, param))) | 
 |  | return task; | 
 |  | if ((task = schedQueryby(root, taskSUSPEND, criteria, param))) | 
 |  | return task; | 
 |  | if ((task = schedQueryby(root, taskREADY, criteria, param))) | 
 |  | return task; | 
 |  | if ((task = schedQueryby(root, taskTHREAD, criteria, param))) | 
 |  | return task; | 
 |  | return NULL;    /* not found */ | 
 |  | } | 
 |  | /* choosen queue */ | 
 |  | switch (type) { | 
 |  | case taskREAD: | 
 |  | queue = &root->root_read; | 
 |  | break; | 
 |  | case taskWRITE: | 
 |  | queue = &root->root_write; | 
 |  | break; | 
 |  | case taskTIMER: | 
 |  | queue = &root->root_timer; | 
 |  | break; | 
 |  | case taskALARM: | 
 |  | queue = &root->root_alarm; | 
 |  | break; | 
 |  | case taskRTC: | 
 |  | queue = &root->root_rtc; | 
 |  | break; | 
 |  | case taskNODE: | 
 |  | queue = &root->root_node; | 
 |  | break; | 
 |  | case taskPROC: | 
 |  | queue = &root->root_proc; | 
 |  | break; | 
 |  | case taskSIGNAL: | 
 |  | queue = &root->root_signal; | 
 |  | break; | 
 |  | case taskAIO: | 
 |  | queue = &root->root_aio; | 
 |  | break; | 
 |  | case taskLIO: | 
 |  | queue = &root->root_lio; | 
 |  | break; | 
 |  | case taskUSER: | 
 |  | queue = &root->root_user; | 
 |  | break; | 
 |  | case taskEVENT: | 
 |  | queue = &root->root_event; | 
 |  | break; | 
 |  | case taskTASK: | 
 |  | queue = &root->root_task; | 
 |  | break; | 
 |  | case taskSUSPEND: | 
 |  | queue = &root->root_suspend; | 
 |  | break; | 
 |  | case taskREADY: | 
 |  | queue = &root->root_ready; | 
 |  | break; | 
 |  | case taskTHREAD: | 
 |  | queue = &root->root_thread; | 
 |  | break; | 
 |  | default: | 
 |  | return NULL;    /* not found */ | 
 |  | } | 
 |  |  | 
 |  | TAILQ_FOREACH(task, queue, task_node) { | 
 |  | switch (criteria) { | 
 |  | case CRITERIA_ANY: | 
 |  | return task;            /* found */ | 
 |  | case CRITERIA_CALL: | 
 |  | if (TASK_FUNC(task) == (sched_task_func_t) param) | 
 |  | return task;    /* found */ | 
 |  | break; | 
 |  | case CRITERIA_ARG: | 
 |  | if (TASK_ARG(task) == param) | 
 |  | return task;    /* found */ | 
 |  | break; | 
 |  | case CRITERIA_FD: | 
 |  | if (TASK_FD(task) == (intptr_t) param) | 
 |  | return task;    /* found */ | 
 |  | break; | 
 |  | case CRITERIA_ID: | 
 |  | case CRITERIA_VAL: | 
 |  | if (TASK_VAL(task) == (u_long) param) | 
 |  | return task;    /* found */ | 
 |  | break; | 
 |  | case CRITERIA_TS: | 
 |  | if (!sched_timespeccmp(&TASK_TS(task), | 
 |  | (struct timespec*) param, -)) | 
 |  | return task;    /* found */ | 
 |  | break; | 
 |  | case CRITERIA_DATA: | 
 |  | if (TASK_DATA(task) == param) | 
 |  | return task;    /* found */ | 
 |  | break; | 
 |  | case CRITERIA_DATLEN: | 
 |  | if (TASK_DATLEN(task) == (size_t) param) | 
 |  | return task;    /* found */ | 
 |  | break; | 
 |  | default: | 
 |  | sched_SetErr(EINVAL, "Invalid parameter criteria %d", | 
 |  | criteria); | 
 |  | return NULL;            /* not found */ | 
 |  | } | 
 |  | } | 
 |  |  | 
 |  | return NULL;    /* not found */ | 
 |  | } | 
 |  |  | 
 |  | /* | 
 | * schedCancel() - Cancel task from scheduler | * schedCancel() - Cancel task from scheduler | 
 | * | * | 
 | * @task = task | * @task = task | 
| Line 429  schedCancel(sched_task_t * __restrict task) | Line 807  schedCancel(sched_task_t * __restrict task) | 
 | default: | default: | 
 | queue = NULL; | queue = NULL; | 
 | } | } | 
| if (queue) { | if (queue) | 
| #ifdef HAVE_LIBPTHREAD | remove_task_from(task, queue); | 
| pthread_mutex_lock(&TASK_ROOT(task)->root_mtx[TASK_TYPE(task)]); |  | 
| #endif |  | 
| TAILQ_REMOVE(queue, TASK_ID(task), task_node); |  | 
| #ifdef HAVE_LIBPTHREAD |  | 
| pthread_mutex_unlock(&TASK_ROOT(task)->root_mtx[TASK_TYPE(task)]); |  | 
| #endif |  | 
| } |  | 
 | if (TASK_TYPE(task) != taskUNUSE) | if (TASK_TYPE(task) != taskUNUSE) | 
 | sched_unuseTask(task); | sched_unuseTask(task); | 
 |  |  | 
| Line 450  schedCancel(sched_task_t * __restrict task) | Line 821  schedCancel(sched_task_t * __restrict task) | 
 | * @root = root task | * @root = root task | 
 | * @type = cancel from queue type, if =taskMAX cancel same task from all queues | * @type = cancel from queue type, if =taskMAX cancel same task from all queues | 
 | * @criteria = find task by criteria | * @criteria = find task by criteria | 
| *      [CRITERIA_ANY|CRITERIA_CALL|CRITERIA_ARG|CRITERIA_FD|CRITERIA_VAL|CRITERIA_ID|CRITERIA_TS|CRITERIA_DATA] | *      [ CRITERIA_ANY|CRITERIA_CALL|CRITERIA_ARG|CRITERIA_FD|CRITERIA_VAL| | 
|  | *                CRITERIA_ID|CRITERIA_TS|CRITERIA_DATA|CRITERIA_DATLEN ] | 
 | * @param = search parameter | * @param = search parameter | 
 | * @hook = custom cleanup hook function, may be NULL | * @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 | * return: -1 error, -2 error in sub-stage cancel execution, -3 error from custom hook or 0 ok | 
| Line 555  schedCancelby(sched_root_task_t * __restrict root, sch | Line 927  schedCancelby(sched_root_task_t * __restrict root, sch | 
 | return 0; | return 0; | 
 | } | } | 
 |  |  | 
| #ifdef HAVE_LIBPTHREAD | SCHED_QLOCK(root, type); | 
| pthread_mutex_lock(&root->root_mtx[type]); |  | 
| #endif |  | 
 | TAILQ_FOREACH_SAFE(task, queue, task_node, tmp) { | TAILQ_FOREACH_SAFE(task, queue, task_node, tmp) { | 
 | flg ^= flg; | flg ^= flg; | 
 | switch (criteria) { | switch (criteria) { | 
| Line 589  schedCancelby(sched_root_task_t * __restrict root, sch | Line 959  schedCancelby(sched_root_task_t * __restrict root, sch | 
 | if (TASK_DATA(task) == param) | if (TASK_DATA(task) == param) | 
 | flg = 1; | flg = 1; | 
 | break; | break; | 
 |  | case CRITERIA_DATLEN: | 
 |  | if (TASK_DATLEN(task) == (size_t) param) | 
 |  | flg = 1; | 
 |  | break; | 
 | default: | default: | 
 | sched_SetErr(EINVAL, "Invalid parameter criteria %d", criteria); | sched_SetErr(EINVAL, "Invalid parameter criteria %d", criteria); | 
 | flg = -1; | flg = -1; | 
| Line 616  schedCancelby(sched_root_task_t * __restrict root, sch | Line 990  schedCancelby(sched_root_task_t * __restrict root, sch | 
 | flg ^= flg;     /* ok */ | flg ^= flg;     /* ok */ | 
 | } | } | 
 | } | } | 
| #ifdef HAVE_LIBPTHREAD | SCHED_QUNLOCK(root, type); | 
| pthread_mutex_unlock(&root->root_mtx[type]); |  | 
| #endif |  | 
 | return flg; | return flg; | 
 | } | } | 
 |  |  | 
| Line 699  schedPolling(sched_root_task_t * __restrict root, stru | Line 1072  schedPolling(sched_root_task_t * __restrict root, stru | 
 | * return: -1 error or 0 ok | * return: -1 error or 0 ok | 
 | */ | */ | 
 | int | int | 
| schedTermCondition(sched_root_task_t * __restrict root, intptr_t condValue) | schedTermCondition(sched_root_task_t * __restrict root, intptr_t * __restrict condValue) | 
 | { | { | 
| if (!root) | if (!root && !condValue) | 
 | return -1; | return -1; | 
 |  |  | 
| root->root_cond = condValue; | *root->root_cond = *condValue; | 
 | root->root_hooks.hook_exec.condition = sched_hook_condition; | root->root_hooks.hook_exec.condition = sched_hook_condition; | 
 | return 0; | return 0; | 
 | } | } | 
| Line 714  schedTermCondition(sched_root_task_t * __restrict root | Line 1087  schedTermCondition(sched_root_task_t * __restrict root | 
 | * | * | 
 | * @root = root task | * @root = root task | 
 | * @criteria = find task by criteria | * @criteria = find task by criteria | 
| *      [CRITERIA_ANY|CRITERIA_ID|CRITERIA_DATA] | *      [CRITERIA_ANY|CRITERIA_ID|CRITERIA_VAL|CRITERIA_DATA] | 
| * @param = search parameter (sched_task_t *task| u_long id) | * @param = search parameter (sched_task_t *task| unsigned long id) | 
 | * return: -1 error or 0 resumed ok | * return: -1 error or 0 resumed ok | 
 | */ | */ | 
 | int | int | 
| Line 727  schedResumeby(sched_root_task_t * __restrict root, u_c | Line 1100  schedResumeby(sched_root_task_t * __restrict root, u_c | 
 | if (!root) | if (!root) | 
 | return -1; | return -1; | 
 |  |  | 
| #ifdef HAVE_LIBPTHREAD | SCHED_QLOCK(root, taskSUSPEND); | 
| pthread_mutex_lock(&root->root_mtx[taskSUSPEND]); |  | 
| #endif |  | 
 | TAILQ_FOREACH_SAFE(task, &root->root_suspend, task_node, tmp) { | TAILQ_FOREACH_SAFE(task, &root->root_suspend, task_node, tmp) { | 
 | flg ^= flg; | flg ^= flg; | 
 | switch (criteria) { | switch (criteria) { | 
| Line 737  schedResumeby(sched_root_task_t * __restrict root, u_c | Line 1108  schedResumeby(sched_root_task_t * __restrict root, u_c | 
 | flg = 1; | flg = 1; | 
 | break; | break; | 
 | case CRITERIA_ID: | case CRITERIA_ID: | 
 |  | case CRITERIA_VAL: | 
 | if (TASK_VAL(task) == (u_long) param) | if (TASK_VAL(task) == (u_long) param) | 
 | flg = 1; | flg = 1; | 
 | break; | break; | 
| Line 761  schedResumeby(sched_root_task_t * __restrict root, u_c | Line 1133  schedResumeby(sched_root_task_t * __restrict root, u_c | 
 | TAILQ_REMOVE(&root->root_suspend, task, task_node); | TAILQ_REMOVE(&root->root_suspend, task, task_node); | 
 |  |  | 
 | task->task_type = taskREADY; | task->task_type = taskREADY; | 
| #ifdef HAVE_LIBPTHREAD | insert_task_to(task, &root->root_ready); | 
| pthread_mutex_lock(&root->root_mtx[taskREADY]); |  | 
| #endif |  | 
| TAILQ_INSERT_TAIL(&root->root_ready, task, task_node); |  | 
| #ifdef HAVE_LIBPTHREAD |  | 
| pthread_mutex_unlock(&root->root_mtx[taskREADY]); |  | 
| #endif |  | 
 |  |  | 
 | flg ^= flg;     /* ok */ | flg ^= flg;     /* ok */ | 
 | } | } | 
 | } | } | 
| #ifdef HAVE_LIBPTHREAD | SCHED_QUNLOCK(root, taskSUSPEND); | 
| pthread_mutex_unlock(&root->root_mtx[taskSUSPEND]); |  | 
| #endif |  | 
 |  |  | 
 | return flg; | return flg; | 
 |  | } | 
 |  |  | 
 |  | static void * | 
 |  | _sched_sigDisp(void *arg) | 
 |  | { | 
 |  | sched_root_task_t *root = arg; | 
 |  | sched_task_t *task, *tmp; | 
 |  | int sig, flg; | 
 |  | sigset_t ss; | 
 |  |  | 
 |  | sigfillset(&ss); | 
 |  | while (root->root_sigthr) { | 
 |  | if (sigwait(&ss, &sig)) | 
 |  | continue; | 
 |  |  | 
 |  | pthread_mutex_lock(&root->root_sigmtx); | 
 |  | if (!sigismember(&root->root_sigset, sig)) { | 
 |  | pthread_mutex_unlock(&root->root_sigmtx); | 
 |  | continue; | 
 |  | } | 
 |  |  | 
 |  | flg = 0; | 
 |  | TAILQ_FOREACH_SAFE(task, &root->root_signal, task_node, tmp) { | 
 |  | if (TASK_VAL(task) == (uintptr_t) sig) { | 
 |  | if (!flg) { | 
 |  | TASK_RET(task) = 0; | 
 |  | TASK_FLAG(task) = 0; | 
 |  |  | 
 |  | /* remove signal handle */ | 
 |  | transit_task2ready(task, &root->root_signal); | 
 |  | } | 
 |  | flg++; | 
 |  | } | 
 |  | } | 
 |  | if (flg < 2) | 
 |  | sigdelset(&root->root_sigset, sig); | 
 |  |  | 
 |  | pthread_mutex_unlock(&root->root_sigmtx); | 
 |  | } | 
 |  |  | 
 |  | return NULL; | 
 |  | } | 
 |  |  | 
 |  | /* | 
 |  | * schedSignalDispatch() - Activate or Deactivate signal dispatcher | 
 |  | * | 
 |  | * @root = root task | 
 |  | * @on = Activate or =0 deactivate | 
 |  | * return: -1 error or 0 ok | 
 |  | */ | 
 |  | int | 
 |  | schedSignalDispatch(sched_root_task_t * __restrict root, int on) | 
 |  | { | 
 |  | sigset_t ss; | 
 |  | struct timespec ts = { .tv_sec = 1, .tv_nsec = 0 }; | 
 |  | #ifndef HAVE_LIBPTHREAD | 
 |  | sched_SetErr(ENOTSUP, "Library has not support pthreads"); | 
 |  | return -1; | 
 |  | #else | 
 |  | pthread_attr_t attr; | 
 |  | #endif | 
 |  |  | 
 |  | #if SUP_ENABLE == KQ_SUPPORT | 
 |  | return 0; | 
 |  | #endif | 
 |  |  | 
 |  | if (!on) { | 
 |  | pthread_cancel(root->root_sigthr); | 
 |  | #ifdef __linux__ | 
 |  | root->root_sigthr = 0L; | 
 |  | #else | 
 |  | root->root_sigthr = NULL; | 
 |  | #endif | 
 |  | return 0; | 
 |  | } | 
 |  |  | 
 |  | /* if we have not using polling, then we must turn on */ | 
 |  | if (sched_timespecisinf(&root->root_poll)) | 
 |  | schedPolling(root, &ts, NULL); | 
 |  |  | 
 |  | pthread_attr_init(&attr); | 
 |  | pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); | 
 |  | #ifdef SCHED_RR | 
 |  | pthread_attr_setschedpolicy(&attr, SCHED_RR); | 
 |  | #else | 
 |  | pthread_attr_setschedpolicy(&attr, SCHED_OTHER); | 
 |  | #endif | 
 |  |  | 
 |  | sigfillset(&ss); | 
 |  | pthread_sigmask(SIG_BLOCK, &ss, NULL); | 
 |  |  | 
 |  | if (pthread_create(&root->root_sigthr, &attr, _sched_sigDisp, root)) { | 
 |  | sched_SetErr(errno, "pthread_create(SignalDispatch) #%d - %s", | 
 |  | errno, strerror(errno)); | 
 |  | #ifdef __linux__ | 
 |  | root->root_sigthr = 0L; | 
 |  | #else | 
 |  | root->root_sigthr = NULL; | 
 |  | #endif | 
 |  | pthread_sigmask(SIG_SETMASK, &root->root_oldset, NULL); | 
 |  | return -1; | 
 |  | } | 
 |  |  | 
 |  | return 0; | 
 | } | } |