| 
version 1.16, 2013/05/30 09:13:52
 | 
version 1.21.2.2, 2013/09/02 11:19:20
 | 
| 
 Line 115  _sched_threadCleanup(sched_task_t *t)
 | 
 Line 115  _sched_threadCleanup(sched_task_t *t)
 | 
 |          if (!t || !TASK_ROOT(t)) | 
          if (!t || !TASK_ROOT(t)) | 
 |                  return; | 
                  return; | 
 |   | 
   | 
 |          if (TASK_FLAG(t) == PTHREAD_CREATE_JOINABLE) | 
   | 
 |                  pthread_detach(pthread_self()); | 
   | 
 |   | 
   | 
 |          pthread_mutex_lock(&TASK_ROOT(t)->root_mtx[taskTHREAD]); | 
          pthread_mutex_lock(&TASK_ROOT(t)->root_mtx[taskTHREAD]); | 
 |          TAILQ_REMOVE(&TASK_ROOT(t)->root_thread, t, task_node); | 
          TAILQ_REMOVE(&TASK_ROOT(t)->root_thread, t, task_node); | 
 |          pthread_mutex_unlock(&TASK_ROOT(t)->root_mtx[taskTHREAD]); | 
          pthread_mutex_unlock(&TASK_ROOT(t)->root_mtx[taskTHREAD]); | 
 |   | 
   | 
 |          sched_unuseTask(t); | 
          sched_unuseTask(t); | 
 |  } | 
  } | 
 |  void * | 
  void * | 
 |  _sched_threadWrapper(sched_task_t *t) | 
  _sched_threadWrapper(sched_task_t *t) | 
 |  { | 
  { | 
 |          void *ret = NULL; | 
          void *ret = NULL; | 
 |          sem_t *s = NULL; | 
   | 
 |   | 
   | 
 |          if (!t || !TASK_ROOT(t) || !TASK_RET(t)) | 
   | 
 |                  pthread_exit(ret); | 
   | 
 |          else | 
   | 
 |                  s = (sem_t*) TASK_RET(t); | 
   | 
 |   | 
   | 
 |          pthread_cleanup_push((void (*)(void*)) _sched_threadCleanup, t); | 
          pthread_cleanup_push((void (*)(void*)) _sched_threadCleanup, t); | 
 |   | 
   | 
 |   | 
          if (!t || !TASK_ROOT(t)) | 
 |   | 
                  pthread_exit(ret); | 
 |   | 
   | 
 |          pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); | 
          pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); | 
 |   | 
          /* | 
 |          pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); | 
          pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); | 
 |   | 
          */ | 
 |   | 
   | 
 |          /* notify parent, thread is ready for execution */ | 
          /* notify parent, thread is ready for execution */ | 
 |          sem_post(s); | 
   | 
 |          pthread_testcancel(); | 
          pthread_testcancel(); | 
 |   | 
   | 
|         ret = TASK_FUNC(t)(t); |         ret = schedCall(t); | 
 |   | 
   | 
 |          pthread_cleanup_pop(42); | 
          pthread_cleanup_pop(42); | 
 |          TASK_ROOT(t)->root_ret = ret; | 
          TASK_ROOT(t)->root_ret = ret; | 
| 
 Line 152  _sched_threadWrapper(sched_task_t *t)
 | 
 Line 146  _sched_threadWrapper(sched_task_t *t)
 | 
 |  } | 
  } | 
 |  #endif | 
  #endif | 
 |   | 
   | 
 |   | 
  #if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME) | 
 |   | 
  void * | 
 |   | 
  _sched_rtcWrapper(sched_task_t *t) | 
 |   | 
  { | 
 |   | 
          sched_task_func_t func; | 
 |   | 
          sched_task_t *task; | 
 |   | 
          sched_root_task_t *r; | 
 |   | 
   | 
 |   | 
          if (!t || !TASK_ROOT(t) || !TASK_DATA(t)) | 
 |   | 
                  return NULL; | 
 |   | 
          else { | 
 |   | 
                  r = TASK_ROOT(t); | 
 |   | 
                  task = (sched_task_t*) TASK_DATA(t); | 
 |   | 
                  func = TASK_FUNC(task); | 
 |   | 
          } | 
 |   | 
   | 
 |   | 
  #ifdef HAVE_LIBPTHREAD | 
 |   | 
          pthread_mutex_lock(&r->root_mtx[taskRTC]); | 
 |   | 
  #endif | 
 |   | 
          TAILQ_REMOVE(&r->root_rtc, task, task_node); | 
 |   | 
  #ifdef HAVE_LIBPTHREAD | 
 |   | 
          pthread_mutex_unlock(&r->root_mtx[taskRTC]); | 
 |   | 
  #endif | 
 |   | 
          sched_unuseTask(task); | 
 |   | 
   | 
 |   | 
          timer_delete((timer_t) TASK_DATLEN(t)); | 
 |   | 
   | 
 |   | 
          return schedCall(task); | 
 |   | 
  } | 
 |   | 
  #endif | 
 |   | 
   | 
 |  #pragma GCC visibility pop | 
  #pragma GCC visibility pop | 
 |   | 
   | 
 |  /* | 
  /* | 
| 
 Line 511  schedSignal(sched_root_task_t * __restrict root, sched
 | 
 Line 536  schedSignal(sched_root_task_t * __restrict root, sched
 | 
 |   * @func = task execution function | 
   * @func = task execution function | 
 |   * @arg = 1st func argument | 
   * @arg = 1st func argument | 
 |   * @ts = timeout argument structure, minimum alarm timer resolution is 1msec! | 
   * @ts = timeout argument structure, minimum alarm timer resolution is 1msec! | 
|  * @opt_data = Optional data |  * @opt_data = Alarm timer ID | 
 |   * @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 | 
 |   */ | 
   */ | 
