Diff for /libaitsched/src/hooks.c between versions 1.2 and 1.24

version 1.2, 2011/10/04 12:34:33 version 1.24, 2013/11/14 21:37:27
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, 2011Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
         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 49  SUCH DAMAGE. Line 49  SUCH DAMAGE.
   
 /*  /*
  * sched_hook_init() - Default INIT hook   * sched_hook_init() - Default INIT hook
    *
  * @root = root task   * @root = root task
 * @data = optional data if !=NULL * @arg = unused
  * return: <0 errors and 0 ok   * return: <0 errors and 0 ok
  */   */
 void *  void *
sched_hook_init(void *root, void *data)sched_hook_init(void *root, void *arg __unused)
 {  {
         sched_root_task_t *r = root;          sched_root_task_t *r = root;
   
        if (!r || r->root_data.iov_base || r->root_data.iov_len)        if (!r)
                 return (void*) -1;                  return (void*) -1;
   
         r->root_data.iov_base = malloc(sizeof(struct sched_IO));  
         if (!r->root_data.iov_base) {  
                 LOGERR;  
                 return (void*) -1;  
         } else {  
                 r->root_data.iov_len = sizeof(struct sched_IO);  
                 memset(r->root_data.iov_base, 0, r->root_data.iov_len);  
         }  
   
         r->root_kq = kqueue();          r->root_kq = kqueue();
         if (r->root_kq == -1) {          if (r->root_kq == -1) {
                 LOGERR;                  LOGERR;
Line 81  sched_hook_init(void *root, void *data) Line 73  sched_hook_init(void *root, void *data)
   
 /*  /*
  * sched_hook_fini() - Default FINI hook   * sched_hook_fini() - Default FINI hook
    *
  * @root = root task   * @root = root task
  * @arg = unused   * @arg = unused
  * return: <0 errors and 0 ok   * return: <0 errors and 0 ok
Line 98  sched_hook_fini(void *root, void *arg __unused) Line 91  sched_hook_fini(void *root, void *arg __unused)
                 r->root_kq = 0;                  r->root_kq = 0;
         }          }
   
         if (r->root_data.iov_base && r->root_data.iov_len) {  
                 free(r->root_data.iov_base);  
                 r->root_data.iov_base = NULL;  
                 r->root_data.iov_len = 0;  
         }  
   
         return NULL;          return NULL;
 }  }
   
 /*  /*
  * sched_hook_cancel() - Default CANCEL hook   * sched_hook_cancel() - Default CANCEL hook
    *
  * @task = current task   * @task = current task
  * @arg = unused   * @arg = unused
  * return: <0 errors and 0 ok   * return: <0 errors and 0 ok
Line 116  sched_hook_fini(void *root, void *arg __unused) Line 104  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)
 {  {
         struct sched_IO *io;  
         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 };
   #ifdef AIO_SUPPORT
           struct aiocb *acb;
   #ifdef EVFILT_LIO
           register int i = 0;
           struct aiocb **acbs;
   #endif  /* EVFILT_LIO */
   #endif  /* AIO_SUPPORT */
   
        if (!t || !t->task_root || !ROOT_DATA(t->task_root) || !ROOT_DATLEN(t->task_root))        if (!t || !TASK_ROOT(t))
                 return (void*) -1;                  return (void*) -1;
         else  
                 io = ROOT_DATA(t->task_root);  
   
        switch (t->task_type) {        switch (TASK_TYPE(t)) {
                 case taskREAD:                  case taskREAD:
 #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, EV_DELETE, 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, EV_DELETE, 0, 0, (void*) TASK_FD(t));
 #endif  #endif
                         kevent(t->task_root->root_kq, chg, 1, NULL, 0, &timeout);  
                         FD_CLR(TASK_FD(t), &io->rfd);  
                         break;                          break;
                 case taskWRITE:                  case taskWRITE:
 #ifdef __NetBSD__  #ifdef __NetBSD__
Line 142  sched_hook_cancel(void *task, void *arg __unused) Line 132  sched_hook_cancel(void *task, void *arg __unused)
 #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, EV_DELETE, 0, 0, (void*) TASK_FD(t));
 #endif  #endif
                         kevent(t->task_root->root_kq, chg, 1, NULL, 0, &timeout);  
                         FD_CLR(TASK_FD(t), &io->wfd);  
                         break;                          break;
                default:                case taskALARM:
 #ifdef __NetBSD__
                         EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_DELETE, 
                                         0, 0, (intptr_t) TASK_DATA(t));
 #else
                         EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_DELETE, 
                                         0, 0, (void*) TASK_DATA(t));
 #endif
                         break;                          break;
                   case taskNODE:
   #ifdef __NetBSD__
                           EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_DELETE, 0, 0, (intptr_t) TASK_FD(t));
   #else
                           EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_DELETE, 0, 0, (void*) TASK_FD(t));
   #endif
                           break;
                   case taskPROC:
   #ifdef __NetBSD__
                           EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));
   #else
                           EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_DELETE, 0, 0, (void*) TASK_VAL(t));
   #endif
                           break;
                   case taskSIGNAL:
   #ifdef __NetBSD__
                           EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));
   #else
                           EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_DELETE, 0, 0, (void*) TASK_VAL(t));
   #endif
                           /* restore signal */
                           signal(TASK_VAL(t), SIG_DFL);
                           break;
   #ifdef AIO_SUPPORT
                   case taskAIO:
   #ifdef __NetBSD__
                           EV_SET(&chg[0], TASK_VAL(t), EVFILT_AIO, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));
   #else
                           EV_SET(&chg[0], TASK_VAL(t), EVFILT_AIO, EV_DELETE, 0, 0, (void*) TASK_VAL(t));
   #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;
                           }
                           break;
   #ifdef EVFILT_LIO
                   case taskLIO:
   #ifdef __NetBSD__
                           EV_SET(&chg[0], TASK_VAL(t), EVFILT_LIO, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));
   #else
                           EV_SET(&chg[0], TASK_VAL(t), EVFILT_LIO, EV_DELETE, 0, 0, (void*) TASK_VAL(t));
   #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;
                           }
                           break;
   #endif  /* EVFILT_LIO */
   #endif  /* AIO_SUPPORT */
   #ifdef EVFILT_USER
                   case taskUSER:
   #ifdef __NetBSD__
                           EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));
   #else
                           EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_DELETE, 0, 0, (void*) TASK_VAL(t));
   #endif
                           break;
   #endif  /* EVFILT_USER */
                   case taskTHREAD:
   #ifdef HAVE_LIBPTHREAD
                           pthread_cancel((pthread_t) TASK_VAL(t));
   #endif
                           return NULL;
   #if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME)
                   case taskRTC:
                           timer_delete((timer_t) TASK_FLAG(t));
                           schedCancel((sched_task_t*) TASK_RET(t));
                           return NULL;
   #endif  /* HAVE_TIMER_CREATE */
                   default:
                           return NULL;
         }          }
   
           kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout);
         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);
           if ((errno = pthread_create(&tid, (pthread_attr_t*) arg, 
                                   (void *(*)(void*)) _sched_threadWrapper, t))) {
                   LOGERR;
                   pthread_sigmask(SIG_SETMASK, &o, NULL);
                   return (void*) -1;
           } else
                   TASK_VAL(t) = (u_long) tid;
   
           if (!TASK_ISLOCKED(t))
                   TASK_LOCK(t);
   
           pthread_sigmask(SIG_SETMASK, &o, NULL);
           return NULL;
   }
   #endif
   
   /*
  * sched_hook_read() - Default READ hook   * sched_hook_read() - Default READ hook
    *
  * @task = current task   * @task = current task
  * @arg = unused   * @arg = unused
  * return: <0 errors and 0 ok   * return: <0 errors and 0 ok
Line 161  sched_hook_cancel(void *task, void *arg __unused) Line 274  sched_hook_cancel(void *task, void *arg __unused)
 void *  void *
 sched_hook_read(void *task, void *arg __unused)  sched_hook_read(void *task, void *arg __unused)
 {  {
         struct sched_IO *io;  
         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 };
   
        if (!t || !t->task_root || !ROOT_DATA(t->task_root) || !ROOT_DATLEN(t->task_root))        if (!t || !TASK_ROOT(t))
                 return (void*) -1;                  return (void*) -1;
         else  
                 io = ROOT_DATA(t->task_root);  
   
         if (FD_ISSET(TASK_FD(t), &io->rfd))  
                 return NULL;  
         else  
                 FD_SET(TASK_FD(t), &io->rfd);  
   
 #ifdef __NetBSD__  #ifdef __NetBSD__
        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD, 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, 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(t->task_root->root_kq, chg, 1, NULL, 0, &timeout) == -1) {        if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                LOGERR;                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;                  return (void*) -1;
         }          }
   
Line 191  sched_hook_read(void *task, void *arg __unused) Line 299  sched_hook_read(void *task, void *arg __unused)
   
 /*  /*
  * sched_hook_write() - Default WRITE hook   * sched_hook_write() - Default WRITE hook
    *
  * @task = current task   * @task = current task
  * @arg = unused   * @arg = unused
  * return: <0 errors and 0 ok   * return: <0 errors and 0 ok
Line 198  sched_hook_read(void *task, void *arg __unused) Line 307  sched_hook_read(void *task, void *arg __unused)
 void *  void *
 sched_hook_write(void *task, void *arg __unused)  sched_hook_write(void *task, void *arg __unused)
 {  {
         struct sched_IO *io;  
         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 };
   
        if (!t || !t->task_root || !ROOT_DATA(t->task_root) || !ROOT_DATLEN(t->task_root))        if (!t || !TASK_ROOT(t))
                 return (void*) -1;                  return (void*) -1;
         else  
                 io = ROOT_DATA(t->task_root);  
   
        if (FD_ISSET(TASK_FD(t), &io->wfd))#ifdef __NetBSD__
                return NULL;        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, (intptr_t) TASK_FD(t));
        else#else
                FD_SET(TASK_FD(t), &io->wfd);        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, (void*) TASK_FD(t));
 #endif
         if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -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;
         }
   
           return NULL;
   }
   
   /*
    * sched_hook_alarm() - Default ALARM hook
    *
    * @task = current task
    * @arg = unused
    * return: <0 errors and 0 ok
    */
   void *
   sched_hook_alarm(void *task, void *arg __unused)
   {
           sched_task_t *t = task;
           struct kevent chg[1];
           struct timespec timeout = { 0, 0 };
   
           if (!t || !TASK_ROOT(t))
                   return (void*) -1;
   
 #ifdef __NetBSD__  #ifdef __NetBSD__
        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD, 0, 0, (intptr_t) TASK_FD(t));        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, 
                         (intptr_t) TASK_DATA(t));
 #else  #else
        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD, 0, 0, (void*) TASK_FD(t));        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, 
                         (void*) TASK_DATA(t));
 #endif  #endif
        if (kevent(t->task_root->root_kq, chg, 1, NULL, 0, &timeout) == -1) {        if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                LOGERR;                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;                  return (void*) -1;
         }          }
   
