| 
version 1.4.2.3, 2012/01/24 14:04:58
 | 
version 1.30.6.2, 2023/02/24 16:21:23
 | 
| 
 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 | 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 46  SUCH DAMAGE.
 | 
 Line 46  SUCH DAMAGE.
 | 
 |  #include "global.h" | 
  #include "global.h" | 
 |   | 
   | 
 |   | 
   | 
| #pragma GCC visibility push(hidden) | /* | 
 |  * sched_useTask() - Get and init new task | 
| inline sched_task_t * |  * | 
| _sched_useTask(sched_root_task_t * __restrict root) |  * @root = root task | 
|   |  * return: NULL error or !=NULL prepared task | 
|   |  */ | 
|   | sched_task_t * | 
|   | sched_useTask(sched_root_task_t * __restrict root) | 
 |  { | 
  { | 
|         sched_task_t *task; |         sched_task_t *task, *tmp; | 
 |   | 
   | 
|         TAILQ_FOREACH(task, &root->root_unuse, task_node) { |         SCHED_QLOCK(root, taskUNUSE); | 
|   |         TAILQ_FOREACH_SAFE(task, &root->root_unuse, task_node, tmp) { | 
 |                  if (!TASK_ISLOCKED(task)) { | 
                  if (!TASK_ISLOCKED(task)) { | 
 |  #ifdef HAVE_LIBPTHREAD | 
   | 
 |                          pthread_mutex_lock(&root->root_mtx[taskUNUSE]); | 
   | 
 |  #endif | 
   | 
 |                          TAILQ_REMOVE(&root->root_unuse, task, task_node); | 
                          TAILQ_REMOVE(&root->root_unuse, task, task_node); | 
 |  #ifdef HAVE_LIBPTHREAD | 
   | 
 |                          pthread_mutex_unlock(&root->root_mtx[taskUNUSE]); | 
   | 
 |  #endif | 
   | 
 |                          break; | 
                          break; | 
 |                  } | 
                  } | 
 |          } | 
          } | 
 |   | 
          SCHED_QUNLOCK(root, taskUNUSE); | 
 |   | 
   | 
 |          if (!task) { | 
          if (!task) { | 
|                 task = malloc(sizeof(sched_task_t)); |                 task = e_malloc(sizeof(sched_task_t)); | 
 |                  if (!task) { | 
                  if (!task) { | 
 |                          LOGERR; | 
                          LOGERR; | 
 |                          return NULL; | 
                          return NULL; | 
 |                  } | 
                  } | 
 |          } | 
          } | 
 |   | 
   | 
 |   | 
          memset(task, 0, sizeof(sched_task_t)); | 
 |   | 
          task->task_id = (uintptr_t) task; | 
 |          return task; | 
          return task; | 
 |  } | 
  } | 
 |   | 
   | 
| inline sched_task_t * | /* | 
| _sched_unuseTask(sched_task_t * __restrict task) |  * sched_unuseTask() - Unlock and put task to unuse queue | 
|   |  * | 
|   |  * @task = task | 
|   |  * return: always is NULL | 
|   |  */ | 
|   | sched_task_t * | 
|   | sched_unuseTask(sched_task_t * __restrict task) | 
 |  { | 
  { | 
 |          TASK_UNLOCK(task); | 
          TASK_UNLOCK(task); | 
 |   | 
   | 
 |          TASK_TYPE(task) = taskUNUSE; | 
          TASK_TYPE(task) = taskUNUSE; | 
| #ifdef HAVE_LIBPTHREAD |         insert_task_to(task, &(TASK_ROOT(task))->root_unuse); | 
|         pthread_mutex_lock(&TASK_ROOT(task)->root_mtx[taskUNUSE]); |   | 
| #endif |   | 
|         TAILQ_INSERT_TAIL(&TASK_ROOT(task)->root_unuse, task, task_node); |   | 
| #ifdef HAVE_LIBPTHREAD |   | 
|         pthread_mutex_unlock(&TASK_ROOT(task)->root_mtx[taskUNUSE]); |   | 
| #endif |   | 
|         task = NULL; |   | 
 |   | 
   | 
 |   | 
          task = NULL; | 
 |          return task; | 
          return task; | 
 |  } | 
  } | 
 |   | 
   | 
| #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 | 
|   |  */ | 
|   | 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 | 
   * schedRead() - Add READ I/O task to scheduler queue | 
 |   | 
   * | 
 |   * @root = root task | 
   * @root = root task | 
 |   * @func = task execution function | 
   * @func = task execution function | 
 |   * @arg = 1st func argument | 
   * @arg = 1st func argument | 
