Diff for /libaitsched/src/hooks.c between versions 1.10.2.1 and 1.32

version 1.10.2.1, 2012/08/01 12:49:26 version 1.32, 2017/09/04 08:47:43
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, 2012Copyright 2004 - 2017
         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 47  SUCH DAMAGE. Line 47  SUCH DAMAGE.
 #include "hooks.h"  #include "hooks.h"
   
   
   static inline void
   transit_task2ready(sched_task_t * __restrict t, sched_queue_t * __restrict q)
   {
           remove_task_from(t, q);
   
           t->task_type = taskREADY;
           insert_task_to(t, &(TASK_ROOT(t))->root_ready);
   }
   
   #ifdef HAVE_LIBPTHREAD
   static void *
   _sched_threadWrapper(sched_task_t *t)
   {
           void *ret = NULL;
           sched_root_task_t *r;
   
           if (!t || !TASK_ROOT(t))
                   pthread_exit(ret);
           else
                   r = (sched_root_task_t*) TASK_ROOT(t);
   
           pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
           /*
           pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
           */
   
           /* notify parent, thread is ready for execution */
           pthread_testcancel();
   
           ret = schedCall(t);
           r->root_ret = ret;
   
           if (TASK_VAL(t)) {
                   transit_task2unuse(t, &r->root_thread);
                   TASK_VAL(t) = 0;
           }
   
           pthread_exit(ret);
   }
   #endif
   
   #if defined(HAVE_LIBRT) && defined(HAVE_TIMER_CREATE) && \
           defined(HAVE_TIMER_SETTIME) && defined(HAVE_TIMER_DELETE)
   #if SUP_ENABLE == KQ_SUPPORT
   static void *
   _sched_rtcWrapper(sched_task_t *t)
   {
           sched_task_t *task;
           void *ret;
   
           if (!t || !TASK_ROOT(t) || !TASK_DATA(t))
                   return NULL;
           else {
                   task = (sched_task_t*) TASK_DATA(t);
                   timer_delete((timer_t) TASK_DATLEN(t));
           }
   
           ret = schedCall(task);
   
           transit_task2unuse(task, &(TASK_ROOT(task))->root_rtc);
           return ret;
   }
   #else
   static void
   _sched_rtcSigWrapper(int sig, siginfo_t *si, void *uc)
   {
           sched_task_t *task;
   
           if (si && si->si_value.sival_ptr) {
                   task = (sched_task_t*) si->si_value.sival_ptr;
                   timer_delete((timer_t) TASK_FLAG(task));
   
                   TASK_RET(task) = (intptr_t) schedCall(task);
   
                   transit_task2unuse(task, &(TASK_ROOT(task))->root_rtc);
           }
   }
   #endif
   #endif
   
 /*  /*
  * sched_hook_init() - Default INIT hook   * sched_hook_init() - Default INIT hook
  *   *
Line 62  sched_hook_init(void *root, void *arg __unused) Line 142  sched_hook_init(void *root, void *arg __unused)
         if (!r)          if (!r)
                 return (void*) -1;                  return (void*) -1;
   
   #if SUP_ENABLE == KQ_SUPPORT
         r->root_kq = kqueue();          r->root_kq = kqueue();
         if (r->root_kq == -1) {          if (r->root_kq == -1) {
                 LOGERR;                  LOGERR;
                 return (void*) -1;                  return (void*) -1;
         }          }
   #elif SUP_ENABLE == EP_SUPPORT
           r->root_kq = epoll_create(KQ_EVENTS);
           if (r->root_kq == -1) {
                   LOGERR;
                   return (void*) -1;
           }
   #else
           r->root_kq ^= r->root_kq;
           FD_ZERO(&r->root_fds[0]);
           FD_ZERO(&r->root_fds[1]);
   #endif
   
         return NULL;          return NULL;
 }  }
Line 86  sched_hook_fini(void *root, void *arg __unused) Line 178  sched_hook_fini(void *root, void *arg __unused)
         if (!r)          if (!r)
                 return (void*) -1;                  return (void*) -1;
   
   #if SUP_ENABLE == KQ_SUPPORT || SUP_ENABLE == EP_SUPPORT
         if (r->root_kq > 2) {          if (r->root_kq > 2) {
                 close(r->root_kq);                  close(r->root_kq);
                 r->root_kq = 0;                  r->root_kq = 0;
         }          }
   #else
           FD_ZERO(&r->root_fds[1]);
           FD_ZERO(&r->root_fds[0]);
           r->root_kq ^= r->root_kq;
   #endif
   
         return NULL;          return NULL;
 }  }
Line 104  sched_hook_fini(void *root, void *arg __unused) Line 202  sched_hook_fini(void *root, void *arg __unused)
 void *  void *
 sched_hook_cancel(void *task, void *arg __unused)  sched_hook_cancel(void *task, void *arg __unused)
 {  {
        sched_task_t *t = task;        sched_task_t *t = task, *tmp, *tt;
         sched_root_task_t *r = NULL;
         int flg;
 #if SUP_ENABLE == KQ_SUPPORT
         struct kevent chg[1];          struct kevent chg[1];
         struct timespec timeout = { 0, 0 };          struct timespec timeout = { 0, 0 };
   #elif SUP_ENABLE == EP_SUPPORT
           struct epoll_event ee = { .events = 0, .data.fd = 0 };
   #else
           register int i;
   #endif
   #ifdef AIO_SUPPORT
           struct aiocb *acb;
   #ifdef EVFILT_LIO
           register int i = 0;
           struct aiocb **acbs;
   #endif  /* EVFILT_LIO */
   #endif  /* AIO_SUPPORT */
   
         if (!t || !TASK_ROOT(t))          if (!t || !TASK_ROOT(t))
                 return (void*) -1;                  return (void*) -1;
           else
                   r = TASK_ROOT(t);
   
         switch (TASK_TYPE(t)) {          switch (TASK_TYPE(t)) {
                 case taskREAD:                  case taskREAD:
                           /* check for multi subscribers */
                           flg = 0;
                           TAILQ_FOREACH_SAFE(tt, &r->root_read, task_node, tmp)
                                   if (TASK_FD(tt) != TASK_FD(t))
                                           continue;
                                   else
                                           flg++;
   #if SUP_ENABLE == KQ_SUPPORT
 #ifdef __NetBSD__  #ifdef __NetBSD__
                        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_DELETE, 0, 0, (intptr_t) TASK_FD(t));                        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, flg < 2 ? EV_DELETE : 0, 
                                         0, 0, (intptr_t) TASK_FD(t));
 #else  #else
                        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_DELETE, 0, 0, (void*) TASK_FD(t));                        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, flg < 2 ? EV_DELETE : 0, 
                                         0, 0, (void*) TASK_FD(t));
 #endif  #endif
   #elif SUP_ENABLE == EP_SUPPORT
                           ee.data.fd = TASK_FD(t);
                           ee.events ^= ee.events;
                           if (FD_ISSET(TASK_FD(t), &r->root_fds[1]))
                                   ee.events = EPOLLOUT;
   
                           if (flg < 2)
                                   FD_CLR(TASK_FD(t), &r->root_fds[0]);
                           else
                                   ee.events |= EPOLLIN | EPOLLPRI;
   #else
                           if (flg < 2) {
                                   FD_CLR(TASK_FD(t), &r->root_fds[0]);
   
                                   /* optimize select */
                                   for (i = r->root_kq - 1; i > 2; i--)
                                           if (FD_ISSET(i, &r->root_fds[0]) || FD_ISSET(i, &r->root_fds[1]))
                                                   break;
                                   if (i > 2)
                                           r->root_kq = i + 1;
                           }
   #endif
                         break;                          break;
                 case taskWRITE:                  case taskWRITE:
                           /* check for multi subscribers */
                           flg = 0;
                           TAILQ_FOREACH_SAFE(tt, &r->root_write, task_node, tmp)
                                   if (TASK_FD(tt) != TASK_FD(t))
                                           continue;
                                   else
                                           flg++;
   #if SUP_ENABLE == KQ_SUPPORT
 #ifdef __NetBSD__  #ifdef __NetBSD__
                        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_DELETE, 0, 0, (intptr_t) TASK_FD(t));                        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, flg < 2 ? EV_DELETE : 0, 
                                         0, 0, (intptr_t) TASK_FD(t));
 #else  #else
                        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_DELETE, 0, 0, (void*) TASK_FD(t));                        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, flg < 2 ? EV_DELETE : 0, 
                                         0, 0, (void*) TASK_FD(t));
 #endif  #endif
   #elif SUP_ENABLE == EP_SUPPORT
                           ee.data.fd = TASK_FD(t);
                           ee.events ^= ee.events;
                           if (FD_ISSET(TASK_FD(t), &r->root_fds[0]))
                                   ee.events = EPOLLIN | EPOLLPRI;
   
                           if (flg < 2)
                                   FD_CLR(TASK_FD(t), &r->root_fds[1]);
                           else
                                   ee.events |= EPOLLOUT;
   #else
                           if (flg < 2) {
                                   FD_CLR(TASK_FD(t), &r->root_fds[1]);
   
                                   /* optimize select */
                                   for (i = r->root_kq - 1; i > 2; i--)
                                           if (FD_ISSET(i, &r->root_fds[0]) || FD_ISSET(i, &r->root_fds[1]))
                                                   break;
                                   if (i > 2)
                                           r->root_kq = i + 1;
                           }
   #endif
                         break;                          break;
                 case taskALARM:                  case taskALARM:
   #if SUP_ENABLE == KQ_SUPPORT
                           /* check for multi subscribers */
                           flg = 0;
                           TAILQ_FOREACH_SAFE(tt, &r->root_alarm, task_node, tmp)
                                   if (TASK_DATA(tt) != TASK_DATA(t))
                                           continue;
                                   else
                                           flg++;
 #ifdef __NetBSD__  #ifdef __NetBSD__
                        EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_DELETE                        EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, flg < 2 ? EV_DELETE : 0, 
                                         0, 0, (intptr_t) TASK_DATA(t));                                          0, 0, (intptr_t) TASK_DATA(t));
 #else  #else
                        EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_DELETE                        EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, flg < 2 ? EV_DELETE : 0, 
                                         0, 0, (void*) TASK_DATA(t));                                          0, 0, (void*) TASK_DATA(t));
 #endif  #endif
   #endif
                         break;                          break;
                 case taskNODE:                  case taskNODE:
   #if SUP_ENABLE == KQ_SUPPORT
                           /* check for multi subscribers */
                           flg = 0;
                           TAILQ_FOREACH_SAFE(tt, &r->root_node, task_node, tmp)
                                   if (TASK_FD(tt) != TASK_FD(t))
                                           continue;
                                   else
                                           flg++;
 #ifdef __NetBSD__  #ifdef __NetBSD__
                        EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_DELETE, 0, 0, (intptr_t) TASK_FD(t));                        EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, flg < 2 ? EV_DELETE : 0, 
                                         0, 0, (intptr_t) TASK_FD(t));
 #else  #else
                        EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_DELETE, 0, 0, (void*) TASK_FD(t));                        EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, flg < 2 ? EV_DELETE : 0, 
                                         0, 0, (void*) TASK_FD(t));
 #endif  #endif
   #endif
                         break;                          break;
                 case taskPROC:                  case taskPROC:
   #if SUP_ENABLE == KQ_SUPPORT
                           /* check for multi subscribers */
                           flg = 0;
                           TAILQ_FOREACH_SAFE(tt, &r->root_proc, task_node, tmp)
                                   if (TASK_VAL(tt) != TASK_VAL(t))
                                           continue;
                                   else
                                           flg++;
 #ifdef __NetBSD__  #ifdef __NetBSD__
                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, flg < 2 ? EV_DELETE : 0, 
                                         0, 0, (intptr_t) TASK_VAL(t));
 #else  #else
                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_DELETE, 0, 0, (void*) TASK_VAL(t));                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, flg < 2 ? EV_DELETE : 0, 
                                         0, 0, (void*) TASK_VAL(t));
 #endif  #endif
   #endif
                         break;                          break;
                 case taskSIGNAL:                  case taskSIGNAL:
   #if SUP_ENABLE == KQ_SUPPORT
                           /* check for multi subscribers */
                           flg = 0;
                           TAILQ_FOREACH_SAFE(tt, &r->root_signal, task_node, tmp)
                                   if (TASK_VAL(tt) != TASK_VAL(t))
                                           continue;
                                   else
                                           flg++;
 #ifdef __NetBSD__  #ifdef __NetBSD__
                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, flg < 2 ? EV_DELETE : 0, 
                                         0, 0, (intptr_t) TASK_VAL(t));
 #else  #else
                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_DELETE, 0, 0, (void*) TASK_VAL(t));                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, flg < 2 ? EV_DELETE : 0, 
                                         0, 0, (void*) TASK_VAL(t));
 #endif  #endif
                           /* restore signal */
                           if (flg < 2)
                                   signal(TASK_VAL(t), SIG_DFL);
   #endif
                         break;                          break;