| 
 Line 1215  schedCallOnce(sched_root_task_t * __restrict root, sch
 | 
 Line 1240  schedCallOnce(sched_root_task_t * __restrict root, sch
 | 
 |   * @root = root task | 
   * @root = root task | 
 |   * @func = task execution function | 
   * @func = task execution function | 
 |   * @arg = 1st func argument | 
   * @arg = 1st func argument | 
 |   * @detach = Detach thread from scheduler, if !=0 | 
   | 
 |   * @ss = stack size | 
   * @ss = stack size | 
 |   * @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 * | 
| schedThread(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int detach,  | schedThread(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg,  | 
 |                  size_t ss, void *opt_data, size_t opt_dlen) | 
                  size_t ss, void *opt_data, size_t opt_dlen) | 
 |  { | 
  { | 
 |  #ifndef HAVE_LIBPTHREAD | 
  #ifndef HAVE_LIBPTHREAD | 
| 
 Line 1230  schedThread(sched_root_task_t * __restrict root, sched
 | 
 Line 1254  schedThread(sched_root_task_t * __restrict root, sched
 | 
 |          return NULL; | 
          return NULL; | 
 |  #endif | 
  #endif | 
 |          sched_task_t *task; | 
          sched_task_t *task; | 
 |          void *ptr; | 
   | 
 |          pthread_attr_t attr; | 
          pthread_attr_t attr; | 
 |          sem_t *s = NULL; | 
   | 
 |   | 
   | 
 |          if (!root || !func) | 
          if (!root || !func) | 
 |                  return NULL; | 
                  return NULL; | 
 |          else { | 
   | 
 |                  /* normalizing stack size & detach state */ | 
   | 
 |                  if (ss) | 
   | 
 |                          ss &= 0x7FFFFFFF; | 
   | 
 |                  detach = detach ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE; | 
   | 
 |          } | 
   | 
 |   | 
   | 
 |          if (!(s = (sem_t*) malloc(sizeof(sem_t)))) { | 
   | 
 |                  LOGERR; | 
   | 
 |                  return NULL; | 
   | 
 |          } | 
   | 
 |          if (sem_init(s, 0, 1)) { | 
   | 
 |                  LOGERR; | 
   | 
 |                  free(s); | 
   | 
 |                  return NULL; | 
   | 
 |          } | 
   | 
 |   | 
   | 
 |          /* get new task */ | 
          /* get new task */ | 
 |          if (!(task = sched_useTask(root))) { | 
          if (!(task = sched_useTask(root))) { | 
 |                  sem_destroy(s); | 
   | 
 |                  free(s); | 
   | 
 |   | 
   | 
 |                  return NULL; | 
                  return NULL; | 
 |          } | 
          } | 
| 
 Line 1266  schedThread(sched_root_task_t * __restrict root, sched
 | 
 Line 1270  schedThread(sched_root_task_t * __restrict root, sched
 | 
 |          TASK_ROOT(task) = root; | 
          TASK_ROOT(task) = root; | 
 |   | 
   | 
 |          TASK_ARG(task) = arg; | 
          TASK_ARG(task) = arg; | 
 |          TASK_FLAG(task) = detach; | 
   | 
 |          TASK_RET(task) = (intptr_t) s; | 
   | 
 |   | 
   | 
 |          TASK_DATA(task) = opt_data; | 
          TASK_DATA(task) = opt_data; | 
 |          TASK_DATLEN(task) = opt_dlen; | 
          TASK_DATLEN(task) = opt_dlen; | 
 |   | 
   | 
 |          pthread_attr_init(&attr); | 
          pthread_attr_init(&attr); | 
|         pthread_attr_setdetachstate(&attr, detach); |         pthread_attr_setdetachstate(&attr, PTHREAD_DETACHED); | 
 |          if (ss && (errno = pthread_attr_setstacksize(&attr, ss))) { | 
          if (ss && (errno = pthread_attr_setstacksize(&attr, ss))) { | 
 |                  LOGERR; | 
                  LOGERR; | 
 |                  pthread_attr_destroy(&attr); | 
                  pthread_attr_destroy(&attr); | 
 |                  sem_destroy(s); | 
   | 
 |                  free(s); | 
   | 
 |                  return sched_unuseTask(task); | 
                  return sched_unuseTask(task); | 
 |          } | 
          } | 
 |          if ((errno = pthread_attr_getstacksize(&attr, &ss))) { | 
          if ((errno = pthread_attr_getstacksize(&attr, &ss))) { | 
 |                  LOGERR; | 
                  LOGERR; | 
 |                  pthread_attr_destroy(&attr); | 
                  pthread_attr_destroy(&attr); | 
 |                  sem_destroy(s); | 
   | 
 |                  free(s); | 
   | 
 |                  return sched_unuseTask(task); | 
                  return sched_unuseTask(task); | 
 |          } else | 
          } else | 
|                 TASK_FLAG(task) |= (ss << 1); |                 TASK_FLAG(task) = ss; | 
 |          if ((errno = pthread_attr_setguardsize(&attr, ss))) { | 
          if ((errno = pthread_attr_setguardsize(&attr, ss))) { | 
 |                  LOGERR; | 
                  LOGERR; | 
 |                  pthread_attr_destroy(&attr); | 
                  pthread_attr_destroy(&attr); | 
 |                  sem_destroy(s); | 
   | 
 |                  free(s); | 
   | 
 |                  return sched_unuseTask(task); | 
                  return sched_unuseTask(task); | 
 |          } | 
          } | 
 |  #ifdef SCHED_RR | 
  #ifdef SCHED_RR | 
| 
 Line 1301  schedThread(sched_root_task_t * __restrict root, sched
 | 
 Line 1297  schedThread(sched_root_task_t * __restrict root, sched
 | 
 |  #else | 
  #else | 
 |          pthread_attr_setschedpolicy(&attr, SCHED_OTHER); | 
          pthread_attr_setschedpolicy(&attr, SCHED_OTHER); | 
 |  #endif | 
  #endif | 
 |   | 
   | 
 |   | 
          pthread_mutex_lock(&root->root_mtx[taskTHREAD]); | 
 |   | 
          TAILQ_INSERT_TAIL(&root->root_thread, TASK_ID(task), task_node); | 
 |   | 
          pthread_mutex_unlock(&root->root_mtx[taskTHREAD]); | 
 |   | 
   | 
 |          if (root->root_hooks.hook_add.thread) | 
          if (root->root_hooks.hook_add.thread) | 
|                 ptr = root->root_hooks.hook_add.thread(task, &attr); |                 if (root->root_hooks.hook_add.thread(task, &attr)) { | 
|   |                         schedCancel(task); | 
|   |                         task = NULL; | 
|   |                 } | 
|   |         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_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME) | 
|   |         sched_task_t *task; | 
|   |         void *ptr; | 
|   |  | 
|   |         if (!root || !func) | 
|   |                 return NULL; | 
|   |  | 
|   |         /* get new task */ | 
|   |         if (!(task = sched_useTask(root))) | 
|   |                 return NULL; | 
|   |  | 
|   |         task->task_func = 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 | 
          else | 
 |                  ptr = NULL; | 
                  ptr = NULL; | 
 |          pthread_attr_destroy(&attr); | 
   | 
 |   | 
   | 
 |          if (!ptr) { | 
          if (!ptr) { | 
|                 pthread_mutex_lock(&root->root_mtx[taskTHREAD]); | #ifdef HAVE_LIBPTHREAD | 
|                 TAILQ_INSERT_TAIL(&root->root_thread, TASK_ID(task), task_node); |                 pthread_mutex_lock(&root->root_mtx[taskRTC]); | 
|                 pthread_mutex_unlock(&root->root_mtx[taskTHREAD]); | #endif | 
 |                 TAILQ_INSERT_TAIL(&root->root_rtc, TASK_ID(task), task_node); | 
|                 /* wait for init thread actions */ | #ifdef HAVE_LIBPTHREAD | 
|                 sem_wait(s); |                 pthread_mutex_unlock(&root->root_mtx[taskRTC]); | 
|   | #endif | 
 |          } else | 
          } else | 
 |                  task = sched_unuseTask(task); | 
                  task = sched_unuseTask(task); | 
 |   | 
   | 
 |          sem_destroy(s); | 
   | 
 |          free(s); | 
   | 
 |          return task; | 
          return task; | 
 |   | 
  #else | 
 |   | 
          sched_SetErr(ENOTSUP, "Not supported realtime clock extensions"); | 
 |   | 
          return NULL; | 
 |   | 
  #endif | 
 |  } | 
  } | 
 |   | 
   |