Line 227  sched_hook_write(void *task, void *arg __unused) Line 368  sched_hook_write(void *task, void *arg __unused)
 }  }
   
 /*  /*
    * sched_hook_node() - Default NODE hook
    *
    * @task = current task
    * @arg = unused
    * return: <0 errors and 0 ok
    */
   void *
   sched_hook_node(void *task, void *arg __unused)
   {
           sched_task_t *t = task;
           struct kevent chg[1];
           struct timespec timeout = { 0, 0 };
   
           if (!t || !TASK_ROOT(t))
                   return (void*) -1;
   
   #ifdef __NetBSD__
           EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_ADD | EV_CLEAR, 
                           NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | 
                           NOTE_LINK | NOTE_RENAME | NOTE_REVOKE, 0, (intptr_t) TASK_FD(t));
   #else
           EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_ADD | EV_CLEAR, 
                           NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | 
                           NOTE_LINK | NOTE_RENAME | NOTE_REVOKE, 0, (void*) TASK_FD(t));
   #endif
           if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -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;
           }
   
           return NULL;
   }
   
   /*
    * sched_hook_proc() - Default PROC hook
    *
    * @task = current task
    * @arg = unused
    * return: <0 errors and 0 ok
    */
   void *
   sched_hook_proc(void *task, void *arg __unused)
   {
           sched_task_t *t = task;
           struct kevent chg[1];
           struct timespec timeout = { 0, 0 };
   
           if (!t || !TASK_ROOT(t))
                   return (void*) -1;
   
   #ifdef __NetBSD__
           EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_ADD | EV_CLEAR, 
                           NOTE_EXIT | NOTE_FORK | NOTE_EXEC | NOTE_TRACK, 0, (intptr_t) TASK_VAL(t));
   #else
           EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_ADD | EV_CLEAR, 
                           NOTE_EXIT | NOTE_FORK | NOTE_EXEC | NOTE_TRACK, 0, (void*) TASK_VAL(t));
   #endif
           if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -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;
           }
   
           return NULL;
   }
   
   /*
    * sched_hook_signal() - Default SIGNAL hook
    *
    * @task = current task
    * @arg = unused
    * return: <0 errors and 0 ok
    */
   void *
   sched_hook_signal(void *task, void *arg __unused)
   {
           sched_task_t *t = task;
           struct kevent chg[1];
           struct timespec timeout = { 0, 0 };
   
           if (!t || !TASK_ROOT(t))
                   return (void*) -1;
   
           /* ignore signal */
           signal(TASK_VAL(t), SIG_IGN);
   
   #ifdef __NetBSD__
           EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_ADD | EV_CLEAR, 0, 0, (intptr_t) TASK_VAL(t));
   #else
           EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_ADD | EV_CLEAR, 0, 0, (void*) TASK_VAL(t));
   #endif
           if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -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;
           }
   
           return NULL;
   }
   
   /*
    * sched_hook_user() - Default USER hook
    *
    * @task = current task
    * @arg = unused
    * return: <0 errors and 0 ok
    */
   #ifdef EVFILT_USER
   void *
   sched_hook_user(void *task, void *arg __unused)
   {
           sched_task_t *t = task;
           struct kevent chg[1];
           struct timespec timeout = { 0, 0 };
   
           if (!t || !TASK_ROOT(t))
                   return (void*) -1;
   
   #ifdef __NetBSD__
           EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_ADD | EV_CLEAR, TASK_DATLEN(t), 
                           0, (intptr_t) TASK_VAL(t));
   #else
           EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_ADD | EV_CLEAR, TASK_DATLEN(t), 
                           0, (void*) TASK_VAL(t));
   #endif
           if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -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;
           }
   
           return NULL;
   }
   #endif
   
   /*
  * sched_hook_fetch() - Default FETCH hook   * sched_hook_fetch() - Default FETCH hook
    *
  * @root = root task   * @root = root task
  * @arg = unused   * @arg = unused
  * return: NULL error or !=NULL fetched task   * return: NULL error or !=NULL fetched task
Line 235  sched_hook_write(void *task, void *arg __unused) Line 522  sched_hook_write(void *task, void *arg __unused)
 void *  void *
 sched_hook_fetch(void *root, void *arg __unused)  sched_hook_fetch(void *root, void *arg __unused)
 {  {
         struct sched_IO *io;  
         sched_root_task_t *r = root;          sched_root_task_t *r = root;
        sched_task_t *task;        sched_task_t *task, *tmp;
        struct timeval now, m, mtmp;        struct timespec now, m, mtmp;
        struct timespec nw, *timeout;        struct timespec *timeout;
         struct kevent evt[1], res[KQ_EVENTS];          struct kevent evt[1], res[KQ_EVENTS];
        register int i;        register int i, flg;
         int en;          int en;
   #ifdef AIO_SUPPORT
           int len, fd;
           struct aiocb *acb;
   #ifdef EVFILT_LIO
           int l;
           register int j;
           off_t off;
           struct aiocb **acbs;
           struct iovec *iv;
   #endif  /* EVFILT_LIO */
   #endif  /* AIO_SUPPORT */
   
        if (!r || !ROOT_DATA(r) || !ROOT_DATLEN(r))        if (!r)
                 return NULL;                  return NULL;
   
         /* get new task by queue priority */          /* get new task by queue priority */
 retry:  
         while ((task = TAILQ_FIRST(&r->root_event))) {          while ((task = TAILQ_FIRST(&r->root_event))) {
   #ifdef HAVE_LIBPTHREAD
                   pthread_mutex_lock(&r->root_mtx[taskEVENT]);
   #endif
                 TAILQ_REMOVE(&r->root_event, task, task_node);                  TAILQ_REMOVE(&r->root_event, task, task_node);
   #ifdef HAVE_LIBPTHREAD
                   pthread_mutex_unlock(&r->root_mtx[taskEVENT]);
   #endif
                 task->task_type = taskUNUSE;                  task->task_type = taskUNUSE;
   #ifdef HAVE_LIBPTHREAD
                   pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
   #endif
                 TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);                  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
                   pthread_mutex_lock(&r->root_mtx[taskREADY]);
   #endif
                 TAILQ_REMOVE(&r->root_ready, task, task_node);                  TAILQ_REMOVE(&r->root_ready, task, task_node);
   #ifdef HAVE_LIBPTHREAD
                   pthread_mutex_unlock(&r->root_mtx[taskREADY]);
   #endif
                 task->task_type = taskUNUSE;                  task->task_type = taskUNUSE;
   #ifdef HAVE_LIBPTHREAD
                   pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
   #endif
                 TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);                  TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
   #ifdef HAVE_LIBPTHREAD
                   pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
   #endif
                 return task;                  return task;
         }          }
   
 #ifdef TIMER_WITHOUT_SORT  #ifdef TIMER_WITHOUT_SORT
        clock_gettime(CLOCK_MONOTONIC, &nw);        clock_gettime(CLOCK_MONOTONIC, &now);
        now.tv_sec = nw.tv_sec; 
        now.tv_usec = nw.tv_nsec / 1000; 
   
        timerclear(&r->root_wait);        sched_timespecclear(&r->root_wait);
         TAILQ_FOREACH(task, &r->root_timer, task_node) {          TAILQ_FOREACH(task, &r->root_timer, task_node) {
                if (!timerisset(&r->root_wait))                if (!sched_timespecisset(&r->root_wait))
                        r->root_wait = TASK_TV(task);                        r->root_wait = TASK_TS(task);
                else if (timercmp(&TASK_TV(task), &r->root_wait, -) < 0)                else if (sched_timespeccmp(&TASK_TS(task), &r->root_wait, -) < 0)
                        r->root_wait = TASK_TV(task);                        r->root_wait = TASK_TS(task);
         }          }
   
         if (TAILQ_FIRST(&r->root_timer)) {          if (TAILQ_FIRST(&r->root_timer)) {
                 m = r->root_wait;                  m = r->root_wait;
                timersub(&m, &now, &mtmp);                sched_timespecsub(&m, &now, &mtmp);
                 r->root_wait = mtmp;                  r->root_wait = mtmp;
         } else {          } else {
                 /* set wait INFTIM */                  /* set wait INFTIM */
                r->root_wait.tv_sec = r->root_wait.tv_usec = -1;                sched_timespecinf(&r->root_wait);
         }          }
 #else  #else
        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, &nw);                clock_gettime(CLOCK_MONOTONIC, &now);
                now.tv_sec = nw.tv_sec; 
                now.tv_usec = nw.tv_nsec / 1000; 
   
                m = TASK_TV(task);                m = TASK_TS(task);
                timersub(&m, &now, &mtmp);                sched_timespecsub(&m, &now, &mtmp);
                 r->root_wait = mtmp;                  r->root_wait = mtmp;
         } else {          } else {
                 /* set wait INFTIM */                  /* set wait INFTIM */
                r->root_wait.tv_sec = r->root_wait.tv_usec = -1;                sched_timespecinf(&r->root_wait);
         }          }
 #endif  #endif
        /* 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))
                timerclear(&r->root_wait);                sched_timespecclear(&r->root_wait);
   
        if (r->root_wait.tv_sec != -1 && r->root_wait.tv_usec != -1) {        if (r->root_wait.tv_sec != -1 && r->root_wait.tv_nsec != -1)
                nw.tv_sec = r->root_wait.tv_sec;                timeout = &r->root_wait;
                nw.tv_nsec = r->root_wait.tv_usec * 1000;        else if (sched_timespecisinf(&r->root_poll))
                timeout = &nw; 
        } else  /* wait INFTIM */ 
                 timeout = NULL;                  timeout = NULL;
           else
                   timeout = &r->root_poll;
         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) {
                LOGERR;                if (r->root_hooks.hook_exec.exception) {
#ifdef NDEBUG                        if (r->root_hooks.hook_exec.exception(r, NULL))
                /* kevent no exit by error, if non-debug version */                                return NULL;
                goto retry;                } else if (errno != EINTR)
#else                        LOGERR;
                /* diagnostic exit from scheduler if kevent error occur */                goto skip_event;
                return NULL; 
#endif 
         }          }
   
        nw.tv_sec = nw.tv_nsec = 0;        /* kevent dispatcher */
         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++) {          for (i = 0; i < en; i++) {
                 memcpy(evt, &res[i], sizeof evt);                  memcpy(evt, &res[i], sizeof evt);
Line 326  retry: Line 641  retry:
                 /* Put read/write task to ready queue */                  /* Put read/write task to ready queue */
                 switch (res[i].filter) {                  switch (res[i].filter) {
                         case EVFILT_READ:                          case EVFILT_READ:
                                TAILQ_FOREACH(task, &r->root_read, task_node) {                                flg = 0;
                                        if (TASK_FD(task) != ((int) res[i].udata))                                TAILQ_FOREACH_SAFE(task, &r->root_read, task_node, tmp) {
                                         if (TASK_FD(task) != ((intptr_t) res[i].udata))
                                                 continue;                                                  continue;
                                           else {
                                                   flg++;
                                                   TASK_RET(task) = res[i].data;
                                                   TASK_FLAG(task) = (u_long) res[i].fflags;
                                           }
                                         /* remove read handle */                                          /* remove read handle */
                                        io = ROOT_DATA(task->task_root);#ifdef HAVE_LIBPTHREAD
                                        FD_CLR(TASK_FD(task), &io->rfd);                                        pthread_mutex_lock(&r->root_mtx[taskREAD]);
#endif
                                         TAILQ_REMOVE(&r->root_read, task, task_node);                                          TAILQ_REMOVE(&r->root_read, task, task_node);
/*                                        if (res[i].flags & EV_EOF) {#ifdef HAVE_LIBPTHREAD
                                                task->task_type = taskUNUSE;                                        pthread_mutex_unlock(&r->root_mtx[taskREAD]);
                                                TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);#endif
                                        } else { */                                        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;                                                  task->task_type = taskREADY;
   #ifdef HAVE_LIBPTHREAD
                                                   pthread_mutex_lock(&r->root_mtx[taskREADY]);
   #endif
                                                 TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);                                                  TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
/*                                      } */#ifdef HAVE_LIBPTHREAD
                                        break;                                                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;                                  break;
                         case EVFILT_WRITE:                          case EVFILT_WRITE:
                                TAILQ_FOREACH(task, &r->root_write, task_node) {                                flg = 0;
                                        if (TASK_FD(task) != ((int) res[i].udata))                                TAILQ_FOREACH_SAFE(task, &r->root_write, task_node, tmp) {
                                         if (TASK_FD(task) != ((intptr_t) res[i].udata))
                                                 continue;                                                  continue;
                                           else {
                                                   flg++;
                                                   TASK_RET(task) = res[i].data;
                                                   TASK_FLAG(task) = (u_long) res[i].fflags;
                                           }
                                         /* remove write handle */                                          /* remove write handle */
                                        io = ROOT_DATA(task->task_root);#ifdef HAVE_LIBPTHREAD
                                        FD_CLR(TASK_FD(task), &io->wfd);                                        pthread_mutex_lock(&r->root_mtx[taskWRITE]);
#endif
                                         TAILQ_REMOVE(&r->root_write, task, task_node);                                          TAILQ_REMOVE(&r->root_write, task, task_node);
/*                                        if (res[i].flags & EV_EOF) {#ifdef HAVE_LIBPTHREAD
                                                task->task_type = taskUNUSE;                                        pthread_mutex_unlock(&r->root_mtx[taskWRITE]);
                                                TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);#endif
                                        } else { */                                        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;                                                  task->task_type = taskREADY;
   #ifdef HAVE_LIBPTHREAD
                                                   pthread_mutex_lock(&r->root_mtx[taskREADY]);
   #endif
                                                 TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);                                                  TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
/*                                      } */#ifdef HAVE_LIBPTHREAD
                                        break;                                                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;                                  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++;
                                                   TASK_RET(task) = res[i].data;
                                                   TASK_FLAG(task) = (u_long) res[i].fflags;
                                           }
                                           /* 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_RET(task) = res[i].data;
                                                   TASK_FLAG(task) = (u_long) 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_RET(task) = res[i].data;
                                                   TASK_FLAG(task) = (u_long) 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++;
                                                   TASK_RET(task) = res[i].data;
                                                   TASK_FLAG(task) = (u_long) res[i].fflags;
                                           }
                                           /* 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 AIO_SUPPORT
                           case EVFILT_AIO:
                                   flg = 0;
                                   TAILQ_FOREACH_SAFE(task, &r->root_aio, task_node, tmp) {
                                           acb = (struct aiocb*) TASK_VAL(task);
                                           if (acb != ((struct aiocb*) res[i].udata))
                                                   continue;
                                           else {
                                                   flg++;
                                                   TASK_RET(task) = res[i].data;
                                                   TASK_FLAG(task) = (u_long) res[i].fflags;
                                           }
                                           /* remove user handle */
   #ifdef HAVE_LIBPTHREAD
                                           pthread_mutex_lock(&r->root_mtx[taskAIO]);
   #endif
                                           TAILQ_REMOVE(&r->root_aio, task, task_node);
   #ifdef HAVE_LIBPTHREAD
                                           pthread_mutex_unlock(&r->root_mtx[taskAIO]);
   #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
                                           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;
                                   }
                                   /* if match at least 2, don't remove resouce of event */
                                   if (flg > 1)
                                           evt->flags ^= evt->flags;
                                   break;
   #ifdef EVFILT_LIO
                           case EVFILT_LIO:
                                   flg = 0;
                                   TAILQ_FOREACH_SAFE(task, &r->root_lio, task_node, tmp) {
                                           acbs = (struct aiocb**) TASK_VAL(task);
                                           if (acbs != ((struct aiocb**) res[i].udata))
                                                   continue;
                                           else {
                                                   flg++;
                                                   TASK_RET(task) = res[i].data;
                                                   TASK_FLAG(task) = (u_long) res[i].fflags;
                                           }
                                           /* remove user handle */
   #ifdef HAVE_LIBPTHREAD
                                           pthread_mutex_lock(&r->root_mtx[taskLIO]);
   #endif
                                           TAILQ_REMOVE(&r->root_lio, task, task_node);
   #ifdef HAVE_LIBPTHREAD
                                           pthread_mutex_unlock(&r->root_mtx[taskLIO]);
   #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
                                           iv = (struct iovec*) TASK_DATA(task);
                                           fd = acbs[0]->aio_fildes;
                                           off = acbs[0]->aio_offset;
                                           for (j = 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;
                                   }
                                   /* if match at least 2, don't remove resouce of event */
                                   if (flg > 1)
                                           evt->flags ^= evt->flags;
                                   break;
   #endif  /* EVFILT_LIO */
   #endif  /* AIO_SUPPORT */
   #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_RET(task) = res[i].data;
                                                   TASK_FLAG(task) = (u_long) 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  /* EVFILT_USER */
                 }                  }
                if (kevent(r->root_kq, evt, 1, NULL, 0, &nw) == -1)                if (kevent(r->root_kq, evt, 1, NULL, 0, &now) == -1) {
                        LOGERR;                        if (r->root_hooks.hook_exec.exception) {
        }                                if (r->root_hooks.hook_exec.exception(r, NULL))
                                         return NULL;
                         } else
                                 LOGERR;
                 }
         }       /* end of kevent dispatcher */
   
   skip_event:
         /* timer update & put in ready queue */          /* timer update & put in ready queue */
        clock_gettime(CLOCK_MONOTONIC, &nw);        clock_gettime(CLOCK_MONOTONIC, &now);
        now.tv_sec = nw.tv_sec; 
        now.tv_usec = nw.tv_nsec / 1000; 
   
        TAILQ_FOREACH(task, &r->root_timer, task_node)        TAILQ_FOREACH_SAFE(task, &r->root_timer, task_node, tmp)
                if (timercmp(&now, &TASK_TV(task), -) >= 0) {                if (sched_timespeccmp(&now, &TASK_TS(task), -) >= 0) {
 #ifdef HAVE_LIBPTHREAD
                         pthread_mutex_lock(&r->root_mtx[taskTIMER]);
 #endif
                         TAILQ_REMOVE(&r->root_timer, task, task_node);                          TAILQ_REMOVE(&r->root_timer, task, task_node);
   #ifdef HAVE_LIBPTHREAD
                           pthread_mutex_unlock(&r->root_mtx[taskTIMER]);
   #endif
                         task->task_type = taskREADY;                          task->task_type = taskREADY;
   #ifdef HAVE_LIBPTHREAD
                           pthread_mutex_lock(&r->root_mtx[taskREADY]);
   #endif
                         TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);                          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;
   
                        TAILQ_REMOVE(&r->root_eventlo, task, task_node);#ifdef HAVE_LIBPTHREAD
                         pthread_mutex_lock(&r->root_mtx[taskTASK]);
 #endif
                         TAILQ_REMOVE(&r->root_task, task, task_node);
 #ifdef HAVE_LIBPTHREAD
                         pthread_mutex_unlock(&r->root_mtx[taskTASK]);
 #endif
                         task->task_type = taskREADY;                          task->task_type = taskREADY;
   #ifdef HAVE_LIBPTHREAD
                           pthread_mutex_lock(&r->root_mtx[taskREADY]);
   #endif
                         TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);                          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 !!! */
        if (!(task = TAILQ_FIRST(&r->root_ready)))        task = TAILQ_FIRST(&r->root_ready);
                goto retry;        if (!(task))
                 return NULL;
 
 #ifdef HAVE_LIBPTHREAD
         pthread_mutex_lock(&r->root_mtx[taskREADY]);
 #endif
         TAILQ_REMOVE(&r->root_ready, task, task_node);          TAILQ_REMOVE(&r->root_ready, task, task_node);
   #ifdef HAVE_LIBPTHREAD
           pthread_mutex_unlock(&r->root_mtx[taskREADY]);
   #endif
         task->task_type = taskUNUSE;          task->task_type = taskUNUSE;
   #ifdef HAVE_LIBPTHREAD
           pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
   #endif
         TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);          TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
   #ifdef HAVE_LIBPTHREAD
           pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
   #endif
         return task;          return task;
 }  }
   
   /*
    * sched_hook_exception() - Default EXCEPTION hook
    *
    * @root = root task
    * @arg = custom handling: if arg == EV_EOF or other value; default: arg == NULL log errno
    * return: <0 errors and 0 ok
    */
   void *
   sched_hook_exception(void *root, void *arg)
   {
           sched_root_task_t *r = root;
   
           if (!r)
                   return NULL;
   
           /* custom exception handling ... */
           if (arg) {
                   if (arg == (void*) EV_EOF)
                           return NULL;
                   return (void*) -1;      /* raise scheduler error!!! */
           }
   
           /* if error hook exists */
           if (r->root_hooks.hook_root.error)
                   return (r->root_hooks.hook_root.error(root, (void*) ((intptr_t) errno)));
   
           /* default case! */
           LOGERR;
           return NULL;
   }
   
   /*
    * sched_hook_condition() - Default CONDITION hook
    *
    * @root = root task
    * @arg = killState from schedRun()
    * return: NULL kill scheduler loop or !=NULL ok
    */
   void *
   sched_hook_condition(void *root, void *arg)
   {
           sched_root_task_t *r = root;
   
           if (!r)
                   return NULL;
   
           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
    */
   #if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME)
   void *
   sched_hook_rtc(void *task, void *arg __unused)
   {
           sched_task_t *sigt = NULL, *t = task;
           struct itimerspec its;
           struct sigevent evt;
           timer_t tmr;
   
           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 = TASK_DATA(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 (!(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;
   
           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;
           }
   
           return NULL;
   }
   #endif  /* HAVE_TIMER_CREATE */

Removed from v.1.2  
changed lines
  Added in v.1.24


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