#ifdef EVFILT_AIO#ifdef AIO_SUPPORT
                 case taskAIO:                  case taskAIO:
   #if SUP_ENABLE == KQ_SUPPORT
                           /* check for multi subscribers */
                           flg = 0;
                           TAILQ_FOREACH_SAFE(tt, &r->root_aio, task_node, tmp)
                                   if (TASK_VAL(tt) != TASK_VAL(t))
                                           continue;
                                   else
                                           flg++;
 #ifdef __NetBSD__  #ifdef __NetBSD__
                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_AIO, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_AIO, flg < 2 ? EV_DELETE : 0, 
                                         0, 0, (intptr_t) TASK_VAL(t));
 #else  #else
                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_AIO, EV_DELETE, 0, 0, (void*) TASK_VAL(t));                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_AIO, flg < 2 ? EV_DELETE : 0, 
                                         0, 0, (void*) TASK_VAL(t));
 #endif  #endif
                           acb = (struct aiocb*) TASK_VAL(t);
                           if (acb) {
                                   if (aio_cancel(acb->aio_fildes, acb) == AIO_CANCELED)
                                           aio_return(acb);
                                   free(acb);
                                   TASK_VAL(t) = 0;
                           }
   #endif
                         break;                          break;
   #ifdef EVFILT_LIO
                   case taskLIO:
   #if SUP_ENABLE == KQ_SUPPORT
                           /* check for multi subscribers */
                           flg = 0;
                           TAILQ_FOREACH_SAFE(tt, &r->root_lio, task_node, tmp)
                                   if (TASK_VAL(tt) != TASK_VAL(t))
                                           continue;
                                   else
                                           flg++;
   #ifdef __NetBSD__
                           EV_SET(&chg[0], TASK_VAL(t), EVFILT_LIO, flg < 2 ? EV_DELETE : 0, 
                                           0, 0, (intptr_t) TASK_VAL(t));
   #else
                           EV_SET(&chg[0], TASK_VAL(t), EVFILT_LIO, flg < 2 ? EV_DELETE : 0, 
                                           0, 0, (void*) TASK_VAL(t));
 #endif  #endif
                           acbs = (struct aiocb**) TASK_VAL(t);
                           if (acbs) {
                                   for (i = 0; i < TASK_DATLEN(t); i++) {
                                           if (aio_cancel(acbs[i]->aio_fildes, acbs[i]) == AIO_CANCELED)
                                                   aio_return(acbs[i]);
                                           free(acbs[i]);
                                   }
                                   free(acbs);
                                   TASK_VAL(t) = 0;
                           }
   #endif
                           break;
   #endif  /* EVFILT_LIO */
   #endif  /* AIO_SUPPORT */
 #ifdef EVFILT_USER  #ifdef EVFILT_USER
                 case taskUSER:                  case taskUSER:
   #if SUP_ENABLE == KQ_SUPPORT
                           /* check for multi subscribers */
                           flg = 0;
                           TAILQ_FOREACH_SAFE(tt, &r->root_user, task_node, tmp)
                                   if (TASK_VAL(tt) != TASK_VAL(t))
                                           continue;
                                   else
                                           flg++;
 #ifdef __NetBSD__  #ifdef __NetBSD__
                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, flg < 2 ? EV_DELETE : 0, 
                                         0, 0, (intptr_t) TASK_VAL(t));
 #else  #else
                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_DELETE, 0, 0, (void*) TASK_VAL(t));                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, flg < 2 ? EV_DELETE : 0, 
                                         0, 0, (void*) TASK_VAL(t));
 #endif  #endif
   #endif
                         break;                          break;
   #endif  /* EVFILT_USER */
                   case taskTHREAD:
   #ifdef HAVE_LIBPTHREAD
                           if (TASK_VAL(t)) {
                                   pthread_cancel((pthread_t) TASK_VAL(t));
                                   pthread_join((pthread_t) TASK_VAL(t), NULL);
                                   if (TASK_VAL(t)) {
                                           transit_task2unuse(t, &(TASK_ROOT(t))->root_thread);
                                           TASK_VAL(t) = 0;
                                   }
                           }
 #endif  #endif
                           return NULL;
   #if defined(HAVE_LIBRT) && defined(HAVE_TIMER_CREATE) && \
           defined(HAVE_TIMER_SETTIME) && defined(HAVE_TIMER_DELETE)
                   case taskRTC:
                           timer_delete((timer_t) TASK_FLAG(t));
   #if SUP_ENABLE == KQ_SUPPORT
                           schedCancel((sched_task_t*) TASK_RET(t));
   #else
                           /* check for multi subscribers */
                           flg = 0;
                           TAILQ_FOREACH_SAFE(tt, &r->root_rtc, task_node, tmp)
                                   if (TASK_DATA(tt) != TASK_DATA(t))
                                           continue;
                                   else
                                           flg++;
   
                           /* restore signal */
                           if (flg < 2)
                                   signal((intptr_t) TASK_DATA(t) + SIGRTMIN, SIG_DFL);
   #endif
                           return NULL;
   #endif  /* HAVE_TIMER_CREATE */
                 default:                  default:
                         return NULL;                          return NULL;
         }          }
   
        kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout);#if SUP_ENABLE == KQ_SUPPORT
         kevent(r->root_kq, chg, 1, NULL, 0, &timeout);
 #elif SUP_ENABLE == EP_SUPPORT
         epoll_ctl(r->root_kq, ee.events ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, ee.data.fd, &ee);
 #endif
         return NULL;          return NULL;
 }  }
   
   #ifdef HAVE_LIBPTHREAD
 /*  /*
    * sched_hook_thread() - Default THREAD hook
    *
    * @task = current task
    * @arg = pthread attributes
    * return: <0 errors and 0 ok
    */
   void *
   sched_hook_thread(void *task, void *arg)
   {
           sched_task_t *t = task;
           pthread_t tid;
           sigset_t s, o;
   
           if (!t || !TASK_ROOT(t))
                   return (void*) -1;
   
           sigfillset(&s);
           pthread_sigmask(SIG_BLOCK, &s, &o);
           errno = pthread_create(&tid, (pthread_attr_t*) arg, 
                           (void *(*)(void*)) _sched_threadWrapper, t);
           pthread_sigmask(SIG_SETMASK, &o, NULL);
   
           if (errno) {
                   LOGERR;
                   return (void*) -1;
           } else
                   TASK_VAL(t) = (u_long) tid;
   
           if (!TASK_ISLOCKED(t))
                   TASK_LOCK(t);
   
           return NULL;
   }
   #endif
   
   /*
  * sched_hook_read() - Default READ hook   * sched_hook_read() - Default READ hook
  *   *
  * @task = current task   * @task = current task
Line 193  void * Line 550  void *
 sched_hook_read(void *task, void *arg __unused)  sched_hook_read(void *task, void *arg __unused)
 {  {
         sched_task_t *t = task;          sched_task_t *t = task;
           sched_root_task_t *r = NULL;
   #if SUP_ENABLE == KQ_SUPPORT
         struct kevent chg[1];          struct kevent chg[1];
         struct timespec timeout = { 0, 0 };          struct timespec timeout = { 0, 0 };
   #elif SUP_ENABLE == EP_SUPPORT
           struct epoll_event ee;
           int flg = 0;
   #endif
   
         if (!t || !TASK_ROOT(t))          if (!t || !TASK_ROOT(t))
                 return (void*) -1;                  return (void*) -1;
           else
                   r = TASK_ROOT(t);
   
   #if SUP_ENABLE == KQ_SUPPORT
 #ifdef __NetBSD__  #ifdef __NetBSD__
         EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, (intptr_t) TASK_FD(t));          EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, (intptr_t) TASK_FD(t));
 #else  #else
         EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, (void*) TASK_FD(t));          EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, (void*) TASK_FD(t));
 #endif  #endif
        if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {        if (kevent(r->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)                if (r->root_hooks.hook_exec.exception)
                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);                        r->root_hooks.hook_exec.exception(r, NULL);
                 else                  else
                         LOGERR;                          LOGERR;
                 return (void*) -1;                  return (void*) -1;
         }          }
   #elif SUP_ENABLE == EP_SUPPORT
           ee.data.fd = TASK_FD(t);
           ee.events = EPOLLIN | EPOLLPRI;
           if (FD_ISSET(TASK_FD(t), &r->root_fds[0]))
                   flg |= 1;
           if (FD_ISSET(TASK_FD(t), &r->root_fds[1])) {
                   flg |= 2;
                   ee.events |= EPOLLOUT;
           }
   
           if (epoll_ctl(r->root_kq, flg ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, TASK_FD(t), &ee) == -1) {
                   if (r->root_hooks.hook_exec.exception)
                           r->root_hooks.hook_exec.exception(r, NULL);
                   else
                           LOGERR;
                   return (void*) -1;
           } else
                   FD_SET(TASK_FD(t), &r->root_fds[0]);
   #else
           FD_SET(TASK_FD(t), &r->root_fds[0]);
           if (TASK_FD(t) >= r->root_kq)
                   r->root_kq = TASK_FD(t) + 1;
   #endif
   
         return NULL;          return NULL;
 }  }
   
Line 226  void * Line 615  void *
 sched_hook_write(void *task, void *arg __unused)  sched_hook_write(void *task, void *arg __unused)
 {  {
         sched_task_t *t = task;          sched_task_t *t = task;
           sched_root_task_t *r = NULL;
   #if SUP_ENABLE == KQ_SUPPORT
         struct kevent chg[1];          struct kevent chg[1];
         struct timespec timeout = { 0, 0 };          struct timespec timeout = { 0, 0 };
   #elif SUP_ENABLE == EP_SUPPORT
           struct epoll_event ee;
           int flg = 0;
   #endif
   
         if (!t || !TASK_ROOT(t))          if (!t || !TASK_ROOT(t))
                 return (void*) -1;                  return (void*) -1;
           else
                   r = TASK_ROOT(t);
   
   #if SUP_ENABLE == KQ_SUPPORT
 #ifdef __NetBSD__  #ifdef __NetBSD__
         EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, (intptr_t) TASK_FD(t));          EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, (intptr_t) TASK_FD(t));
 #else  #else
         EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, (void*) TASK_FD(t));          EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, (void*) TASK_FD(t));
 #endif  #endif
        if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {        if (kevent(r->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)                if (r->root_hooks.hook_exec.exception)
                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);                        r->root_hooks.hook_exec.exception(r, NULL);
                 else                  else
                         LOGERR;                          LOGERR;
                 return (void*) -1;                  return (void*) -1;
         }          }
   #elif SUP_ENABLE == EP_SUPPORT
           ee.data.fd = TASK_FD(t);
           ee.events = EPOLLOUT;
   
           if (FD_ISSET(TASK_FD(t), &r->root_fds[0])) {
                   flg |= 1;
                   ee.events |= EPOLLIN | EPOLLPRI;
           }
           if (FD_ISSET(TASK_FD(t), &r->root_fds[1]))
                   flg |= 2;
   
           if (epoll_ctl(r->root_kq, flg ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, TASK_FD(t), &ee) == -1) {
                   if (r->root_hooks.hook_exec.exception)
                           r->root_hooks.hook_exec.exception(r, NULL);
                   else
                           LOGERR;
                   return (void*) -1;
           } else
                   FD_SET(TASK_FD(t), &r->root_fds[1]);
   #else
           FD_SET(TASK_FD(t), &r->root_fds[1]);
           if (TASK_FD(t) >= r->root_kq)
                   r->root_kq = TASK_FD(t) + 1;
   #endif
   
         return NULL;          return NULL;
 }  }
   
Line 258  sched_hook_write(void *task, void *arg __unused) Line 680  sched_hook_write(void *task, void *arg __unused)
 void *  void *
 sched_hook_alarm(void *task, void *arg __unused)  sched_hook_alarm(void *task, void *arg __unused)
 {  {
   #if SUP_ENABLE == KQ_SUPPORT
         sched_task_t *t = task;          sched_task_t *t = task;
         struct kevent chg[1];          struct kevent chg[1];
         struct timespec timeout = { 0, 0 };          struct timespec timeout = { 0, 0 };
Line 266  sched_hook_alarm(void *task, void *arg __unused) Line 689  sched_hook_alarm(void *task, void *arg __unused)
                 return (void*) -1;                  return (void*) -1;
   
 #ifdef __NetBSD__  #ifdef __NetBSD__
        EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0,         EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_ADD | EV_CLEAR, 0, 
                         t->task_val.ts.tv_sec * 1000 + t->task_val.ts.tv_nsec / 1000000,                           t->task_val.ts.tv_sec * 1000 + t->task_val.ts.tv_nsec / 1000000, 
                         (intptr_t) TASK_DATA(t));                          (intptr_t) TASK_DATA(t));
 #else  #else
        EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0,         EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_ADD | EV_CLEAR, 0, 
                         t->task_val.ts.tv_sec * 1000 + t->task_val.ts.tv_nsec / 1000000,                           t->task_val.ts.tv_sec * 1000 + t->task_val.ts.tv_nsec / 1000000, 
                         (void*) TASK_DATA(t));                          (void*) TASK_DATA(t));
 #endif  #endif
Line 282  sched_hook_alarm(void *task, void *arg __unused) Line 705  sched_hook_alarm(void *task, void *arg __unused)
                 return (void*) -1;                  return (void*) -1;
         }          }
   
   #endif
         return NULL;          return NULL;
 }  }
   
Line 295  sched_hook_alarm(void *task, void *arg __unused) Line 719  sched_hook_alarm(void *task, void *arg __unused)
 void *  void *
 sched_hook_node(void *task, void *arg __unused)  sched_hook_node(void *task, void *arg __unused)
 {  {
   #if SUP_ENABLE == KQ_SUPPORT
         sched_task_t *t = task;          sched_task_t *t = task;
         struct kevent chg[1];          struct kevent chg[1];
         struct timespec timeout = { 0, 0 };          struct timespec timeout = { 0, 0 };
Line 319  sched_hook_node(void *task, void *arg __unused) Line 744  sched_hook_node(void *task, void *arg __unused)
                 return (void*) -1;                  return (void*) -1;
         }          }
   
   #endif
         return NULL;          return NULL;
 }  }
   
Line 332  sched_hook_node(void *task, void *arg __unused) Line 758  sched_hook_node(void *task, void *arg __unused)
 void *  void *
 sched_hook_proc(void *task, void *arg __unused)  sched_hook_proc(void *task, void *arg __unused)
 {  {
   #if SUP_ENABLE == KQ_SUPPORT
         sched_task_t *t = task;          sched_task_t *t = task;
         struct kevent chg[1];          struct kevent chg[1];
         struct timespec timeout = { 0, 0 };          struct timespec timeout = { 0, 0 };
Line 354  sched_hook_proc(void *task, void *arg __unused) Line 781  sched_hook_proc(void *task, void *arg __unused)
                 return (void*) -1;                  return (void*) -1;
         }          }
   
   #endif
         return NULL;          return NULL;
 }  }
   
Line 367  sched_hook_proc(void *task, void *arg __unused) Line 795  sched_hook_proc(void *task, void *arg __unused)
 void *  void *
 sched_hook_signal(void *task, void *arg __unused)  sched_hook_signal(void *task, void *arg __unused)
 {  {
   #if SUP_ENABLE == KQ_SUPPORT
         sched_task_t *t = task;          sched_task_t *t = task;
         struct kevent chg[1];          struct kevent chg[1];
         struct timespec timeout = { 0, 0 };          struct timespec timeout = { 0, 0 };
Line 374  sched_hook_signal(void *task, void *arg __unused) Line 803  sched_hook_signal(void *task, void *arg __unused)
         if (!t || !TASK_ROOT(t))          if (!t || !TASK_ROOT(t))
                 return (void*) -1;                  return (void*) -1;
   
           /* ignore signal */
           signal(TASK_VAL(t), SIG_IGN);
   
 #ifdef __NetBSD__  #ifdef __NetBSD__
        EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_ADD, 0, 0, (intptr_t) TASK_VAL(t));        EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_ADD | EV_CLEAR, 0, 0, (intptr_t) TASK_VAL(t));
 #else  #else
        EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_ADD, 0, 0, (void*) TASK_VAL(t));        EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_ADD | EV_CLEAR, 0, 0, (void*) TASK_VAL(t));
 #endif  #endif
         if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {          if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                 if (TASK_ROOT(t)->root_hooks.hook_exec.exception)                  if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
Line 386  sched_hook_signal(void *task, void *arg __unused) Line 818  sched_hook_signal(void *task, void *arg __unused)
                         LOGERR;                          LOGERR;
                 return (void*) -1;                  return (void*) -1;
         }          }
