Diff for /libaitsched/src/hooks.c between versions 1.2.2.1 and 1.6.4.3

version 1.2.2.1, 2011/10/04 13:29:00 version 1.6.4.3, 2012/05/30 08:51:49
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
         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 };
   
        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);                        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 126  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);                        kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout);
                        FD_CLR(TASK_FD(t), &io->wfd); 
                         break;                          break;
                   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
                           kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout);
                           break;
                 default:                  default:
                         break;                          break;
         }          }
Line 154  sched_hook_cancel(void *task, void *arg __unused) Line 147  sched_hook_cancel(void *task, void *arg __unused)
   
 /*  /*
  * 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 155  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, 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, 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) {
                if (t->task_root->root_hooks.hook_exec.exception)                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                        t->task_root->root_hooks.hook_exec.exception(t->task_root, NULL);                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
                 else
                         LOGERR;
                 return (void*) -1;                  return (void*) -1;
         }          }
   
Line 192  sched_hook_read(void *task, void *arg __unused) Line 180  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 199  sched_hook_read(void *task, void *arg __unused) Line 188  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))  
                 return NULL;  
         else  
                 FD_SET(TASK_FD(t), &io->wfd);  
   
 #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], TASK_FD(t), EVFILT_WRITE, EV_ADD, 0, 0, (intptr_t) TASK_FD(t));
 #else  #else
         EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD, 0, 0, (void*) TASK_FD(t));          EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD, 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) {
                if (t->task_root->root_hooks.hook_exec.exception)                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                        t->task_root->root_hooks.hook_exec.exception(t->task_root, NULL);                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
                 else
                         LOGERR;
                 return (void*) -1;                  return (void*) -1;
         }          }
   
Line 229  sched_hook_write(void *task, void *arg __unused) Line 212  sched_hook_write(void *task, void *arg __unused)
 }  }
   
 /*  /*
    * 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__
           EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 
                           t->task_val.ts.tv_sec * 1000 + t->task_val.ts.tv_nsec / 1000000, 
                           (intptr_t) TASK_DATA(t));
   #else
           EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 
                           t->task_val.ts.tv_sec * 1000 + t->task_val.ts.tv_nsec / 1000000, 
                           (void*) TASK_DATA(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_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 237  sched_hook_write(void *task, void *arg __unused) Line 258  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;
         int en;          int en;
   
        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_eventlo) && (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 eventLo, set NOWAIT */
         if (TAILQ_FIRST(&r->root_eventlo))          if (TAILQ_FIRST(&r->root_eventlo))
                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) {
                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;    /* exit from scheduler */                                return NULL;
#ifdef NDEBUG                } else if (errno != EINTR)
                /* kevent no exit by error, if non-debug version */                        LOGERR;
                goto retry; 
#else 
                /* diagnostic exit from scheduler if kevent error occur */ 
                 return NULL;                  return NULL;
 #endif  
         }          }
   
        nw.tv_sec = nw.tv_nsec = 0;        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 330  retry: Line 365  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) {                                TAILQ_FOREACH_SAFE(task, &r->root_read, task_node, tmp) {
                                        if (TASK_FD(task) != ((int) res[i].udata))                                        if (TASK_FD(task) != ((intptr_t) res[i].udata))
                                                 continue;                                                  continue;
                                         /* 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);
   #ifdef HAVE_LIBPTHREAD
                                           pthread_mutex_unlock(&r->root_mtx[taskREAD]);
   #endif
                                         if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {                                          if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
                                                 if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {                                                  if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
                                                         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
                                                 } else {                                                  } 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
                                                           pthread_mutex_unlock(&r->root_mtx[taskREADY]);
   #endif
                                                 }                                                  }
                                         } else {                                          } 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
                                                   pthread_mutex_unlock(&r->root_mtx[taskREADY]);
   #endif
                                         }                                          }
                                         break;                                          break;
                                 }                                  }
                                 break;                                  break;
                         case EVFILT_WRITE:                          case EVFILT_WRITE:
                                TAILQ_FOREACH(task, &r->root_write, task_node) {                                TAILQ_FOREACH_SAFE(task, &r->root_write, task_node, tmp) {
                                        if (TASK_FD(task) != ((int) res[i].udata))                                        if (TASK_FD(task) != ((intptr_t) res[i].udata))
                                                 continue;                                                  continue;
                                         /* 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);
   #ifdef HAVE_LIBPTHREAD
                                           pthread_mutex_unlock(&r->root_mtx[taskWRITE]);
   #endif
                                         if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {                                          if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
                                                 if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {                                                  if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
                                                         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
                                                 } else {                                                  } 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
                                                           pthread_mutex_unlock(&r->root_mtx[taskREADY]);
   #endif
                                                 }                                                  }
                                         } else {                                          } 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
                                                   pthread_mutex_unlock(&r->root_mtx[taskREADY]);
   #endif
                                         }                                          }
                                         break;                                          break;
                                 }                                  }
                                 break;                                  break;
                           case EVFILT_TIMER:
                                   TAILQ_FOREACH_SAFE(task, &r->root_alarm, task_node, tmp) {
                                           if ((uintptr_t) TASK_DATA(task) != ((uintptr_t) res[i].udata))
                                                   continue;
                                           /* 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
                                           break;
                                   }
                                   break;
                 }                  }
                if (kevent(r->root_kq, evt, 1, NULL, 0, &nw) == -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) {
                                 if (r->root_hooks.hook_exec.exception(r, NULL))                                  if (r->root_hooks.hook_exec.exception(r, NULL))
                                        return NULL;    /* exit from scheduler */                                        return NULL;
                         } else
                                 LOGERR;
                 }
         }          }
   
         /* 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 eventlo priority task to ready queue, if there is no ready task or 
Line 402  retry: Line 515  retry:
                 if (!TAILQ_FIRST(&r->root_ready) || r->root_eventlo_miss > MAX_EVENTLO_MISS) {                  if (!TAILQ_FIRST(&r->root_ready) || r->root_eventlo_miss > MAX_EVENTLO_MISS) {
                         r->root_eventlo_miss = 0;                          r->root_eventlo_miss = 0;
   
   #ifdef HAVE_LIBPTHREAD
                           pthread_mutex_lock(&r->root_mtx[taskEVENTLO]);
   #endif
                         TAILQ_REMOVE(&r->root_eventlo, task, task_node);                          TAILQ_REMOVE(&r->root_eventlo, task, task_node);
   #ifdef HAVE_LIBPTHREAD
                           pthread_mutex_unlock(&r->root_mtx[taskEVENTLO]);
   #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_eventlo_miss++;
         } else          } else
                 r->root_eventlo_miss = 0;                  r->root_eventlo_miss = 0;
   
         /* 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   * sched_hook_exception() - Default EXCEPTION hook
    *
  * @root = root task   * @root = root task
 * @arg = may be EV_EOF * @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
  */   */
 void *  void *
Line 430  sched_hook_exception(void *root, void *arg) Line 570  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 ... */
         if (arg) {          if (arg) {
                 if (arg == (void*) EV_EOF)                  if (arg == (void*) EV_EOF)
                         return NULL;                          return NULL;
                return (void*) -1;      /* raise error */                return (void*) -1;      /* raise scheduler error!!! */
        } else        }
                LOGERR; 
   
        if (errno == EINTR)        /* if error hook exists */
                return (void*) -1;     /* raise error */        if (r->root_hooks.hook_root.error)
                 return (r->root_hooks.hook_root.error(root, (void*) ((intptr_t) errno)));
   
           /* default case! */
           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);
 }  }

Removed from v.1.2.2.1  
changed lines
  Added in v.1.6.4.3


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