| 
 Line 111  sched_task_t *
 | 
 Line 133  sched_task_t *
 | 
 |  schedRead(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd,  | 
  schedRead(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd,  | 
 |                  void *opt_data, size_t opt_dlen) | 
                  void *opt_data, size_t opt_dlen) | 
 |  { | 
  { | 
 |   | 
          return schedReadExt(root, func, arg, fd, opt_data, opt_dlen, 0); | 
 |   | 
  } | 
 |   | 
   | 
 |   | 
  /* | 
 |   | 
   * schedReadExt() - Add READ I/O task to scheduler queue with custom event mask | 
 |   | 
   * | 
 |   | 
   * @root = root task | 
 |   | 
   * @func = task execution function | 
 |   | 
   * @arg = 1st func argument | 
 |   | 
   * @fd = fd handle | 
 |   | 
   * @opt_data = Optional data | 
 |   | 
   * @opt_dlen = Optional data length | 
 |   | 
   * @mask = Event mask | 
 |   | 
   * return: NULL error or !=NULL new queued task | 
 |   | 
   */ | 
 |   | 
  sched_task_t * | 
 |   | 
  schedReadExt(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd,  | 
 |   | 
                  void *opt_data, size_t opt_dlen, u_long mask) | 
 |   | 
  { | 
 |          sched_task_t *task; | 
          sched_task_t *task; | 
 |          void *ptr; | 
          void *ptr; | 
 |   | 
   | 
| 
 Line 118  schedRead(sched_root_task_t * __restrict root, sched_t
 | 
 Line 159  schedRead(sched_root_task_t * __restrict root, sched_t
 | 
 |                  return NULL; | 
                  return NULL; | 
 |   | 
   | 
 |          /* get new task */ | 
          /* get new task */ | 
|         if (!(task = _sched_useTask(root))) |         if (!(task = sched_useTask(root))) | 
 |                  return NULL; | 
                  return NULL; | 
 |   | 
   | 
|         memset(task, 0, sizeof(sched_task_t)); |         TASK_FUNC(task) = func; | 
|         task->task_id = 0; |   | 
|         task->task_lock = 0; |   | 
|         task->task_func = func; |   | 
 |          TASK_TYPE(task) = taskREAD; | 
          TASK_TYPE(task) = taskREAD; | 
 |          TASK_ROOT(task) = root; | 
          TASK_ROOT(task) = root; | 
 |   | 
   | 
| 
 Line 134  schedRead(sched_root_task_t * __restrict root, sched_t
 | 
 Line 172  schedRead(sched_root_task_t * __restrict root, sched_t
 | 
 |          TASK_DATA(task) = opt_data; | 
          TASK_DATA(task) = opt_data; | 
 |          TASK_DATLEN(task) = opt_dlen; | 
          TASK_DATLEN(task) = opt_dlen; | 
 |   | 
   | 
 |   | 
          TASK_HARG(task) = mask; | 
 |   | 
   | 
 |          if (root->root_hooks.hook_add.read) | 
          if (root->root_hooks.hook_add.read) | 
|                 ptr = root->root_hooks.hook_add.read(task, NULL); |                 ptr = root->root_hooks.hook_add.read(task,  | 
|   |                                 (void*) task->task_harg); | 
 |          else | 
          else | 
 |                  ptr = NULL; | 
                  ptr = NULL; | 
 |   | 
   | 
|         if (!ptr) { |         if (!ptr) | 
| #ifdef HAVE_LIBPTHREAD |                 insert_task_to(task, &root->root_read); | 
|                 pthread_mutex_lock(&root->root_mtx[taskREAD]); |         else | 
| #endif |                 task = sched_unuseTask(task); | 
|                 TAILQ_INSERT_TAIL(&root->root_read, task, task_node); |   | 
| #ifdef HAVE_LIBPTHREAD |   | 
|                 pthread_mutex_unlock(&root->root_mtx[taskREAD]); |   | 
| #endif |   | 
|         } else |   | 
|                 task = _sched_unuseTask(task); |   | 
 |   | 
   | 
 |          return task; | 
          return task; | 
 |  } | 
  } | 
 |   | 
   | 
 |  /* | 
  /* | 
 |   * schedWrite() - Add WRITE I/O task to scheduler queue | 
   * schedWrite() - Add WRITE I/O task to scheduler queue | 
 |   | 
   * | 
 |   * @root = root task | 
   * @root = root task | 
 |   * @func = task execution function | 
   * @func = task execution function | 
 |   * @arg = 1st func argument | 
   * @arg = 1st func argument | 
| 
 Line 167  sched_task_t *
 | 
 Line 203  sched_task_t *
 | 
 |  schedWrite(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd,  | 
  schedWrite(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd,  | 
 |                  void *opt_data, size_t opt_dlen) | 
                  void *opt_data, size_t opt_dlen) | 
 |  { | 
  { | 
 |   | 
          return schedWriteExt(root, func, arg, fd, opt_data, opt_dlen, 0); | 
 |   | 
  } | 
 |   | 
   | 
 |   | 
  /* | 
 |   | 
   * schedWriteExt() - Add WRITE I/O task to scheduler queue with custom event mask | 
 |   | 
   * | 
 |   | 
   * @root = root task | 
 |   | 
   * @func = task execution function | 
 |   | 
   * @arg = 1st func argument | 
 |   | 
   * @fd = fd handle | 
 |   | 
   * @opt_data = Optional data | 
 |   | 
   * @opt_dlen = Optional data length | 
 |   | 
   * @mask = Event mask | 
 |   | 
   * return: NULL error or !=NULL new queued task | 
 |   | 
   */ | 
 |   | 
  sched_task_t * | 
 |   | 
  schedWriteExt(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd,  | 
 |   | 
                  void *opt_data, size_t opt_dlen, u_long mask) | 
 |   | 
  { | 
 |          sched_task_t *task; | 
          sched_task_t *task; | 
 |          void *ptr; | 
          void *ptr; | 
 |   | 
   | 
| 
 Line 174  schedWrite(sched_root_task_t * __restrict root, sched_
 | 
 Line 229  schedWrite(sched_root_task_t * __restrict root, sched_
 | 
 |                  return NULL; | 
                  return NULL; | 
 |   | 
   | 
 |          /* get new task */ | 
          /* get new task */ | 
|         if (!(task = _sched_useTask(root))) |         if (!(task = sched_useTask(root))) | 
 |                  return NULL; | 
                  return NULL; | 
 |   | 
   | 
|         memset(task, 0, sizeof(sched_task_t)); |         TASK_FUNC(task) = func; | 
|         task->task_id = 0; |   | 
|         task->task_lock = 0; |   | 
|         task->task_func = func; |   | 
 |          TASK_TYPE(task) = taskWRITE; | 
          TASK_TYPE(task) = taskWRITE; | 
 |          TASK_ROOT(task) = root; | 
          TASK_ROOT(task) = root; | 
 |   | 
   | 
| 
 Line 190  schedWrite(sched_root_task_t * __restrict root, sched_
 | 
 Line 242  schedWrite(sched_root_task_t * __restrict root, sched_
 | 
 |          TASK_DATA(task) = opt_data; | 
          TASK_DATA(task) = opt_data; | 
 |          TASK_DATLEN(task) = opt_dlen; | 
          TASK_DATLEN(task) = opt_dlen; | 
 |   | 
   | 
 |   | 
          TASK_HARG(task) = mask; | 
 |   | 
   | 
 |          if (root->root_hooks.hook_add.write) | 
          if (root->root_hooks.hook_add.write) | 
|                 ptr = root->root_hooks.hook_add.write(task, NULL); |                 ptr = root->root_hooks.hook_add.write(task,  | 
|   |                                 (void*) task->task_harg); | 
 |          else | 
          else | 
 |                  ptr = NULL; | 
                  ptr = NULL; | 
 |   | 
   | 
|         if (!ptr) { |         if (!ptr) | 
| #ifdef HAVE_LIBPTHREAD |                 insert_task_to(task, &root->root_write); | 
|                 pthread_mutex_lock(&root->root_mtx[taskWRITE]); |         else | 
|   |                 task = sched_unuseTask(task); | 
|   |  | 
|   |         return task; | 
|   | } | 
|   |  | 
|   | /* | 
|   |  * schedNode() - Add NODE task to scheduler queue | 
|   |  * | 
|   |  * @root = root task | 
|   |  * @func = task execution function | 
|   |  * @arg = 1st func argument | 
|   |  * @fd = fd handle | 
|   |  * @opt_data = Optional data | 
|   |  * @opt_dlen = Optional data length | 
|   |  * return: NULL error or !=NULL new queued task | 
|   |  */ | 
|   | sched_task_t * | 
|   | schedNode(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd,  | 
|   |                 void *opt_data, size_t opt_dlen) | 
|   | { | 
|   | #if SUP_ENABLE != KQ_SUPPORT | 
|   |         sched_SetErr(ENOTSUP, "disabled kqueue support"); | 
|   |         return NULL; | 
|   | #else | 
|   |         sched_task_t *task; | 
|   |         void *ptr; | 
|   |  | 
|   |         if (!root || !func) | 
|   |                 return NULL; | 
|   |  | 
|   |         /* get new task */ | 
|   |         if (!(task = sched_useTask(root))) | 
|   |                 return NULL; | 
|   |  | 
|   |         TASK_FUNC(task) = func; | 
|   |         TASK_TYPE(task) = taskNODE; | 
|   |         TASK_ROOT(task) = root; | 
|   |  | 
|   |         TASK_ARG(task) = arg; | 
|   |         TASK_FD(task) = fd; | 
|   |  | 
|   |         TASK_DATA(task) = opt_data; | 
|   |         TASK_DATLEN(task) = opt_dlen; | 
|   |  | 
|   |         if (root->root_hooks.hook_add.node) | 
|   |                 ptr = root->root_hooks.hook_add.node(task, NULL); | 
|   |         else | 
|   |                 ptr = NULL; | 
|   |  | 
|   |         if (!ptr) | 
|   |                 insert_task_to(task, &root->root_node); | 
|   |         else | 
|   |                 task = sched_unuseTask(task); | 
|   |  | 
|   |         return task; | 
|   | #endif  /* KQ_SUPPORT */ | 
|   | } | 
|   |  | 
|   | /* | 
|   |  * schedNode2() - Add NODE task with all events to scheduler queue | 
|   |  * | 
|   |  * @root = root task | 
|   |  * @func = task execution function | 
|   |  * @arg = 1st func argument | 
|   |  * @fd = fd handle | 
|   |  * @opt_data = Optional data | 
|   |  * @opt_dlen = Optional data length | 
|   |  * return: NULL error or !=NULL new queued task | 
|   |  */ | 
|   | sched_task_t * | 
|   | schedNode2(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd,  | 
|   |                 void *opt_data, size_t opt_dlen) | 
|   | { | 
|   | #if SUP_ENABLE != KQ_SUPPORT | 
|   |         sched_SetErr(ENOTSUP, "disabled kqueue support"); | 
|   |         return NULL; | 
|   | #else | 
|   |         sched_task_t *task; | 
|   |         void *ptr; | 
|   |  | 
|   |         if (!root || !func) | 
|   |                 return NULL; | 
|   |  | 
|   |         /* get new task */ | 
|   |         if (!(task = sched_useTask(root))) | 
|   |                 return NULL; | 
|   |  | 
|   |         TASK_FUNC(task) = func; | 
|   |         TASK_TYPE(task) = taskNODE; | 
|   |         TASK_ROOT(task) = root; | 
|   |  | 
|   |         TASK_ARG(task) = arg; | 
|   |         TASK_FD(task) = fd; | 
|   |  | 
|   |         TASK_DATA(task) = opt_data; | 
|   |         TASK_DATLEN(task) = opt_dlen; | 
|   |  | 
|   |         if (root->root_hooks.hook_add.node) | 
|   | #ifdef __FreeBSD__ | 
|   |                 ptr = root->root_hooks.hook_add.node(task,  | 
|   |                                 (void*) (NOTE_READ | NOTE_CLOSE_WRITE | NOTE_CLOSE | NOTE_OPEN)); | 
|   | #else | 
|   |                 ptr = root->root_hooks.hook_add.node(task, NULL); | 
 |  #endif | 
  #endif | 
|                 TAILQ_INSERT_TAIL(&root->root_write, task, task_node); |         else | 
| #ifdef HAVE_LIBPTHREAD |                 ptr = NULL; | 
|                 pthread_mutex_unlock(&root->root_mtx[taskWRITE]); |  | 
| #endif |         if (!ptr) | 
|   |                 insert_task_to(task, &root->root_node); | 
|   |         else | 
|   |                 task = sched_unuseTask(task); | 
|   |  | 
|   |         return task; | 
|   | #endif  /* KQ_SUPPORT */ | 
|   | } | 
|   |  | 
|   | /* | 
|   |  * schedProc() - Add PROC task to scheduler queue | 
|   |  * | 
|   |  * @root = root task | 
|   |  * @func = task execution function | 
|   |  * @arg = 1st func argument | 
|   |  * @pid = PID | 
|   |  * @opt_data = Optional data | 
|   |  * @opt_dlen = Optional data length | 
|   |  * return: NULL error or !=NULL new queued task | 
|   |  */ | 
|   | sched_task_t * | 
|   | schedProc(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, u_long pid,  | 
|   |                 void *opt_data, size_t opt_dlen) | 
|   | { | 
|   | #if SUP_ENABLE != KQ_SUPPORT | 
|   |         sched_SetErr(ENOTSUP, "disabled kqueue support"); | 
|   |         return NULL; | 
|   | #else | 
|   |         sched_task_t *task; | 
|   |         void *ptr; | 
|   |  | 
|   |         if (!root || !func) | 
|   |                 return NULL; | 
|   |  | 
|   |         /* get new task */ | 
|   |         if (!(task = sched_useTask(root))) | 
|   |                 return NULL; | 
|   |  | 
|   |         TASK_FUNC(task) = func; | 
|   |         TASK_TYPE(task) = taskPROC; | 
|   |         TASK_ROOT(task) = root; | 
|   |  | 
|   |         TASK_ARG(task) = arg; | 
|   |         TASK_VAL(task) = pid; | 
|   |  | 
|   |         TASK_DATA(task) = opt_data; | 
|   |         TASK_DATLEN(task) = opt_dlen; | 
|   |  | 
|   |         if (root->root_hooks.hook_add.proc) | 
|   |                 ptr = root->root_hooks.hook_add.proc(task, NULL); | 
|   |         else | 
|   |                 ptr = NULL; | 
|   |  | 
|   |         if (!ptr) | 
|   |                 insert_task_to(task, &root->root_proc); | 
|   |         else | 
|   |                 task = sched_unuseTask(task); | 
|   |  | 
|   |         return task; | 
|   | #endif  /* KQ_SUPPORT */ | 
|   | } | 
|   |  | 
|   | /* | 
|   |  * schedUser() - Add trigger USER task to scheduler queue | 
|   |  * | 
|   |  * @root = root task | 
|   |  * @func = task execution function | 
|   |  * @arg = 1st func argument | 
|   |  * @id = Trigger ID | 
|   |  * @opt_data = Optional data | 
|   |  * @opt_dlen = Optional user's trigger flags | 
|   |  * return: NULL error or !=NULL new queued task | 
|   |  */ | 
|   | sched_task_t * | 
|   | schedUser(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, u_long id,  | 
|   |                 void *opt_data, size_t opt_dlen) | 
|   | { | 
|   | #if SUP_ENABLE != KQ_SUPPORT | 
|   |         sched_SetErr(ENOTSUP, "disabled kqueue support"); | 
|   |         return NULL; | 
|   | #else | 
|   | #ifndef EVFILT_USER | 
|   |         sched_SetErr(ENOTSUP, "Not supported kevent() filter"); | 
|   |         return NULL; | 
|   | #else | 
|   |         sched_task_t *task; | 
|   |         void *ptr; | 
|   |  | 
|   |         if (!root || !func) | 
|   |                 return NULL; | 
|   |  | 
|   |         /* get new task */ | 
|   |         if (!(task = sched_useTask(root))) | 
|   |                 return NULL; | 
|   |  | 
|   |         TASK_FUNC(task) = func; | 
|   |         TASK_TYPE(task) = taskUSER; | 
|   |         TASK_ROOT(task) = root; | 
|   |  | 
|   |         TASK_ARG(task) = arg; | 
|   |         TASK_VAL(task) = id; | 
|   |  | 
|   |         TASK_DATA(task) = opt_data; | 
|   |         TASK_DATLEN(task) = opt_dlen; | 
|   |  | 
|   |         if (root->root_hooks.hook_add.user) | 
|   |                 ptr = root->root_hooks.hook_add.user(task, NULL); | 
|   |         else | 
|   |                 ptr = NULL; | 
|   |  | 
|   |         if (!ptr) | 
|   |                 insert_task_to(task, &root->root_user); | 
|   |         else | 
|   |                 task = sched_unuseTask(task); | 
|   |  | 
|   |         return task; | 
|   | #endif  /* EVFILT_USER */ | 
|   | #endif  /* KQ_SUPPORT */ | 
|   | } | 
|   |  | 
|   | /* | 
|   |  * schedSignal() - Add SIGNAL task to scheduler queue | 
|   |  * | 
|   |  * @root = root task | 
|   |  * @func = task execution function | 
|   |  * @arg = 1st func argument | 
|   |  * @sig = Signal | 
|   |  * @opt_data = Optional data | 
|   |  * @opt_dlen = Optional data length | 
|   |  * return: NULL error or !=NULL new queued task | 
|   |  */ | 
|   | sched_task_t * | 
|   | schedSignal(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, u_long sig,  | 
|   |                 void *opt_data, size_t opt_dlen) | 
|   | { | 
|   |         sched_task_t *task; | 
|   |         void *ptr; | 
|   |  | 
|   |         if (!root || !func) | 
|   |                 return NULL; | 
|   |  | 
|   |         /* get new task */ | 
|   |         if (!(task = sched_useTask(root))) | 
|   |                 return NULL; | 
|   |  | 
|   |         TASK_FUNC(task) = func; | 
|   |         TASK_TYPE(task) = taskSIGNAL; | 
|   |         TASK_ROOT(task) = root; | 
|   |  | 
|   |         TASK_ARG(task) = arg; | 
|   |         TASK_VAL(task) = sig; | 
|   |  | 
|   |         TASK_DATA(task) = opt_data; | 
|   |         TASK_DATLEN(task) = opt_dlen; | 
|   |  | 
|   |         if (root->root_hooks.hook_add.signal) | 
|   |                 ptr = root->root_hooks.hook_add.signal(task, NULL); | 
|   |         else | 
|   |                 ptr = NULL; | 
|   |  | 
|   |         if (!ptr) | 
|   |                 insert_task_to(task, &root->root_signal); | 
|   |         else | 
|   |                 task = sched_unuseTask(task); | 
|   |  | 
|   |         return task; | 
|   | } | 
|   |  | 
|   | /* | 
|   |  * schedAlarm() - Add ALARM task to scheduler queue | 
|   |  * | 
|   |  * @root = root task | 
|   |  * @func = task execution function | 
|   |  * @arg = 1st func argument | 
|   |  * @ts = timeout argument structure, minimum alarm timer resolution is 1msec! | 
|   |  * @opt_data = Alarm timer ID | 
|   |  * @opt_dlen = Optional data length | 
|   |  * return: NULL error or !=NULL new queued task | 
|   |  */ | 
|   | sched_task_t * | 
|   | schedAlarm(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, struct timespec ts,  | 
|   |                 void *opt_data, size_t opt_dlen) | 
|   | { | 
|   | #if SUP_ENABLE != KQ_SUPPORT | 
|   |         sched_SetErr(ENOTSUP, "disabled kqueue support"); | 
|   |         return NULL; | 
|   | #else | 
|   |         sched_task_t *task; | 
|   |         void *ptr; | 
|   |  | 
|   |         if (!root || !func) | 
|   |                 return NULL; | 
|   |  | 
|   |         /* get new task */ | 
|   |         if (!(task = sched_useTask(root))) | 
|   |                 return NULL; | 
|   |  | 
|   |         TASK_FUNC(task) = func; | 
|   |         TASK_TYPE(task) = taskALARM; | 
|   |         TASK_ROOT(task) = root; | 
|   |  | 
|   |         TASK_ARG(task) = arg; | 
|   |         TASK_TS(task) = ts; | 
|   |  | 
|   |         TASK_DATA(task) = opt_data; | 
|   |         TASK_DATLEN(task) = opt_dlen; | 
|   |  | 
|   |         if (root->root_hooks.hook_add.alarm) | 
|   |                 ptr = root->root_hooks.hook_add.alarm(task, NULL); | 
|   |         else | 
|   |                 ptr = NULL; | 
|   |  | 
|   |         if (!ptr) | 
|   |                 insert_task_to(task, &root->root_alarm); | 
|   |         else | 
|   |                 task = sched_unuseTask(task); | 
|   |  | 
|   |         return task; | 
|   | #endif  /* KQ_SUPPORT */ | 
|   | } | 
|   |  | 
|   | #ifdef AIO_SUPPORT | 
|   | /* | 
|   |  * schedAIO() - Add AIO task to scheduler queue | 
|   |  * | 
|   |  * @root = root task | 
|   |  * @func = task execution function | 
|   |  * @arg = 1st func argument | 
|   |  * @acb = AIO cb structure address | 
|   |  * @opt_data = Optional data | 
|   |  * @opt_dlen = Optional data length | 
|   |  * return: NULL error or !=NULL new queued task | 
|   |  */ | 
|   | sched_task_t * | 
|   | schedAIO(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg,  | 
|   |                 struct aiocb * __restrict acb, void *opt_data, size_t opt_dlen) | 
|   | { | 
|   | #if SUP_ENABLE != KQ_SUPPORT | 
|   |         sched_SetErr(ENOTSUP, "disabled kqueue support"); | 
|   |         return NULL; | 
|   | #else | 
|   |         sched_task_t *task; | 
|   |         void *ptr; | 
|   |  | 
|   |         if (!root || !func || !acb || !opt_dlen) | 
|   |                 return NULL; | 
|   |  | 
|   |         /* get new task */ | 
|   |         if (!(task = sched_useTask(root))) | 
|   |                 return NULL; | 
|   |  | 
|   |         TASK_FUNC(task) = func; | 
|   |         TASK_TYPE(task) = taskAIO; | 
|   |         TASK_ROOT(task) = root; | 
|   |  | 
|   |         TASK_ARG(task) = arg; | 
|   |         TASK_VAL(task) = (u_long) acb; | 
|   |  | 
|   |         TASK_DATA(task) = opt_data; | 
|   |         TASK_DATLEN(task) = opt_dlen; | 
|   |  | 
|   |         if (root->root_hooks.hook_add.aio) | 
|   |                 ptr = root->root_hooks.hook_add.aio(task, NULL); | 
|   |         else | 
|   |                 ptr = NULL; | 
|   |  | 
|   |         if (!ptr) | 
|   |                 insert_task_to(task, &root->root_aio); | 
|   |         else | 
|   |                 task = sched_unuseTask(task); | 
|   |  | 
|   |         return task; | 
|   | #endif  /* KQ_SUPPORT */ | 
|   | } | 
|   |  | 
|   | /* | 
|   |  * schedAIORead() - Add AIO read task to scheduler queue | 
|   |  * | 
|   |  * @root = root task | 
|   |  * @func = task execution function | 
|   |  * @arg = 1st func argument | 
|   |  * @fd = file descriptor | 
|   |  * @buffer = Buffer | 
|   |  * @buflen = Buffer length | 
|   |  * @offset = Offset from start of file, if =-1 from current position | 
|   |  * return: NULL error or !=NULL new queued task | 
|   |  */ | 
|   | sched_task_t * | 
|   | schedAIORead(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd,  | 
|   |                 void *buffer, size_t buflen, off_t offset) | 
|   | { | 
|   | #if SUP_ENABLE != KQ_SUPPORT | 
|   |         sched_SetErr(ENOTSUP, "disabled kqueue support"); | 
|   |         return NULL; | 
|   | #else | 
|   |         struct aiocb *acb; | 
|   |         off_t off; | 
|   |  | 
|   |         if (!root || !func || !buffer || !buflen) | 
|   |                 return NULL; | 
|   |  | 
|   |         if (offset == (off_t) -1) { | 
|   |                 off = lseek(fd, 0, SEEK_CUR); | 
|   |                 if (off == -1) { | 
|   |                         LOGERR; | 
|   |                         return NULL; | 
|   |                 } | 
 |          } else | 
          } else | 
|                 task = _sched_unuseTask(task); |                 off = offset; | 
 |   | 
   | 
 |   | 
          if (!(acb = e_malloc(sizeof(struct aiocb)))) { | 
 |   | 
                  LOGERR; | 
 |   | 
                  return NULL; | 
 |   | 
          } else | 
 |   | 
                  memset(acb, 0, sizeof(struct aiocb)); | 
 |   | 
   | 
 |   | 
          acb->aio_fildes = fd; | 
 |   | 
          acb->aio_nbytes = buflen; | 
 |   | 
          acb->aio_buf = buffer; | 
 |   | 
          acb->aio_offset = off; | 
 |   | 
          acb->aio_sigevent.sigev_notify = SIGEV_KEVENT; | 
 |   | 
          acb->aio_sigevent.sigev_notify_kqueue = root->root_kq; | 
 |   | 
          acb->aio_sigevent.sigev_value.sival_ptr = acb; | 
 |   | 
   | 
 |   | 
          if (aio_read(acb)) { | 
 |   | 
                  LOGERR; | 
 |   | 
                  e_free(acb); | 
 |   | 
                  return NULL; | 
 |   | 
          } | 
 |   | 
   | 
 |   | 
          return schedAIO(root, func, arg, acb, buffer, buflen); | 
 |   | 
  #endif  /* KQ_SUPPORT */ | 
 |   | 
  } | 
 |   | 
   | 
 |   | 
  /* | 
 |   | 
   * schedAIOWrite() - Add AIO write task to scheduler queue | 
 |   | 
   * | 
 |   | 
   * @root = root task | 
 |   | 
   * @func = task execution function | 
 |   | 
   * @arg = 1st func argument | 
 |   | 
   * @fd = file descriptor | 
 |   | 
   * @buffer = Buffer | 
 |   | 
   * @buflen = Buffer length | 
 |   | 
   * @offset = Offset from start of file, if =-1 from current position | 
 |   | 
   * return: NULL error or !=NULL new queued task | 
 |   | 
   */ | 
 |   | 
  sched_task_t * | 
 |   | 
  schedAIOWrite(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd,  | 
 |   | 
                  void *buffer, size_t buflen, off_t offset) | 
 |   | 
  { | 
 |   | 
  #if SUP_ENABLE != KQ_SUPPORT | 
 |   | 
          sched_SetErr(ENOTSUP, "disabled kqueue support"); | 
 |   | 
          return NULL; | 
 |   | 
  #else | 
 |   | 
          struct aiocb *acb; | 
 |   | 
          off_t off; | 
 |   | 
   | 
 |   | 
          if (!root || !func || !buffer || !buflen) | 
 |   | 
                  return NULL; | 
 |   | 
   | 
 |   | 
          if (offset == (off_t) -1) { | 
 |   | 
                  off = lseek(fd, 0, SEEK_CUR); | 
 |   | 
                  if (off == -1) { | 
 |   | 
                          LOGERR; | 
 |   | 
                          return NULL; | 
 |   | 
                  } | 
 |   | 
          } else | 
 |   | 
                  off = offset; | 
 |   | 
   | 
 |   | 
          if (!(acb = e_malloc(sizeof(struct aiocb)))) { | 
 |   | 
                  LOGERR; | 
 |   | 
                  return NULL; | 
 |   | 
          } else | 
 |   | 
                  memset(acb, 0, sizeof(struct aiocb)); | 
 |   | 
   | 
 |   | 
          acb->aio_fildes = fd; | 
 |   | 
          acb->aio_nbytes = buflen; | 
 |   | 
          acb->aio_buf = buffer; | 
 |   | 
          acb->aio_offset = off; | 
 |   | 
          acb->aio_sigevent.sigev_notify = SIGEV_KEVENT; | 
 |   | 
          acb->aio_sigevent.sigev_notify_kqueue = root->root_kq; | 
 |   | 
          acb->aio_sigevent.sigev_value.sival_ptr = acb; | 
 |   | 
   | 
 |   | 
          if (aio_write(acb)) { | 
 |   | 
                  LOGERR; | 
 |   | 
                  e_free(acb); | 
 |   | 
                  return NULL; | 
 |   | 
          } | 
 |   | 
   | 
 |   | 
          return schedAIO(root, func, arg, acb, buffer, buflen); | 
 |   | 
  #endif  /* KQ_SUPPORT */ | 
 |   | 
  } | 
 |   | 
   | 
 |   | 
  #ifdef EVFILT_LIO | 
 |   | 
  /* | 
 |   | 
   * schedLIO() - Add AIO bulk tasks to scheduler queue | 
 |   | 
   * | 
 |   | 
   * @root = root task | 
 |   | 
   * @func = task execution function | 
 |   | 
   * @arg = 1st func argument | 
 |   | 
   * @acbs = AIO cb structure addresses | 
 |   | 
   * @opt_data = Optional data | 
 |   | 
   * @opt_dlen = Optional data length | 
 |   | 
   * return: NULL error or !=NULL new queued task | 
 |   | 
   */ | 
 |   | 
  sched_task_t * | 
 |   | 
  schedLIO(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg,  | 
 |   | 
                  struct aiocb ** __restrict acbs, void *opt_data, size_t opt_dlen) | 
 |   | 
  { | 
 |   | 
  #if SUP_ENABLE != KQ_SUPPORT | 
 |   | 
          sched_SetErr(ENOTSUP, "disabled kqueue support"); | 
 |   | 
          return NULL; | 
 |   | 
  #else | 
 |   | 
          sched_task_t *task; | 
 |   | 
          void *ptr; | 
 |   | 
   | 
 |   | 
          if (!root || !func || !acbs || !opt_dlen) | 
 |   | 
                  return NULL; | 
 |   | 
   | 
 |   | 
          /* get new task */ | 
 |   | 
          if (!(task = sched_useTask(root))) | 
 |   | 
                  return NULL; | 
 |   | 
   | 
 |   | 
          TASK_FUNC(task) = func; | 
 |   | 
          TASK_TYPE(task) = taskLIO; | 
 |   | 
          TASK_ROOT(task) = root; | 
 |   | 
   | 
 |   | 
          TASK_ARG(task) = arg; | 
 |   | 
          TASK_VAL(task) = (u_long) acbs; | 
 |   | 
   | 
 |   | 
          TASK_DATA(task) = opt_data; | 
 |   | 
          TASK_DATLEN(task) = opt_dlen; | 
 |   | 
   | 
 |   | 
          if (root->root_hooks.hook_add.lio) | 
 |   | 
                  ptr = root->root_hooks.hook_add.lio(task, NULL); | 
 |   | 
          else | 
 |   | 
                  ptr = NULL; | 
 |   | 
   | 
 |   | 
          if (!ptr) | 
 |   | 
                  insert_task_to(task, &root->root_lio); | 
 |   | 
          else | 
 |   | 
                  task = sched_unuseTask(task); | 
 |   | 
   | 
 |          return task; | 
          return task; | 
 |   | 
  #endif  /* KQ_SUPPORT */ | 
 |  } | 
  } | 
 |   | 
   | 
 |  /* | 
  /* | 
 |   | 
   * schedLIORead() - Add list of AIO read tasks to scheduler queue | 
 |   | 
   * | 
 |   | 
   * @root = root task | 
 |   | 
   * @func = task execution function | 
 |   | 
   * @arg = 1st func argument | 
 |   | 
   * @fd = file descriptor | 
 |   | 
   * @bufs = Buffer's list | 
 |   | 
   * @nbufs = Number of Buffers | 
 |   | 
   * @offset = Offset from start of file, if =-1 from current position | 
 |   | 
   * return: NULL error or !=NULL new queued task | 
 |   | 
   */ | 
 |   | 
  sched_task_t * | 
 |   | 
  schedLIORead(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd,  | 
 |   | 
                  struct iovec *bufs, size_t nbufs, off_t offset) | 
 |   | 
  { | 
 |   | 
  #if SUP_ENABLE != KQ_SUPPORT | 
 |   | 
          sched_SetErr(ENOTSUP, "disabled kqueue support"); | 
 |   | 
          return NULL; | 
 |   | 
  #else | 
 |   | 
          struct sigevent sig; | 
 |   | 
          struct aiocb **acb; | 
 |   | 
          off_t off; | 
 |   | 
          register int i; | 
 |   | 
   | 
 |   | 
          if (!root || !func || !bufs || !nbufs) | 
 |   | 
                  return NULL; | 
 |   | 
   | 
 |   | 
          if (offset == (off_t) -1) { | 
 |   | 
                  off = lseek(fd, 0, SEEK_CUR); | 
 |   | 
                  if (off == -1) { | 
 |   | 
                          LOGERR; | 
 |   | 
                          return NULL; | 
 |   | 
                  } | 
 |   | 
          } else | 
 |   | 
                  off = offset; | 
 |   | 
   | 
 |   | 
          if (!(acb = e_calloc(sizeof(void*), nbufs))) { | 
 |   | 
                  LOGERR; | 
 |   | 
                  return NULL; | 
 |   | 
          } else | 
 |   | 
                  memset(acb, 0, sizeof(void*) * nbufs); | 
 |   | 
          for (i = 0; i < nbufs; off += bufs[i++].iov_len) { | 
 |   | 
                  acb[i] = e_malloc(sizeof(struct aiocb)); | 
 |   | 
                  if (!acb[i]) { | 
 |   | 
                          LOGERR; | 
 |   | 
                          for (i = 0; i < nbufs; i++) | 
 |   | 
                                  if (acb[i]) | 
 |   | 
                                          e_free(acb[i]); | 
 |   | 
                          e_free(acb); | 
 |   | 
                          return NULL; | 
 |   | 
                  } else | 
 |   | 
                          memset(acb[i], 0, sizeof(struct aiocb)); | 
 |   | 
                  acb[i]->aio_fildes = fd; | 
 |   | 
                  acb[i]->aio_nbytes = bufs[i].iov_len; | 
 |   | 
                  acb[i]->aio_buf = bufs[i].iov_base; | 
 |   | 
                  acb[i]->aio_offset = off; | 
 |   | 
                  acb[i]->aio_lio_opcode = LIO_READ; | 
 |   | 
          } | 
 |   | 
          memset(&sig, 0, sizeof sig); | 
 |   | 
          sig.sigev_notify = SIGEV_KEVENT; | 
 |   | 
          sig.sigev_notify_kqueue = root->root_kq; | 
 |   | 
          sig.sigev_value.sival_ptr = acb; | 
 |   | 
   | 
 |   | 
          if (lio_listio(LIO_NOWAIT, acb, nbufs, &sig)) { | 
 |   | 
                  LOGERR; | 
 |   | 
                  for (i = 0; i < nbufs; i++) | 
 |   | 
                          if (acb[i]) | 
 |   | 
                                  e_free(acb[i]); | 
 |   | 
                  e_free(acb); | 
 |   | 
                  return NULL; | 
 |   | 
          } | 
 |   | 
   | 
 |   | 
          return schedLIO(root, func, arg, (void*) acb, bufs, nbufs); | 
 |   | 
  #endif  /* KQ_SUPPORT */ | 
 |   | 
  } | 
 |   | 
   | 
 |   | 
  /* | 
 |   | 
   * schedLIOWrite() - Add list of AIO write tasks to scheduler queue | 
 |   | 
   * | 
 |   | 
   * @root = root task | 
 |   | 
   * @func = task execution function | 
 |   | 
   * @arg = 1st func argument | 
 |   | 
   * @fd = file descriptor | 
 |   | 
   * @bufs = Buffer's list | 
 |   | 
   * @nbufs = Number of Buffers | 
 |   | 
   * @offset = Offset from start of file, if =-1 from current position | 
 |   | 
   * return: NULL error or !=NULL new queued task | 
 |   | 
   */ | 
 |   | 
  sched_task_t * | 
 |   | 
  schedLIOWrite(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd,  | 
 |   | 
                  struct iovec *bufs, size_t nbufs, off_t offset) | 
 |   | 
  { | 
 |   | 
  #if SUP_ENABLE != KQ_SUPPORT | 
 |   | 
          sched_SetErr(ENOTSUP, "disabled kqueue support"); | 
 |   | 
          return NULL; | 
 |   | 
  #else | 
 |   | 
          struct sigevent sig; | 
 |   | 
          struct aiocb **acb; | 
 |   | 
          off_t off; | 
 |   | 
          register int i; | 
 |   | 
   | 
 |   | 
          if (!root || !func || !bufs || !nbufs) | 
 |   | 
                  return NULL; | 
 |   | 
   | 
 |   | 
          if (offset == (off_t) -1) { | 
 |   | 
                  off = lseek(fd, 0, SEEK_CUR); | 
 |   | 
                  if (off == -1) { | 
 |   | 
                          LOGERR; | 
 |   | 
                          return NULL; | 
 |   | 
                  } | 
 |   | 
          } else | 
 |   | 
                  off = offset; | 
 |   | 
   | 
 |   | 
          if (!(acb = e_calloc(sizeof(void*), nbufs))) { | 
 |   | 
                  LOGERR; | 
 |   | 
                  return NULL; | 
 |   | 
          } else | 
 |   | 
                  memset(acb, 0, sizeof(void*) * nbufs); | 
 |   | 
          for (i = 0; i < nbufs; off += bufs[i++].iov_len) { | 
 |   | 
                  acb[i] = e_malloc(sizeof(struct aiocb)); | 
 |   | 
                  if (!acb[i]) { | 
 |   | 
                          LOGERR; | 
 |   | 
                          for (i = 0; i < nbufs; i++) | 
 |   | 
                                  if (acb[i]) | 
 |   | 
                                          e_free(acb[i]); | 
 |   | 
                          e_free(acb); | 
 |   | 
                          return NULL; | 
 |   | 
                  } else | 
 |   | 
                          memset(acb[i], 0, sizeof(struct aiocb)); | 
 |   | 
                  acb[i]->aio_fildes = fd; | 
 |   | 
                  acb[i]->aio_nbytes = bufs[i].iov_len; | 
 |   | 
                  acb[i]->aio_buf = bufs[i].iov_base; | 
 |   | 
                  acb[i]->aio_offset = off; | 
 |   | 
                  acb[i]->aio_lio_opcode = LIO_WRITE; | 
 |   | 
          } | 
 |   | 
          memset(&sig, 0, sizeof sig); | 
 |   | 
          sig.sigev_notify = SIGEV_KEVENT; | 
 |   | 
          sig.sigev_notify_kqueue = root->root_kq; | 
 |   | 
          sig.sigev_value.sival_ptr = acb; | 
 |   | 
   | 
 |   | 
          if (lio_listio(LIO_NOWAIT, acb, nbufs, &sig)) { | 
 |   | 
                  LOGERR; | 
 |   | 
                  for (i = 0; i < nbufs; i++) | 
 |   | 
                          if (acb[i]) | 
 |   | 
                                  e_free(acb[i]); | 
 |   | 
                  e_free(acb); | 
 |   | 
                  return NULL; | 
 |   | 
          } | 
 |   | 
   | 
 |   | 
          return schedLIO(root, func, arg, (void*) acb, bufs, nbufs); | 
 |   | 
  #endif  /* KQ_SUPPORT */ | 
 |   | 
  } | 
 |   | 
  #endif  /* EVFILT_LIO */ | 
 |   | 
  #endif  /* AIO_SUPPORT */ | 
 |   | 
   | 
 |   | 
  /* | 
 |   * schedTimer() - Add TIMER task to scheduler queue | 
   * schedTimer() - Add TIMER task to scheduler queue | 
 |   | 
   * | 
 |   * @root = root task | 
   * @root = root task | 
 |   * @func = task execution function | 
   * @func = task execution function | 
 |   * @arg = 1st func argument | 
   * @arg = 1st func argument | 
| 
 Line 223  sched_task_t *
 | 
 Line 978  sched_task_t *
 | 
 |  schedTimer(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, struct timespec ts,  | 
  schedTimer(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, struct timespec ts,  | 
 |                  void *opt_data, size_t opt_dlen) | 
                  void *opt_data, size_t opt_dlen) | 
 |  { | 
  { | 
|         sched_task_t *task, *t = NULL; |         sched_task_t *task, *tmp, *t = NULL; | 
 |          void *ptr; | 
          void *ptr; | 
 |          struct timespec now; | 
          struct timespec now; | 
 |   | 
   | 
| 
 Line 231  schedTimer(sched_root_task_t * __restrict root, sched_
 | 
 Line 986  schedTimer(sched_root_task_t * __restrict root, sched_
 | 
 |                  return NULL; | 
                  return NULL; | 
 |   | 
   | 
 |          /* get new task */ | 
          /* get new task */ | 
|         if (!(task = _sched_useTask(root))) |         if (!(task = sched_useTask(root))) | 
 |                  return NULL; | 
                  return NULL; | 
 |   | 
   | 
|         memset(task, 0, sizeof(sched_task_t)); |         TASK_FUNC(task) = func; | 
|         task->task_id = 0; |   | 
|         task->task_lock = 0; |   | 
|         task->task_func = func; |   | 
 |          TASK_TYPE(task) = taskTIMER; | 
          TASK_TYPE(task) = taskTIMER; | 
 |          TASK_ROOT(task) = root; | 
          TASK_ROOT(task) = root; | 
 |   | 
   | 
| 
 Line 250  schedTimer(sched_root_task_t * __restrict root, sched_
 | 
 Line 1002  schedTimer(sched_root_task_t * __restrict root, sched_
 | 
 |          clock_gettime(CLOCK_MONOTONIC, &now); | 
          clock_gettime(CLOCK_MONOTONIC, &now); | 
 |          now.tv_sec += ts.tv_sec; | 
          now.tv_sec += ts.tv_sec; | 
 |          now.tv_nsec += ts.tv_nsec; | 
          now.tv_nsec += ts.tv_nsec; | 
|         if (now.tv_nsec >= 1000000000) { |         if (now.tv_nsec >= 1000000000L) { | 
 |                  now.tv_sec++; | 
                  now.tv_sec++; | 
|                 now.tv_nsec -= 1000000000; |                 now.tv_nsec -= 1000000000L; | 
 |          } else if (now.tv_nsec < 0) { | 
          } else if (now.tv_nsec < 0) { | 
 |                  now.tv_sec--; | 
                  now.tv_sec--; | 
|                 now.tv_nsec += 1000000000; |                 now.tv_nsec += 1000000000L; | 
 |          } | 
          } | 
 |          TASK_TS(task) = now; | 
          TASK_TS(task) = now; | 
 |   | 
   | 
| 
 Line 265  schedTimer(sched_root_task_t * __restrict root, sched_
 | 
 Line 1017  schedTimer(sched_root_task_t * __restrict root, sched_
 | 
 |                  ptr = NULL; | 
                  ptr = NULL; | 
 |   | 
   | 
 |          if (!ptr) { | 
          if (!ptr) { | 
| #ifdef HAVE_LIBPTHREAD |                 SCHED_QLOCK(root, taskTIMER); | 
|                 pthread_mutex_lock(&root->root_mtx[taskTIMER]); |   | 
| #endif |   | 
 |  #ifdef TIMER_WITHOUT_SORT | 
  #ifdef TIMER_WITHOUT_SORT | 
 |                  TAILQ_INSERT_TAIL(&root->root_timer, task, task_node); | 
                  TAILQ_INSERT_TAIL(&root->root_timer, task, task_node); | 
 |  #else | 
  #else | 
|                 TAILQ_FOREACH(t, &root->root_timer, task_node) |                 TAILQ_FOREACH_SAFE(t, &root->root_timer, task_node, tmp) | 
|                         if (timespeccmp(&TASK_TS(task), &TASK_TS(t), -) < 1) |                         if (sched_timespeccmp(&TASK_TS(task), &TASK_TS(t), -) < 1) | 
 |                                  break; | 
                                  break; | 
 |                  if (!t) | 
                  if (!t) | 
 |                          TAILQ_INSERT_TAIL(&root->root_timer, task, task_node); | 
                          TAILQ_INSERT_TAIL(&root->root_timer, task, task_node); | 
 |                  else | 
                  else | 
 |                          TAILQ_INSERT_BEFORE(t, task, task_node); | 
                          TAILQ_INSERT_BEFORE(t, task, task_node); | 
 |  #endif | 
  #endif | 
| #ifdef HAVE_LIBPTHREAD |                 SCHED_QUNLOCK(root, taskTIMER); | 
|                 pthread_mutex_unlock(&root->root_mtx[taskTIMER]); |   | 
| #endif |   | 
 |          } else | 
          } else | 
|                 task = _sched_unuseTask(task); |                 task = sched_unuseTask(task); | 
 |   | 
   | 
 |          return task; | 
          return task; | 
 |  } | 
  } | 
 |   | 
   | 
 |  /* | 
  /* | 
 |   * schedEvent() - Add EVENT task to scheduler queue | 
   * schedEvent() - Add EVENT task to scheduler queue | 
 |   | 
   * | 
 |   * @root = root task | 
   * @root = root task | 
 |   * @func = task execution function | 
   * @func = task execution function | 
 |   * @arg = 1st func argument | 
   * @arg = 1st func argument | 
| 
 Line 309  schedEvent(sched_root_task_t * __restrict root, sched_
 | 
 Line 1058  schedEvent(sched_root_task_t * __restrict root, sched_
 | 
 |                  return NULL; | 
                  return NULL; | 
 |   | 
   | 
 |          /* get new task */ | 
          /* get new task */ | 
|         if (!(task = _sched_useTask(root))) |         if (!(task = sched_useTask(root))) | 
 |                  return NULL; | 
                  return NULL; | 
 |   | 
   | 
|         memset(task, 0, sizeof(sched_task_t)); |         TASK_FUNC(task) = func; | 
|         task->task_id = 0; |   | 
|         task->task_lock = 0; |   | 
|         task->task_func = func; |   | 
 |          TASK_TYPE(task) = taskEVENT; | 
          TASK_TYPE(task) = taskEVENT; | 
 |          TASK_ROOT(task) = root; | 
          TASK_ROOT(task) = root; | 
 |   | 
   | 
| 
 Line 330  schedEvent(sched_root_task_t * __restrict root, sched_
 | 
 Line 1076  schedEvent(sched_root_task_t * __restrict root, sched_
 | 
 |          else | 
          else | 
 |                  ptr = NULL; | 
                  ptr = NULL; | 
 |   | 
   | 
|         if (!ptr) { |         if (!ptr) | 
| #ifdef HAVE_LIBPTHREAD |                 insert_task_to(task, &root->root_event); | 
|                 pthread_mutex_lock(&root->root_mtx[taskEVENT]); |         else | 
| #endif |                 task = sched_unuseTask(task); | 
|                 TAILQ_INSERT_TAIL(&root->root_event, task, task_node); |   | 
| #ifdef HAVE_LIBPTHREAD |   | 
|                 pthread_mutex_unlock(&root->root_mtx[taskEVENT]); |   | 
| #endif |   | 
|         } else |   | 
|                 task = _sched_unuseTask(task); |   | 
 |   | 
   | 
 |          return task; | 
          return task; | 
 |  } | 
  } | 
 |   | 
   | 
 |   | 
   | 
 |  /* | 
  /* | 
|  * schedEventLo() - Add EVENT_Lo task to scheduler queue |  * schedTask() - Add regular task to scheduler queue | 
|   |  * | 
 |   * @root = root task | 
   * @root = root task | 
 |   * @func = task execution function | 
   * @func = task execution function | 
 |   * @arg = 1st func argument | 
   * @arg = 1st func argument | 
|  * @val = additional func argument |  * @prio = regular task priority, 0 is hi priority for regular tasks | 
 |   * @opt_data = Optional data | 
   * @opt_data = Optional data | 
 |   * @opt_dlen = Optional data length | 
   * @opt_dlen = Optional data length | 
 |   * return: NULL error or !=NULL new queued task | 
   * return: NULL error or !=NULL new queued task | 
 |   */ | 
   */ | 
 |  sched_task_t * | 
  sched_task_t * | 
| schedEventLo(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, u_long val,  | schedTask(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, u_long prio,  | 
 |                  void *opt_data, size_t opt_dlen) | 
                  void *opt_data, size_t opt_dlen) | 
 |  { | 
  { | 
|         sched_task_t *task; |         sched_task_t *task, *tmp, *t = NULL; | 
 |          void *ptr; | 
          void *ptr; | 
 |   | 
   | 
 |          if (!root || !func) | 
          if (!root || !func) | 
 |                  return NULL; | 
                  return NULL; | 
 |   | 
   | 
 |          /* get new task */ | 
          /* get new task */ | 
|         if (!(task = _sched_useTask(root))) |         if (!(task = sched_useTask(root))) | 
 |                  return NULL; | 
                  return NULL; | 
 |   | 
   | 
|         memset(task, 0, sizeof(sched_task_t)); |         TASK_FUNC(task) = func; | 
|         task->task_id = 0; |         TASK_TYPE(task) = taskTASK; | 
|         task->task_lock = 0; |   | 
|         task->task_func = func; |   | 
|         TASK_TYPE(task) = taskEVENT; |   | 
 |          TASK_ROOT(task) = root; | 
          TASK_ROOT(task) = root; | 
 |   | 
   | 
 |          TASK_ARG(task) = arg; | 
          TASK_ARG(task) = arg; | 
|         TASK_VAL(task) = val; |         TASK_VAL(task) = prio; | 
 |   | 
   | 
 |          TASK_DATA(task) = opt_data; | 
          TASK_DATA(task) = opt_data; | 
 |          TASK_DATLEN(task) = opt_dlen; | 
          TASK_DATLEN(task) = opt_dlen; | 
 |   | 
   | 
|         if (root->root_hooks.hook_add.eventlo) |         if (root->root_hooks.hook_add.task) | 
|                 ptr = root->root_hooks.hook_add.eventlo(task, NULL); |                 ptr = root->root_hooks.hook_add.task(task, NULL); | 
 |          else | 
          else | 
 |                  ptr = NULL; | 
                  ptr = NULL; | 
 |   | 
   | 
 |          if (!ptr) { | 
          if (!ptr) { | 
| #ifdef HAVE_LIBPTHREAD |                 SCHED_QLOCK(root, taskTASK); | 
|                 pthread_mutex_lock(&root->root_mtx[taskEVENTLO]); |                 TAILQ_FOREACH_SAFE(t, &root->root_task, task_node, tmp) | 
| #endif |                         if (TASK_VAL(task) < TASK_VAL(t)) | 
|                 TAILQ_INSERT_TAIL(&root->root_eventlo, task, task_node); |                                 break; | 
| #ifdef HAVE_LIBPTHREAD |                 if (!t) | 
|                 pthread_mutex_unlock(&root->root_mtx[taskEVENTLO]); |                         TAILQ_INSERT_TAIL(&root->root_task, task, task_node); | 
| #endif |                 else | 
|   |                         TAILQ_INSERT_BEFORE(t, task, task_node); | 
|   |                 SCHED_QUNLOCK(root, taskTASK); | 
 |          } else | 
          } else | 
|                 task = _sched_unuseTask(task); |                 task = sched_unuseTask(task); | 
 |   | 
   | 
 |          return task; | 
          return task; | 
 |  } | 
  } | 
 |   | 
   | 
 |  /* | 
  /* | 
 |   | 
   * schedSuspend() - Add Suspended task to scheduler queue | 
 |   | 
   * | 
 |   | 
   * @root = root task | 
 |   | 
   * @func = task execution function | 
 |   | 
   * @arg = 1st func argument | 
 |   | 
   * @id = Trigger ID | 
 |   | 
   * @opt_data = Optional data | 
 |   | 
   * @opt_dlen = Optional data length | 
 |   | 
   * return: NULL error or !=NULL new queued task | 
 |   | 
   */ | 
 |   | 
  sched_task_t * | 
 |   | 
  schedSuspend(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, u_long id,  | 
 |   | 
                  void *opt_data, size_t opt_dlen) | 
 |   | 
  { | 
 |   | 
          sched_task_t *task; | 
 |   | 
          void *ptr; | 
 |   | 
   | 
 |   | 
          if (!root || !func) | 
 |   | 
                  return NULL; | 
 |   | 
   | 
 |   | 
          /* get new task */ | 
 |   | 
          if (!(task = sched_useTask(root))) | 
 |   | 
                  return NULL; | 
 |   | 
   | 
 |   | 
          TASK_FUNC(task) = func; | 
 |   | 
          TASK_TYPE(task) = taskSUSPEND; | 
 |   | 
          TASK_ROOT(task) = root; | 
 |   | 
   | 
 |   | 
          TASK_ARG(task) = arg; | 
 |   | 
          TASK_VAL(task) = id; | 
 |   | 
   | 
 |   | 
          TASK_DATA(task) = opt_data; | 
 |   | 
          TASK_DATLEN(task) = opt_dlen; | 
 |   | 
   | 
 |   | 
          if (root->root_hooks.hook_add.suspend) | 
 |   | 
                  ptr = root->root_hooks.hook_add.suspend(task, NULL); | 
 |   | 
          else | 
 |   | 
                  ptr = NULL; | 
 |   | 
   | 
 |   | 
          if (!ptr) | 
 |   | 
                  insert_task_to(task, &root->root_suspend); | 
 |   | 
          else | 
 |   | 
                  task = sched_unuseTask(task); | 
 |   | 
   | 
 |   | 
          return task; | 
 |   | 
  } | 
 |   | 
   | 
 |   | 
  /* | 
 |   * schedCallOnce() - Call once from scheduler | 
   * schedCallOnce() - Call once from scheduler | 
 |   | 
   * | 
 |   * @root = root task | 
   * @root = root task | 
 |   * @func = task execution function | 
   * @func = task execution function | 
 |   * @arg = 1st func argument | 
   * @arg = 1st func argument | 
| 
 Line 422  schedCallOnce(sched_root_task_t * __restrict root, sch
 | 
 Line 1211  schedCallOnce(sched_root_task_t * __restrict root, sch
 | 
 |                  return NULL; | 
                  return NULL; | 
 |   | 
   | 
 |          /* get new task */ | 
          /* get new task */ | 
|         if (!(task = _sched_useTask(root))) |         if (!(task = sched_useTask(root))) | 
 |                  return NULL; | 
                  return NULL; | 
 |   | 
   | 
|         memset(task, 0, sizeof(sched_task_t)); |         TASK_FUNC(task) = func; | 
|         task->task_id = 0; |   | 
|         task->task_lock = 0; |   | 
|         task->task_func = func; |   | 
 |          TASK_TYPE(task) = taskEVENT; | 
          TASK_TYPE(task) = taskEVENT; | 
 |          TASK_ROOT(task) = root; | 
          TASK_ROOT(task) = root; | 
 |   | 
   | 
| 
 Line 440  schedCallOnce(sched_root_task_t * __restrict root, sch
 | 
 Line 1226  schedCallOnce(sched_root_task_t * __restrict root, sch
 | 
 |   | 
   | 
 |          ret = schedCall(task); | 
          ret = schedCall(task); | 
 |   | 
   | 
|         _sched_unuseTask(task); |         sched_unuseTask(task); | 
 |          return ret; | 
          return ret; | 
 |   | 
  } | 
 |   | 
   | 
 |   | 
  /* | 
 |   | 
   * schedThread() - Add thread task to scheduler queue | 
 |   | 
   * | 
 |   | 
   * @root = root task | 
 |   | 
   * @func = task execution function | 
 |   | 
   * @arg = 1st func argument | 
 |   | 
   * @ss = stack size | 
 |   | 
   * @opt_data = Optional data | 
 |   | 
   * @opt_dlen = Optional data length | 
 |   | 
   * return: NULL error or !=NULL new queued task | 
 |   | 
   */ | 
 |   | 
  sched_task_t * | 
 |   | 
  schedThread(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg,  | 
 |   | 
                  size_t ss, void *opt_data, size_t opt_dlen) | 
 |   | 
  { | 
 |   | 
  #ifndef HAVE_LIBPTHREAD | 
 |   | 
          sched_SetErr(ENOTSUP, "Not supported thread tasks"); | 
 |   | 
          return NULL; | 
 |   | 
  #endif | 
 |   | 
          sched_task_t *task; | 
 |   | 
          pthread_attr_t attr; | 
 |   | 
          void *ptr; | 
 |   | 
   | 
 |   | 
          if (!root || !func) | 
 |   | 
                  return NULL; | 
 |   | 
   | 
 |   | 
          /* get new task */ | 
 |   | 
          if (!(task = sched_useTask(root))) | 
 |   | 
                  return NULL; | 
 |   | 
   | 
 |   | 
          TASK_FUNC(task) = func; | 
 |   | 
          TASK_TYPE(task) = taskTHREAD; | 
 |   | 
          TASK_ROOT(task) = root; | 
 |   | 
   | 
 |   | 
          TASK_ARG(task) = arg; | 
 |   | 
   | 
 |   | 
          TASK_DATA(task) = opt_data; | 
 |   | 
          TASK_DATLEN(task) = opt_dlen; | 
 |   | 
   | 
 |   | 
          pthread_attr_init(&attr); | 
 |   | 
          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); | 
 |   | 
          if (ss && (errno = pthread_attr_setstacksize(&attr, ss))) { | 
 |   | 
                  LOGERR; | 
 |   | 
                  pthread_attr_destroy(&attr); | 
 |   | 
                  return sched_unuseTask(task); | 
 |   | 
          } | 
 |   | 
          if ((errno = pthread_attr_getstacksize(&attr, &ss))) { | 
 |   | 
                  LOGERR; | 
 |   | 
                  pthread_attr_destroy(&attr); | 
 |   | 
                  return sched_unuseTask(task); | 
 |   | 
          } else | 
 |   | 
                  TASK_FLAG(task) = ss; | 
 |   | 
   | 
 |   | 
  #ifdef SCHED_RR | 
 |   | 
          pthread_attr_setschedpolicy(&attr, SCHED_RR); | 
 |   | 
  #else | 
 |   | 
          pthread_attr_setschedpolicy(&attr, SCHED_OTHER); | 
 |   | 
  #endif | 
 |   | 
   | 
 |   | 
          if (root->root_hooks.hook_add.thread) | 
 |   | 
                  ptr = root->root_hooks.hook_add.thread(task, &attr); | 
 |   | 
          else | 
 |   | 
                  ptr = NULL; | 
 |   | 
   | 
 |   | 
          if (!ptr) | 
 |   | 
                  insert_task_to(task, &root->root_thread); | 
 |   | 
          else | 
 |   | 
                  task = sched_unuseTask(task); | 
 |   | 
   | 
 |   | 
          pthread_attr_destroy(&attr); | 
 |   | 
          return task; | 
 |   | 
  } | 
 |   | 
   | 
 |   | 
  /* | 
 |   | 
   * schedRTC() - Add RTC task to scheduler queue | 
 |   | 
   * | 
 |   | 
   * @root = root task | 
 |   | 
   * @func = task execution function | 
 |   | 
   * @arg = 1st func argument | 
 |   | 
   * @ts = timeout argument structure, minimum alarm timer resolution is 1msec! | 
 |   | 
   * @opt_data = Optional RTC ID | 
 |   | 
   * @opt_dlen = Optional data length | 
 |   | 
   * return: NULL error or !=NULL new queued task | 
 |   | 
   */ | 
 |   | 
  sched_task_t * | 
 |   | 
  schedRTC(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, struct timespec ts,  | 
 |   | 
                  void *opt_data, size_t opt_dlen) | 
 |   | 
  { | 
 |   | 
  #if defined(HAVE_LIBRT) && defined(HAVE_TIMER_CREATE) && \ | 
 |   | 
          defined(HAVE_TIMER_SETTIME) && defined(HAVE_TIMER_DELETE) | 
 |   | 
          sched_task_t *task; | 
 |   | 
          void *ptr; | 
 |   | 
   | 
 |   | 
          if (!root || !func) | 
 |   | 
                  return NULL; | 
 |   | 
   | 
 |   | 
          /* get new task */ | 
 |   | 
          if (!(task = sched_useTask(root))) | 
 |   | 
                  return NULL; | 
 |   | 
   | 
 |   | 
          TASK_FUNC(task) = func; | 
 |   | 
          TASK_TYPE(task) = taskRTC; | 
 |   | 
          TASK_ROOT(task) = root; | 
 |   | 
   | 
 |   | 
          TASK_ARG(task) = arg; | 
 |   | 
          TASK_TS(task) = ts; | 
 |   | 
   | 
 |   | 
          TASK_DATA(task) = opt_data; | 
 |   | 
          TASK_DATLEN(task) = opt_dlen; | 
 |   | 
   | 
 |   | 
          if (root->root_hooks.hook_add.rtc) | 
 |   | 
                  ptr = root->root_hooks.hook_add.rtc(task, NULL); | 
 |   | 
          else | 
 |   | 
                  ptr = NULL; | 
 |   | 
   | 
 |   | 
          if (!ptr) | 
 |   | 
                  insert_task_to(task, &root->root_rtc); | 
 |   | 
          else | 
 |   | 
                  task = sched_unuseTask(task); | 
 |   | 
   | 
 |   | 
          return task; | 
 |   | 
  #else | 
 |   | 
          sched_SetErr(ENOTSUP, "Not supported realtime clock extensions"); | 
 |   | 
          return NULL; | 
 |   | 
  #endif | 
 |  } | 
  } |