#endif
         return NULL;          return NULL;
 }  }
   
Line 401  sched_hook_signal(void *task, void *arg __unused) Line 833  sched_hook_signal(void *task, void *arg __unused)
 void *  void *
 sched_hook_user(void *task, void *arg __unused)  sched_hook_user(void *task, void *arg __unused)
 {  {
   #if SUP_ENABLE == KQ_SUPPORT
         sched_task_t *t = task;          sched_task_t *t = task;
         struct kevent chg[1];          struct kevent chg[1];
         struct timespec timeout = { 0, 0 };          struct timespec timeout = { 0, 0 };
Line 423  sched_hook_user(void *task, void *arg __unused) Line 856  sched_hook_user(void *task, void *arg __unused)
                 return (void*) -1;                  return (void*) -1;
         }          }
   
   #endif
         return NULL;          return NULL;
 }  }
 #endif  #endif
   
   #if SUP_ENABLE == KQ_SUPPORT
   static inline void 
   fetch_hook_kevent_proceed(int en, struct kevent *res, sched_root_task_t *r)
   {
           struct kevent evt[1];
           register int i;
           sched_task_t *task, *tmp;
           struct timespec now = { 0, 0 };
   #ifdef AIO_SUPPORT
           int len, fd;
           struct aiocb *acb;
   #ifdef EVFILT_LIO
           int l;
           off_t off;
           struct aiocb **acbs;
           struct iovec *iv;
   #endif  /* EVFILT_LIO */
   #endif  /* AIO_SUPPORT */
   
           for (i = 0; i < en; i++) {
                   memcpy(evt, &res[i], sizeof evt);
                   evt->flags = EV_DELETE;
                   /* Put read/write task to ready queue */
                   switch (res[i].filter) {
                           case EVFILT_READ:
                                   TAILQ_FOREACH_SAFE(task, &r->root_read, task_node, tmp) {
                                           if (TASK_FD(task) == ((intptr_t) res[i].udata)) {
                                                   TASK_RET(task) = res[i].data;
                                                   TASK_FLAG(task) = (u_long) res[i].fflags;
   
                                                   /* remove read handle */
                                                   remove_task_from(task, &r->root_read);
   
                                                   if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
                                                           if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
                                                                   task->task_type = taskUNUSE;
                                                                   insert_task_to(task, &r->root_unuse);
                                                           } else {
                                                                   task->task_type = taskREADY;
                                                                   insert_task_to(task, &r->root_ready);
                                                           }
                                                   } else {
                                                           task->task_type = taskREADY;
                                                           insert_task_to(task, &r->root_ready);
                                                   }
                                                   break;
                                           }
                                   }
                                   break;
                           case EVFILT_WRITE:
                                   TAILQ_FOREACH_SAFE(task, &r->root_write, task_node, tmp) {
                                           if (TASK_FD(task) == ((intptr_t) res[i].udata)) {
                                                   TASK_RET(task) = res[i].data;
                                                   TASK_FLAG(task) = (u_long) res[i].fflags;
   
                                                   /* remove write handle */
                                                   remove_task_from(task, &r->root_write);
   
                                                   if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
                                                           if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
                                                                   task->task_type = taskUNUSE;
                                                                   insert_task_to(task, &r->root_unuse);
                                                           } else {
                                                                   task->task_type = taskREADY;
                                                                   insert_task_to(task, &r->root_ready);
                                                           }
                                                   } else {
                                                           task->task_type = taskREADY;
                                                           insert_task_to(task, &r->root_ready);
                                                   }
                                                   break;
                                           }
                                   }
                                   break;
                           case EVFILT_TIMER:
                                   TAILQ_FOREACH_SAFE(task, &r->root_alarm, task_node, tmp) {
                                           if ((uintptr_t) TASK_DATA(task) == ((uintptr_t) res[i].udata)) {
                                                   TASK_RET(task) = res[i].data;
                                                   TASK_FLAG(task) = (u_long) res[i].fflags;
   
                                                   /* remove alarm handle */
                                                   transit_task2ready(task, &r->root_alarm);
                                                   break;
                                           }
                                   }
                                   break;
                           case EVFILT_VNODE:
                                   TAILQ_FOREACH_SAFE(task, &r->root_node, task_node, tmp) {
                                           if (TASK_FD(task) == ((intptr_t) res[i].udata)) {
                                                   TASK_RET(task) = res[i].data;
                                                   TASK_FLAG(task) = (u_long) res[i].fflags;
   
                                                   /* remove node handle */
                                                   transit_task2ready(task, &r->root_node);
                                                   break;
                                           }
                                   }
                                   break;
                           case EVFILT_PROC:
                                   TAILQ_FOREACH_SAFE(task, &r->root_proc, task_node, tmp) {
                                           if (TASK_VAL(task) == ((uintptr_t) res[i].udata)) {
                                                   TASK_RET(task) = res[i].data;
                                                   TASK_FLAG(task) = (u_long) res[i].fflags;
   
                                                   /* remove proc handle */
                                                   transit_task2ready(task, &r->root_proc);
                                                   break;
                                           }
                                   }
                                   break;
                           case EVFILT_SIGNAL:
                                   TAILQ_FOREACH_SAFE(task, &r->root_signal, task_node, tmp) {
                                           if (TASK_VAL(task) == ((uintptr_t) res[i].udata)) {
                                                   TASK_RET(task) = res[i].data;
                                                   TASK_FLAG(task) = (u_long) res[i].fflags;
   
                                                   /* remove signal handle */
                                                   transit_task2ready(task, &r->root_signal);
                                                   break;
                                           }
                                   }
                                   break;
   #ifdef AIO_SUPPORT
                           case EVFILT_AIO:
                                   TAILQ_FOREACH_SAFE(task, &r->root_aio, task_node, tmp) {
                                           acb = (struct aiocb*) TASK_VAL(task);
                                           if (acb == ((struct aiocb*) res[i].udata)) {
                                                   TASK_RET(task) = res[i].data;
                                                   TASK_FLAG(task) = (u_long) res[i].fflags;
                                                   
                                                   /* remove user handle */
                                                   transit_task2ready(task, &r->root_aio);
   
                                                   fd = acb->aio_fildes;
                                                   if ((len = aio_return(acb)) != -1) {
                                                           if (lseek(fd, acb->aio_offset + len, SEEK_CUR) == -1)
                                                                   LOGERR;
                                                   } else
                                                           LOGERR;
                                                   free(acb);
                                                   TASK_DATLEN(task) = (u_long) len;
                                                   TASK_FD(task) = fd;
                                                   break;
                                           }
                                   }
                                   break;
   #ifdef EVFILT_LIO
                           case EVFILT_LIO:
                                   TAILQ_FOREACH_SAFE(task, &r->root_lio, task_node, tmp) {
                                           acbs = (struct aiocb**) TASK_VAL(task);
                                           if (acbs == ((struct aiocb**) res[i].udata)) {
                                                   TASK_RET(task) = res[i].data;
                                                   TASK_FLAG(task) = (u_long) res[i].fflags;
   
                                                   /* remove user handle */
                                                   transit_task2ready(task, &r->root_lio);
   
                                                   iv = (struct iovec*) TASK_DATA(task);
                                                   fd = acbs[0]->aio_fildes;
                                                   off = acbs[0]->aio_offset;
                                                   for (len = 0; i < TASK_DATLEN(task); len += l, i++) {
                                                           if ((iv[i].iov_len = aio_return(acbs[i])) == -1)
                                                                   l = 0;
                                                           else
                                                                   l = iv[i].iov_len;
                                                           free(acbs[i]);
                                                   }
                                                   free(acbs);
                                                   TASK_DATLEN(task) = (u_long) len;
                                                   TASK_FD(task) = fd;
   
                                                   if (lseek(fd, off + len, SEEK_CUR) == -1)
                                                           LOGERR;
                                                   break;
                                           }
                                   }
                                   break;
   #endif  /* EVFILT_LIO */
   #endif  /* AIO_SUPPORT */
   #ifdef EVFILT_USER
                           case EVFILT_USER:
                                   TAILQ_FOREACH_SAFE(task, &r->root_user, task_node, tmp) {
                                           if (TASK_VAL(task) == ((uintptr_t) res[i].udata)) {
                                                   TASK_RET(task) = res[i].data;
                                                   TASK_FLAG(task) = (u_long) res[i].fflags;
   
                                                   /* remove user handle */
                                                   transit_task2ready(task, &r->root_user);
                                                   break;
                                           }
                                   }
                                   break;
   #endif  /* EVFILT_USER */
                   }
   
                   if (kevent(r->root_kq, evt, 1, NULL, 0, &now) == -1) {
                           if (r->root_hooks.hook_exec.exception)
                                   r->root_hooks.hook_exec.exception(r, NULL);
                           else
                                   LOGERR;
                   }
           }
   }
   #endif
   
   #if SUP_ENABLE == EP_SUPPORT
   static inline void
   fetch_hook_epoll_proceed(int en, struct epoll_event *res, sched_root_task_t *r)
   {
           register int i, flg;
           int ops = EPOLL_CTL_DEL;
           sched_task_t *t, *tmp, *task;
           struct epoll_event evt[1];
   
           for (i = 0; i < en; i++) {
                   memcpy(evt, &res[i], sizeof evt);
   
                   if (evt->events & (EPOLLIN | EPOLLPRI)) {
                           flg = 0;
                           task = NULL;
                           TAILQ_FOREACH_SAFE(t, &r->root_read, task_node, tmp) {
                                   if (TASK_FD(t) == evt->data.fd) {
                                           if (!flg)
                                                   task = t;
                                           flg++;
                                   }
                           }
   
                           if (flg && task) {
                                   TASK_FLAG(task) = ioctl(TASK_FD(task), FIONREAD, &TASK_RET(task));
                                   /* remove read handle */
                                   remove_task_from(task, &r->root_read);
   
                                   if (r->root_hooks.hook_exec.exception && evt->events & (EPOLLRDHUP | EPOLLERR | EPOLLHUP)) {
                                           if (r->root_hooks.hook_exec.exception(r, (void*) (intptr_t)
                                                                   (evt->events & EPOLLERR ? EV_ERROR | EV_EOF : EV_EOF))) {
                                                   task->task_type = taskUNUSE;
                                                   insert_task_to(task, &r->root_unuse);
                                           } else {
                                                   task->task_type = taskREADY;
                                                   insert_task_to(task, &r->root_ready);
                                           }
                                   } else {
                                           task->task_type = taskREADY;
                                           insert_task_to(task, &r->root_ready);
                                   }
   
                                   evt->events ^= evt->events;
                                   if (FD_ISSET(evt->data.fd, &r->root_fds[1])) {
                                           ops = EPOLL_CTL_MOD;
                                           evt->events |= EPOLLOUT;
                                   }
                                   if (flg > 1) {
                                           ops = EPOLL_CTL_MOD;
                                           evt->events |= EPOLLIN | EPOLLPRI;
                                   } else
                                           FD_CLR(evt->data.fd, &r->root_fds[0]);
                           }
                   } else if (evt->events & EPOLLOUT) {
                           flg = 0;
                           task = NULL;
                           TAILQ_FOREACH_SAFE(t, &r->root_write, task_node, tmp) {
                                   if (TASK_FD(t) == evt->data.fd) {
                                           if (!flg)
                                                   task = t;
                                           flg++;
                                   }
                           }
   
                           if (flg && task) {
                                   TASK_FLAG(task) = ioctl(TASK_FD(task), FIONWRITE, &TASK_RET(task));
                                   /* remove write handle */
                                   remove_task_from(task, &r->root_write);
   
                                   if (r->root_hooks.hook_exec.exception && evt->events & (EPOLLERR | EPOLLHUP)) {
                                           if (r->root_hooks.hook_exec.exception(r, (void*) (intptr_t)
                                                                   (evt->events & EPOLLERR ? EV_ERROR | EV_EOF : EV_EOF))) {
                                                   task->task_type = taskUNUSE;
                                                   insert_task_to(task, &r->root_unuse);
                                           } else {
                                                   task->task_type = taskREADY;
                                                   insert_task_to(task, &r->root_ready);
                                           }
                                   } else {
                                           task->task_type = taskREADY;
                                           insert_task_to(task, &r->root_ready);
                                   }
   
                                   evt->events ^= evt->events;
                                   if (FD_ISSET(evt->data.fd, &r->root_fds[0])) {
                                           ops = EPOLL_CTL_MOD;
                                           evt->events |= EPOLLIN | EPOLLPRI;
                                   }
                                   if (flg > 1) {
                                           ops = EPOLL_CTL_MOD;
                                           evt->events |= EPOLLOUT;
                                   } else
                                           FD_CLR(evt->data.fd, &r->root_fds[1]);
                           }
                   }
   
                   if (epoll_ctl(r->root_kq, ops, evt->data.fd, evt) == -1) {
                           if (r->root_hooks.hook_exec.exception) {
                                   r->root_hooks.hook_exec.exception(r, NULL);
                           } else
                                   LOGERR;
                   }
           }
   }
   #endif
   
   #if SUP_ENABLE == NO_SUPPORT
   static inline void 
   fetch_hook_select_proceed(int en, fd_set rfd, fd_set wfd, fd_set xfd, sched_root_task_t *r)
   {
           register int i, flg;
           sched_task_t *t, *tmp, *task = NULL;
   
           /* skip select check if return value from select is zero */
           if (!en)
                   return;
   
           for (i = 0; i < r->root_kq; i++) {
                   if (FD_ISSET(i, &rfd) || FD_ISSET(i, &xfd)) {
                           flg = 0;
                           TAILQ_FOREACH_SAFE(t, &r->root_read, task_node, tmp) {
                                   if (TASK_FD(t) == i) {
                                           if (!flg)
                                                   task = t;
                                           flg++;
                                   }
                           }
   
                           if (flg && task) {
                                   TASK_FLAG(task) = ioctl(TASK_FD(task), FIONREAD, &TASK_RET(task));
   
                                   /* remove read handle */
                                   remove_task_from(task, &r->root_read);
   
                                   if (r->root_hooks.hook_exec.exception) {
                                           if (r->root_hooks.hook_exec.exception(r, NULL)) {
                                                   task->task_type = taskUNUSE;
                                                   insert_task_to(task, &r->root_unuse);
                                           } else {
                                                   task->task_type = taskREADY;
                                                   insert_task_to(task, &r->root_ready);
                                           }
                                   } else {
                                           task->task_type = taskREADY;
                                           insert_task_to(task, &r->root_ready);
                                   }
   
                                   /* remove resouce */
                                   if (flg == 1)
                                           FD_CLR(i, &r->root_fds[0]);
                           }
                   } else if (FD_ISSET(i, &wfd)) {
                           flg = 0;
                           TAILQ_FOREACH_SAFE(t, &r->root_write, task_node, tmp) {
                                   if (TASK_FD(t) == i) {
                                           if (!flg)
                                                   task = t;
                                           flg++;
                                   }
                           }
   
                           if (flg && task) {
                                   TASK_FLAG(task) = ioctl(TASK_FD(task), FIONWRITE, &TASK_RET(task));
   
                                   /* remove write handle */
                                   remove_task_from(task, &r->root_write);
   
                                   if (r->root_hooks.hook_exec.exception) {
                                           if (r->root_hooks.hook_exec.exception(r, NULL)) {
                                                   task->task_type = taskUNUSE;
                                                   insert_task_to(task, &r->root_unuse);
                                           } else {
                                                   task->task_type = taskREADY;
                                                   insert_task_to(task, &r->root_ready);
                                           }
                                   } else {
                                           task->task_type = taskREADY;
                                           insert_task_to(task, &r->root_ready);
                                   }
   
                                   /* remove resouce */
                                   if (flg == 1)
                                           FD_CLR(i, &r->root_fds[1]);
                           }
                   }
           }
   
           /* optimize select */
           for (i = r->root_kq - 1; i > 2; i--)
                   if (FD_ISSET(i, &r->root_fds[0]) || FD_ISSET(i, &r->root_fds[1]))
                           break;
           if (i > 2)
                   r->root_kq = i + 1;
   }
   #endif
   
 /*  /*
  * sched_hook_fetch() - Default FETCH hook   * sched_hook_fetch() - Default FETCH hook
  *   *
Line 440  sched_hook_fetch(void *root, void *arg __unused) Line 1275  sched_hook_fetch(void *root, void *arg __unused)
         sched_root_task_t *r = root;          sched_root_task_t *r = root;
         sched_task_t *task, *tmp;          sched_task_t *task, *tmp;
         struct timespec now, m, mtmp;          struct timespec now, m, mtmp;
   #if SUP_ENABLE == KQ_SUPPORT
           struct kevent res[KQ_EVENTS];
         struct timespec *timeout;          struct timespec *timeout;
        struct kevent evt[1], res[KQ_EVENTS];#elif SUP_ENABLE == EP_SUPPORT
        register int i, flg;        struct epoll_event res[KQ_EVENTS];
         u_long timeout = 0;
 #else
         struct timeval *timeout, tv;
         fd_set rfd, wfd, xfd;
 #endif
         int en;          int en;
   
         if (!r)          if (!r)
Line 450  sched_hook_fetch(void *root, void *arg __unused) Line 1292  sched_hook_fetch(void *root, void *arg __unused)
   
         /* get new task by queue priority */          /* get new task by queue priority */
         while ((task = TAILQ_FIRST(&r->root_event))) {          while ((task = TAILQ_FIRST(&r->root_event))) {
#ifdef HAVE_LIBPTHREAD                transit_task2unuse(task, &r->root_event);
                pthread_mutex_lock(&r->root_mtx[taskEVENT]); 
#endif 
                TAILQ_REMOVE(&r->root_event, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                pthread_mutex_unlock(&r->root_mtx[taskEVENT]); 
#endif 
                task->task_type = taskUNUSE; 
#ifdef HAVE_LIBPTHREAD 
                pthread_mutex_lock(&r->root_mtx[taskUNUSE]); 
#endif 
                TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                pthread_mutex_unlock(&r->root_mtx[taskUNUSE]); 
#endif 
                 return task;                  return task;
         }          }
         while ((task = TAILQ_FIRST(&r->root_ready))) {          while ((task = TAILQ_FIRST(&r->root_ready))) {
#ifdef HAVE_LIBPTHREAD                transit_task2unuse(task, &r->root_ready);
                pthread_mutex_lock(&r->root_mtx[taskREADY]); 
#endif 
                TAILQ_REMOVE(&r->root_ready, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                pthread_mutex_unlock(&r->root_mtx[taskREADY]); 
#endif 
                task->task_type = taskUNUSE; 
#ifdef HAVE_LIBPTHREAD 
                pthread_mutex_lock(&r->root_mtx[taskUNUSE]); 
#endif 
                TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                pthread_mutex_unlock(&r->root_mtx[taskUNUSE]); 
#endif 
                 return task;                  return task;
         }          }
   
Line 505  sched_hook_fetch(void *root, void *arg __unused) Line 1319  sched_hook_fetch(void *root, void *arg __unused)
                 /* set wait INFTIM */                  /* set wait INFTIM */
                 sched_timespecinf(&r->root_wait);                  sched_timespecinf(&r->root_wait);
         }          }
