Diff for /libaitsched/src/hooks.c between versions 1.4 and 1.19

version 1.4, 2012/01/24 21:59:47 version 1.19, 2013/08/15 19:10:48
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 || !TASK_ROOT(t) || !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 (TASK_TYPE(t)) {          switch (TASK_TYPE(t)) {
                 case taskREAD:                  case taskREAD:
Line 133  sched_hook_cancel(void *task, void *arg __unused) Line 125  sched_hook_cancel(void *task, void *arg __unused)
 #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(TASK_ROOT(t)->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(TASK_ROOT(t)->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 || !TASK_ROOT(t) || !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(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 194  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 201  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 || !TASK_ROOT(t) || !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(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 233  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 241  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 timespec now, m, mtmp;          struct timespec now, m, mtmp;
         struct timespec *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  #ifdef HAVE_LIBPTHREAD
                 pthread_mutex_lock(&r->root_mtx[taskEVENT]);                  pthread_mutex_lock(&r->root_mtx[taskEVENT]);
Line 312  retry: Line 602  retry:
                 sched_timespecinf(&r->root_wait);                  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, &now);                  clock_gettime(CLOCK_MONOTONIC, &now);
   
                 m = TASK_TS(task);                  m = TASK_TS(task);
Line 323  retry: Line 613  retry:
                 sched_timespecinf(&r->root_wait);                  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))
                 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)
Line 337  retry: Line 627  retry:
                 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                } else if (errno != EINTR)
                         LOGERR;                          LOGERR;
 #ifdef NDEBUG  
                 /* kevent no exit by error, if non-debug version */  
                 goto retry;  
 #else  
                 /* diagnostic exit from scheduler if kevent error occur */  
                 return NULL;                  return NULL;
 #endif  
         }          }
   
         now.tv_sec = now.tv_nsec = 0;          now.tv_sec = now.tv_nsec = 0;
Line 356  retry: Line 640  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;
                                 TAILQ_FOREACH_SAFE(task, &r->root_read, task_node, tmp) {
                                         if (TASK_FD(task) != ((intptr_t) res[i].udata))                                          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);  
                                         FD_CLR(TASK_FD(task), &io->rfd);  
   
 #ifdef HAVE_LIBPTHREAD  #ifdef HAVE_LIBPTHREAD
                                         pthread_mutex_lock(&r->root_mtx[taskREAD]);                                          pthread_mutex_lock(&r->root_mtx[taskREAD]);
 #endif  #endif
Line 400  retry: Line 687  retry:
                                                 pthread_mutex_unlock(&r->root_mtx[taskREADY]);                                                  pthread_mutex_unlock(&r->root_mtx[taskREADY]);
 #endif  #endif
                                         }                                          }
                                         break;  
                                 }                                  }
                                   /* 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;
                                 TAILQ_FOREACH_SAFE(task, &r->root_write, task_node, tmp) {
                                         if (TASK_FD(task) != ((intptr_t) res[i].udata))                                          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);  
                                         FD_CLR(TASK_FD(task), &io->wfd);  
   
 #ifdef HAVE_LIBPTHREAD  #ifdef HAVE_LIBPTHREAD
                                         pthread_mutex_lock(&r->root_mtx[taskWRITE]);                                          pthread_mutex_lock(&r->root_mtx[taskWRITE]);
 #endif  #endif
Line 448  retry: Line 740  retry:
                                                 pthread_mutex_unlock(&r->root_mtx[taskREADY]);                                                  pthread_mutex_unlock(&r->root_mtx[taskREADY]);
 #endif  #endif
                                         }                                          }
                                         break;  
                                 }                                  }
                                   /* 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, &now) == -1) {                  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) {
Line 464  retry: Line 1008  retry:
         /* timer update & put in ready queue */          /* timer update & put in ready queue */
         clock_gettime(CLOCK_MONOTONIC, &now);          clock_gettime(CLOCK_MONOTONIC, &now);
   
        TAILQ_FOREACH(task, &r->root_timer, task_node)        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  #ifdef HAVE_LIBPTHREAD
                         pthread_mutex_lock(&r->root_mtx[taskTIMER]);                          pthread_mutex_lock(&r->root_mtx[taskTIMER]);
Line 483  retry: Line 1027  retry:
 #endif  #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  #ifdef HAVE_LIBPTHREAD
                        pthread_mutex_lock(&r->root_mtx[taskEVENTLO]);                        pthread_mutex_lock(&r->root_mtx[taskTASK]);
 #endif  #endif
                        TAILQ_REMOVE(&r->root_eventlo, task, task_node);                        TAILQ_REMOVE(&r->root_task, task, task_node);
 #ifdef HAVE_LIBPTHREAD  #ifdef HAVE_LIBPTHREAD
                        pthread_mutex_unlock(&r->root_mtx[taskEVENTLO]);                        pthread_mutex_unlock(&r->root_mtx[taskTASK]);
 #endif  #endif
                         task->task_type = taskREADY;                          task->task_type = taskREADY;
 #ifdef HAVE_LIBPTHREAD  #ifdef HAVE_LIBPTHREAD
Line 505  retry: Line 1049  retry:
                         pthread_mutex_unlock(&r->root_mtx[taskREADY]);                          pthread_mutex_unlock(&r->root_mtx[taskREADY]);
 #endif  #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  #ifdef HAVE_LIBPTHREAD
         pthread_mutex_lock(&r->root_mtx[taskREADY]);          pthread_mutex_lock(&r->root_mtx[taskREADY]);
 #endif  #endif
Line 532  retry: Line 1078  retry:
   
 /*  /*
  * sched_hook_exception() - Default EXCEPTION hook   * sched_hook_exception() - Default EXCEPTION hook
    *
  * @root = root task   * @root = root task
  * @arg = custom handling: if arg == EV_EOF or other value; default: arg == NULL log errno   * @arg = custom handling: if arg == EV_EOF or other value; default: arg == NULL log errno
  * return: <0 errors and 0 ok   * return: <0 errors and 0 ok
Line 541  sched_hook_exception(void *root, void *arg) Line 1088  sched_hook_exception(void *root, void *arg)
 {  {
         sched_root_task_t *r = root;          sched_root_task_t *r = root;
   
        if (!r || !ROOT_DATA(r) || !ROOT_DATLEN(r))        if (!r)
                 return NULL;                  return NULL;
   
         /* custom exception handling ... */          /* custom exception handling ... */
Line 559  sched_hook_exception(void *root, void *arg) Line 1106  sched_hook_exception(void *root, void *arg)
         LOGERR;          LOGERR;
         return NULL;          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 = (int) 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), TASK_FUNC(t), TASK_ARG(t), evt.sigev_signo, 
                                   TASK_DATA(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.4  
changed lines
  Added in v.1.19


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