#else#else   /* ! TIMER_WITHOUT_SORT */
        if (!TAILQ_FIRST(&r->root_eventlo) && (task = TAILQ_FIRST(&r->root_timer))) {        if (!TAILQ_FIRST(&r->root_task) && (task = TAILQ_FIRST(&r->root_timer))) {
                 clock_gettime(CLOCK_MONOTONIC, &now);                  clock_gettime(CLOCK_MONOTONIC, &now);
   
                 m = TASK_TS(task);                  m = TASK_TS(task);
Line 516  sched_hook_fetch(void *root, void *arg __unused) Line 1330  sched_hook_fetch(void *root, void *arg __unused)
                 /* set wait INFTIM */                  /* set wait INFTIM */
                 sched_timespecinf(&r->root_wait);                  sched_timespecinf(&r->root_wait);
         }          }
#endif#endif  /* TIMER_WITHOUT_SORT */
        /* if present member of eventLo, set NOWAIT */        /* if present member of task, set NOWAIT */
        if (TAILQ_FIRST(&r->root_eventlo))        if (TAILQ_FIRST(&r->root_task))
                 sched_timespecclear(&r->root_wait);                  sched_timespecclear(&r->root_wait);
   
        if (r->root_wait.tv_sec != -1 && r->root_wait.tv_nsec != -1)        if (r->root_wait.tv_sec != -1 && r->root_wait.tv_nsec != -1) {
 #if SUP_ENABLE == KQ_SUPPORT
                 timeout = &r->root_wait;                  timeout = &r->root_wait;
        else if (sched_timespecisinf(&r->root_poll))#elif SUP_ENABLE == EP_SUPPORT
                 timeout = r->root_wait.tv_sec * 1000 + r->root_wait.tv_nsec / 1000000;
 #else
                 sched_timespec2val(&r->root_wait, &tv);
                 timeout = &tv;
 #endif  /* KQ_SUPPORT */
         } else if (sched_timespecisinf(&r->root_poll))
 #if SUP_ENABLE == EP_SUPPORT
                 timeout = -1;
 #else
                 timeout = NULL;                  timeout = NULL;
        else#endif
         else {
 #if SUP_ENABLE == KQ_SUPPORT
                 timeout = &r->root_poll;                  timeout = &r->root_poll;
   #elif SUP_ENABLE == EP_SUPPORT
                   timeout = r->root_poll.tv_sec * 1000 + r->root_poll.tv_nsec / 1000000;
   #else
                   sched_timespec2val(&r->root_poll, &tv);
                   timeout = &tv;
   #endif  /* KQ_SUPPORT */
           }
   
   #if SUP_ENABLE == KQ_SUPPORT
         if ((en = kevent(r->root_kq, NULL, 0, res, KQ_EVENTS, timeout)) == -1) {          if ((en = kevent(r->root_kq, NULL, 0, res, KQ_EVENTS, timeout)) == -1) {
   #elif SUP_ENABLE == EP_SUPPORT
           if ((en = epoll_wait(r->root_kq, res, KQ_EVENTS, timeout)) == -1) {
   #else
           rfd = xfd = r->root_fds[0];
           wfd = r->root_fds[1];
           if ((en = select(r->root_kq, &rfd, &wfd, &xfd, timeout)) == -1) {
   #endif  /* KQ_SUPPORT */
                 if (r->root_hooks.hook_exec.exception) {                  if (r->root_hooks.hook_exec.exception) {
                         if (r->root_hooks.hook_exec.exception(r, NULL))                          if (r->root_hooks.hook_exec.exception(r, NULL))
                                 return NULL;                                  return NULL;
                 } else if (errno != EINTR)                  } else if (errno != EINTR)
                         LOGERR;                          LOGERR;
                return NULL;                goto skip_event;
         }          }
   
         now.tv_sec = now.tv_nsec = 0;  
         /* Go and catch the cat into pipes ... */          /* Go and catch the cat into pipes ... */
        for (i = 0; i < en; i++) {#if SUP_ENABLE == KQ_SUPPORT
                memcpy(evt, &res[i], sizeof evt);        /* kevent dispatcher */
                evt->flags = EV_DELETE;        fetch_hook_kevent_proceed(en, res, r);
                /* Put read/write task to ready queue */#elif SUP_ENABLE == EP_SUPPORT
                switch (res[i].filter) {        /* epoll dispatcher */
                        case EVFILT_READ:        fetch_hook_epoll_proceed(en, res, r);
                                flg = 0;#else
                                TAILQ_FOREACH_SAFE(task, &r->root_read, task_node, tmp) {        /* select dispatcher */
                                        if (TASK_FD(task) != ((intptr_t) res[i].udata))        fetch_hook_select_proceed(en, rfd, wfd, xfd, r);
                                                continue;#endif  /* KQ_SUPPORT */
                                        else 
                                                flg++; 
                                        /* remove read handle */ 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_lock(&r->root_mtx[taskREAD]); 
#endif 
                                        TAILQ_REMOVE(&r->root_read, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_unlock(&r->root_mtx[taskREAD]); 
#endif 
                                        if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) { 
                                                if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) { 
                                                        task->task_type = taskUNUSE; 
#ifdef HAVE_LIBPTHREAD 
                                                        pthread_mutex_lock(&r->root_mtx[taskUNUSE]); 
#endif 
                                                        TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                                                        pthread_mutex_unlock(&r->root_mtx[taskUNUSE]); 
#endif 
                                                } else { 
                                                        task->task_type = taskREADY; 
#ifdef HAVE_LIBPTHREAD 
                                                        pthread_mutex_lock(&r->root_mtx[taskREADY]); 
#endif 
                                                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                                                        pthread_mutex_unlock(&r->root_mtx[taskREADY]); 
#endif 
                                                } 
                                        } else { 
                                                task->task_type = taskREADY; 
#ifdef HAVE_LIBPTHREAD 
                                                pthread_mutex_lock(&r->root_mtx[taskREADY]); 
#endif 
                                                TAILQ_INSERT_TAIL(&r->root_ready, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                                                pthread_mutex_unlock(&r->root_mtx[taskREADY]); 
#endif 
                                        } 
                                } 
                                /* if match at least 2, don't remove resouce of event */ 
                                if (flg > 1) 
                                        evt->flags ^= evt->flags; 
                                break; 
                        case EVFILT_WRITE: 
                                flg = 0; 
                                TAILQ_FOREACH_SAFE(task, &r->root_write, task_node, tmp) { 
                                        if (TASK_FD(task) != ((intptr_t) res[i].udata)) 
                                                continue; 
                                        else 
                                                flg++; 
                                        /* remove write handle */ 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_lock(&r->root_mtx[taskWRITE]); 
#endif 
                                        TAILQ_REMOVE(&r->root_write, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_unlock(&r->root_mtx[taskWRITE]); 
#endif 
                                        if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) { 
                                                if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) { 
                                                        task->task_type = taskUNUSE; 
#ifdef HAVE_LIBPTHREAD 
                                                        pthread_mutex_lock(&r->root_mtx[taskUNUSE]); 
#endif 
                                                        TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                                                        pthread_mutex_unlock(&r->root_mtx[taskUNUSE]); 
#endif 
                                                } else { 
                                                        task->task_type = taskREADY; 
#ifdef HAVE_LIBPTHREAD 
                                                        pthread_mutex_lock(&r->root_mtx[taskREADY]); 
#endif 
                                                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                                                        pthread_mutex_unlock(&r->root_mtx[taskREADY]); 
#endif 
                                                } 
                                        } else { 
                                                task->task_type = taskREADY; 
#ifdef HAVE_LIBPTHREAD 
                                                pthread_mutex_lock(&r->root_mtx[taskREADY]); 
#endif 
                                                TAILQ_INSERT_TAIL(&r->root_ready, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                                                pthread_mutex_unlock(&r->root_mtx[taskREADY]); 
#endif 
                                        } 
                                } 
                                /* if match at least 2, don't remove resouce of event */ 
                                if (flg > 1) 
                                        evt->flags ^= evt->flags; 
                                break; 
                        case EVFILT_TIMER: 
                                flg = 0; 
                                TAILQ_FOREACH_SAFE(task, &r->root_alarm, task_node, tmp) { 
                                        if ((uintptr_t) TASK_DATA(task) != ((uintptr_t) res[i].udata)) 
                                                continue; 
                                        else 
                                                flg++; 
                                        /* remove alarm handle */ 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_lock(&r->root_mtx[taskALARM]); 
#endif 
                                        TAILQ_REMOVE(&r->root_alarm, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_unlock(&r->root_mtx[taskALARM]); 
#endif 
                                        task->task_type = taskREADY; 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_lock(&r->root_mtx[taskREADY]); 
#endif 
                                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_unlock(&r->root_mtx[taskREADY]); 
#endif 
                                } 
                                /* if match at least 2, don't remove resouce of event */ 
                                if (flg > 1) 
                                        evt->flags ^= evt->flags; 
                                break; 
                        case EVFILT_VNODE: 
                                flg = 0; 
                                TAILQ_FOREACH_SAFE(task, &r->root_node, task_node, tmp) { 
                                        if (TASK_FD(task) != ((intptr_t) res[i].udata)) 
                                                continue; 
                                        else { 
                                                flg++; 
                                                TASK_DATA(task) = (void*) (uintptr_t) res[i].data; 
                                                TASK_DATLEN(task) = res[i].fflags; 
                                        } 
                                        /* remove node handle */ 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_lock(&r->root_mtx[taskNODE]); 
#endif 
                                        TAILQ_REMOVE(&r->root_node, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_unlock(&r->root_mtx[taskNODE]); 
#endif 
                                        task->task_type = taskREADY; 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_lock(&r->root_mtx[taskREADY]); 
#endif 
                                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_unlock(&r->root_mtx[taskREADY]); 
#endif 
                                } 
                                /* if match at least 2, don't remove resouce of event */ 
                                if (flg > 1) 
                                        evt->flags ^= evt->flags; 
                                break; 
                        case EVFILT_PROC: 
                                flg = 0; 
                                TAILQ_FOREACH_SAFE(task, &r->root_proc, task_node, tmp) { 
                                        if (TASK_VAL(task) != ((uintptr_t) res[i].udata)) 
                                                continue; 
                                        else { 
                                                flg++; 
                                                TASK_DATA(task) = (void*) (uintptr_t) res[i].data; 
                                                TASK_DATLEN(task) = res[i].fflags; 
                                        } 
                                        /* remove proc handle */ 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_lock(&r->root_mtx[taskPROC]); 
#endif 
                                        TAILQ_REMOVE(&r->root_proc, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_unlock(&r->root_mtx[taskPROC]); 
#endif 
                                        task->task_type = taskREADY; 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_lock(&r->root_mtx[taskREADY]); 
#endif 
                                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_unlock(&r->root_mtx[taskREADY]); 
#endif 
                                } 
                                /* if match at least 2, don't remove resouce of event */ 
                                if (flg > 1) 
                                        evt->flags ^= evt->flags; 
                                break; 
                        case EVFILT_SIGNAL: 
                                flg = 0; 
                                TAILQ_FOREACH_SAFE(task, &r->root_signal, task_node, tmp) { 
                                        if (TASK_VAL(task) != ((uintptr_t) res[i].udata)) 
                                                continue; 
                                        else 
                                                flg++; 
                                        /* remove signal handle */ 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_lock(&r->root_mtx[taskSIGNAL]); 
#endif 
                                        TAILQ_REMOVE(&r->root_signal, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_unlock(&r->root_mtx[taskSIGNAL]); 
#endif 
                                        task->task_type = taskREADY; 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_lock(&r->root_mtx[taskREADY]); 
#endif 
                                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_unlock(&r->root_mtx[taskREADY]); 
#endif 
                                } 
                                /* if match at least 2, don't remove resouce of event */ 
                                if (flg > 1) 
                                        evt->flags ^= evt->flags; 
                                break; 
#ifdef EVFILT_USER 
                        case EVFILT_USER: 
                                flg = 0; 
                                TAILQ_FOREACH_SAFE(task, &r->root_user, task_node, tmp) { 
                                        if (TASK_VAL(task) != ((uintptr_t) res[i].udata)) 
                                                continue; 
                                        else { 
                                                flg++; 
                                                TASK_DATA(task) = (void*) res[i].data; 
                                                TASK_DATLEN(task) = res[i].fflags; 
                                        } 
                                        /* remove user handle */ 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_lock(&r->root_mtx[taskUSER]); 
#endif 
                                        TAILQ_REMOVE(&r->root_user, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_unlock(&r->root_mtx[taskUSER]); 
#endif 
                                        task->task_type = taskREADY; 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_lock(&r->root_mtx[taskREADY]); 
#endif 
                                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                                        pthread_mutex_unlock(&r->root_mtx[taskREADY]); 
#endif 
                                } 
                                /* if match at least 2, don't remove resouce of event */ 
                                if (flg > 1) 
                                        evt->flags ^= evt->flags; 
                                break; 
#endif 
                } 
                if (kevent(r->root_kq, evt, 1, NULL, 0, &now) == -1) { 
                        if (r->root_hooks.hook_exec.exception) { 
                                if (r->root_hooks.hook_exec.exception(r, NULL)) 
                                        return NULL; 
                        } else 
                                LOGERR; 
                } 
        } 
   
   skip_event:
         /* timer update & put in ready queue */          /* timer update & put in ready queue */
         clock_gettime(CLOCK_MONOTONIC, &now);          clock_gettime(CLOCK_MONOTONIC, &now);
   
         TAILQ_FOREACH_SAFE(task, &r->root_timer, task_node, tmp)          TAILQ_FOREACH_SAFE(task, &r->root_timer, task_node, tmp)
                if (sched_timespeccmp(&now, &TASK_TS(task), -) >= 0) {                if (sched_timespeccmp(&now, &TASK_TS(task), -) >= 0)
#ifdef HAVE_LIBPTHREAD                        transit_task2ready(task, &r->root_timer);
                        pthread_mutex_lock(&r->root_mtx[taskTIMER]); 
#endif 
                        TAILQ_REMOVE(&r->root_timer, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                        pthread_mutex_unlock(&r->root_mtx[taskTIMER]); 
#endif 
                        task->task_type = taskREADY; 
#ifdef HAVE_LIBPTHREAD 
                        pthread_mutex_lock(&r->root_mtx[taskREADY]); 
#endif 
                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                        pthread_mutex_unlock(&r->root_mtx[taskREADY]); 
#endif 
                } 
   
        /* put eventlo priority task to ready queue, if there is no ready task or         /* put regular task priority task to ready queue, 
                reach max missed fetch-rotate */                if there is no ready task or reach max missing hit for regular task */
        if ((task = TAILQ_FIRST(&r->root_eventlo))) {        if ((task = TAILQ_FIRST(&r->root_task))) {
                if (!TAILQ_FIRST(&r->root_ready) || r->root_eventlo_miss > MAX_EVENTLO_MISS) {                if (!TAILQ_FIRST(&r->root_ready) || r->root_miss >= TASK_VAL(task)) {
                        r->root_eventlo_miss = 0;                        r->root_miss ^= r->root_miss;
   
#ifdef HAVE_LIBPTHREAD                        transit_task2ready(task, &r->root_task);
                        pthread_mutex_lock(&r->root_mtx[taskEVENTLO]); 
#endif 
                        TAILQ_REMOVE(&r->root_eventlo, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                        pthread_mutex_unlock(&r->root_mtx[taskEVENTLO]); 
#endif 
                        task->task_type = taskREADY; 
#ifdef HAVE_LIBPTHREAD 
                        pthread_mutex_lock(&r->root_mtx[taskREADY]); 
#endif 
                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
                        pthread_mutex_unlock(&r->root_mtx[taskREADY]); 
#endif 
                 } else                  } else
                        r->root_eventlo_miss++;                        r->root_miss++;
         } else          } else
                r->root_eventlo_miss = 0;                r->root_miss ^= r->root_miss;
   
         /* OK, lets get ready task !!! */          /* OK, lets get ready task !!! */
         task = TAILQ_FIRST(&r->root_ready);          task = TAILQ_FIRST(&r->root_ready);
        if (!(task))        if (task)
                return NULL;                transit_task2unuse(task, &r->root_ready);
 
#ifdef HAVE_LIBPTHREAD 
        pthread_mutex_lock(&r->root_mtx[taskREADY]); 
#endif 
        TAILQ_REMOVE(&r->root_ready, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
        pthread_mutex_unlock(&r->root_mtx[taskREADY]); 
#endif 
        task->task_type = taskUNUSE; 
#ifdef HAVE_LIBPTHREAD 
        pthread_mutex_lock(&r->root_mtx[taskUNUSE]); 
#endif 
        TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node); 
#ifdef HAVE_LIBPTHREAD 
        pthread_mutex_unlock(&r->root_mtx[taskUNUSE]); 
#endif 
         return task;          return task;
 }  }
   
Line 921  sched_hook_condition(void *root, void *arg) Line 1463  sched_hook_condition(void *root, void *arg)
         if (!r)          if (!r)
                 return NULL;                  return NULL;
   
        return (void*) (r->root_cond - *(intptr_t*) arg);        return (void*) (*r->root_cond - *(intptr_t*) arg);
 }
 
 /*
  * sched_hook_rtc() - Default RTC hook
  *
  * @task = current task
  * @arg = unused
  * return: <0 errors and 0 ok
  */
 void *
 sched_hook_rtc(void *task, void *arg __unused)
 {
 #if defined(HAVE_LIBRT) && defined(HAVE_TIMER_CREATE) && \
         defined(HAVE_TIMER_SETTIME) && defined(HAVE_TIMER_DELETE)
         sched_task_t *sigt = NULL, *t = task;
         struct itimerspec its;
         struct sigevent evt;
         timer_t tmr;
 #if SUP_ENABLE != KQ_SUPPORT
         struct sigaction sa;
 #endif
 
         if (!t || !TASK_ROOT(t))
                 return (void*) -1;
 
         memset(&evt, 0, sizeof evt);
         evt.sigev_notify = SIGEV_SIGNAL;
         evt.sigev_signo = (intptr_t) TASK_DATA(t) + SIGRTMIN;
         evt.sigev_value.sival_ptr = t;
 
         if (timer_create(CLOCK_MONOTONIC, &evt, &tmr) == -1) {
                 if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                         TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
                 else
                         LOGERR;
                 return (void*) -1;
         } else
                 TASK_FLAG(t) = (u_long) tmr;
 
 #if SUP_ENABLE == KQ_SUPPORT
         if (!(sigt = schedSignal(TASK_ROOT(t), _sched_rtcWrapper, TASK_ARG(t), evt.sigev_signo, 
                                 t, (size_t) tmr))) {
                 if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                         TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
                 else
                         LOGERR;
                 timer_delete(tmr);
                 return (void*) -1;
         } else
                 TASK_RET(t) = (uintptr_t) sigt;
 #else
         memset(&sa, 0, sizeof sa);
         sigemptyset(&sa.sa_mask);
         sa.sa_sigaction = _sched_rtcSigWrapper;
         sa.sa_flags = SA_SIGINFO | SA_RESTART;
 
         if (sigaction(evt.sigev_signo, &sa, NULL) == -1) {
                 if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                         TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
                 else
                         LOGERR;
                 timer_delete(tmr);
                 return (void*) -1;
         }
 #endif
 
         memset(&its, 0, sizeof its);
         its.it_value.tv_sec = t->task_val.ts.tv_sec;
         its.it_value.tv_nsec = t->task_val.ts.tv_nsec;
 
         if (timer_settime(tmr, TIMER_RELTIME, &its, NULL) == -1) {
                 if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                         TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
                 else
                         LOGERR;
                 schedCancel(sigt);
                 timer_delete(tmr);
                 return (void*) -1;
         }
 #endif  /* HAVE_TIMER_CREATE */
         return NULL;
 }  }

Removed from v.1.10.2.1  
changed lines
  Added in v.1.32


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>