Diff for /libaitsched/src/hooks.c between versions 1.30 and 1.42

version 1.30, 2015/07/02 23:27:06 version 1.42, 2023/08/17 14:14:24
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 - 2015Copyright 2004 - 2023
         by Michael Pounov <misho@elwix.org>.  All rights reserved.          by Michael Pounov <misho@elwix.org>.  All rights reserved.
   
 Redistribution and use in source and binary forms, with or without  Redistribution and use in source and binary forms, with or without
Line 47  SUCH DAMAGE. Line 47  SUCH DAMAGE.
 #include "hooks.h"  #include "hooks.h"
   
   
 static inline void  
 transit_task2ready(sched_task_t * __restrict t, sched_queue_t * __restrict q)  
 {  
         remove_task_from(t, q);  
   
         t->task_type = taskREADY;  
         insert_task_to(t, &(TASK_ROOT(t))->root_ready);  
 }  
   
 #ifdef HAVE_LIBPTHREAD  #ifdef HAVE_LIBPTHREAD
 static void *  static void *
 _sched_threadWrapper(sched_task_t *t)  _sched_threadWrapper(sched_task_t *t)
Line 156  sched_hook_init(void *root, void *arg __unused) Line 147  sched_hook_init(void *root, void *arg __unused)
         }          }
 #else  #else
         r->root_kq ^= r->root_kq;          r->root_kq ^= r->root_kq;
   #endif
   
         FD_ZERO(&r->root_fds[0]);          FD_ZERO(&r->root_fds[0]);
         FD_ZERO(&r->root_fds[1]);          FD_ZERO(&r->root_fds[1]);
#endif        FD_ZERO(&r->root_fds[2]);
   
         return NULL;          return NULL;
 }  }
Line 184  sched_hook_fini(void *root, void *arg __unused) Line 177  sched_hook_fini(void *root, void *arg __unused)
                 r->root_kq = 0;                  r->root_kq = 0;
         }          }
 #else  #else
         FD_ZERO(&r->root_fds[1]);  
         FD_ZERO(&r->root_fds[0]);  
         r->root_kq ^= r->root_kq;          r->root_kq ^= r->root_kq;
 #endif  #endif
   
           FD_ZERO(&r->root_fds[2]);
           FD_ZERO(&r->root_fds[1]);
           FD_ZERO(&r->root_fds[0]);
   
         return NULL;          return NULL;
 }  }
   
Line 204  sched_hook_cancel(void *task, void *arg __unused) Line 199  sched_hook_cancel(void *task, void *arg __unused)
 {  {
         sched_task_t *t = task, *tmp, *tt;          sched_task_t *t = task, *tmp, *tt;
         sched_root_task_t *r = NULL;          sched_root_task_t *r = NULL;
        int flg;        int flg = 0;
 #if SUP_ENABLE == KQ_SUPPORT  #if SUP_ENABLE == KQ_SUPPORT
         struct kevent chg[1];          struct kevent chg[1];
         struct timespec timeout = { 0, 0 };          struct timespec timeout = { 0, 0 };
 #elif SUP_ENABLE == EP_SUPPORT  #elif SUP_ENABLE == EP_SUPPORT
        struct epoll_event ee = { .events = 0, .data.fd = 0 };        struct epoll_event ee = { .events = 0, .data.u64 = 0l };
 #else  #else
         register int i;          register int i;
 #endif  #endif
Line 229  sched_hook_cancel(void *task, void *arg __unused) Line 224  sched_hook_cancel(void *task, void *arg __unused)
         switch (TASK_TYPE(t)) {          switch (TASK_TYPE(t)) {
                 case taskREAD:                  case taskREAD:
                         /* check for multi subscribers */                          /* check for multi subscribers */
                         flg = 0;  
                         TAILQ_FOREACH_SAFE(tt, &r->root_read, task_node, tmp)                          TAILQ_FOREACH_SAFE(tt, &r->root_read, task_node, tmp)
                                if (TASK_FD(tt) != TASK_FD(t))                                if (TASK_FD(tt) == TASK_FD(t))
                                        continue; 
                                else 
                                         flg++;                                          flg++;
 #if SUP_ENABLE == KQ_SUPPORT  #if SUP_ENABLE == KQ_SUPPORT
 #ifdef __NetBSD__  #ifdef __NetBSD__
Line 245  sched_hook_cancel(void *task, void *arg __unused) Line 237  sched_hook_cancel(void *task, void *arg __unused)
 #endif  #endif
 #elif SUP_ENABLE == EP_SUPPORT  #elif SUP_ENABLE == EP_SUPPORT
                         ee.data.fd = TASK_FD(t);                          ee.data.fd = TASK_FD(t);
                           ee.events ^= ee.events;
                         if (FD_ISSET(TASK_FD(t), &r->root_fds[1]))                          if (FD_ISSET(TASK_FD(t), &r->root_fds[1]))
                                ee.events = EPOLLOUT;                                ee.events |= EPOLLOUT;
   
                        if (flg < 2)                        if (flg < 2) {
                                 FD_CLR(TASK_FD(t), &r->root_fds[0]);                                  FD_CLR(TASK_FD(t), &r->root_fds[0]);
                        else                                FD_CLR(TASK_FD(t), &r->root_fds[2]);
                                ee.events |= (EPOLLIN | EPOLLPRI | EPOLLRDHUP);                        } else {
                                 if (FD_ISSET(TASK_FD(t), &r->root_fds[0]))
                                         ee.events |= EPOLLIN;
                                 if (FD_ISSET(TASK_FD(t), &r->root_fds[2]))
                                         ee.events |= EPOLLPRI;
                         }
 #else  #else
                         if (flg < 2) {                          if (flg < 2) {
                                 FD_CLR(TASK_FD(t), &r->root_fds[0]);                                  FD_CLR(TASK_FD(t), &r->root_fds[0]);
                                   FD_CLR(TASK_FD(t), &r->root_fds[2]);
   
                                 /* optimize select */                                  /* optimize select */
                                for (i = r->root_kq - 1; i > 2; i--)                                for (i = r->root_kq - 1; i >= 0; i--)
                                        if (FD_ISSET(i, &r->root_fds[0]) || FD_ISSET(i, &r->root_fds[1]))                                        if (FD_ISSET(i, &r->root_fds[0]) || 
                                                         FD_ISSET(i, &r->root_fds[1]) || 
                                                         FD_ISSET(i, &r->root_fds[2]))
                                                 break;                                                  break;
                                if (i > 2)                                r->root_kq = i + 1;
                                        r->root_kq = i + 1; 
                         }                          }
 #endif  #endif
                         break;                          break;
                 case taskWRITE:                  case taskWRITE:
                         /* check for multi subscribers */                          /* check for multi subscribers */
                         flg = 0;  
                         TAILQ_FOREACH_SAFE(tt, &r->root_write, task_node, tmp)                          TAILQ_FOREACH_SAFE(tt, &r->root_write, task_node, tmp)
                                if (TASK_FD(tt) != TASK_FD(t))                                if (TASK_FD(tt) == TASK_FD(t))
                                        continue; 
                                else 
                                         flg++;                                          flg++;
 #if SUP_ENABLE == KQ_SUPPORT  #if SUP_ENABLE == KQ_SUPPORT
 #ifdef __NetBSD__  #ifdef __NetBSD__
Line 283  sched_hook_cancel(void *task, void *arg __unused) Line 280  sched_hook_cancel(void *task, void *arg __unused)
 #endif  #endif
 #elif SUP_ENABLE == EP_SUPPORT  #elif SUP_ENABLE == EP_SUPPORT
                         ee.data.fd = TASK_FD(t);                          ee.data.fd = TASK_FD(t);
                           ee.events ^= ee.events;
                         if (FD_ISSET(TASK_FD(t), &r->root_fds[0]))                          if (FD_ISSET(TASK_FD(t), &r->root_fds[0]))
                                ee.events = EPOLLIN | EPOLLPRI | EPOLLRDHUP;                                ee.events |= EPOLLIN;
                         if (FD_ISSET(TASK_FD(t), &r->root_fds[2]))
                                 ee.events |= EPOLLPRI;
   
                         if (flg < 2)                          if (flg < 2)
                                 FD_CLR(TASK_FD(t), &r->root_fds[1]);                                  FD_CLR(TASK_FD(t), &r->root_fds[1]);
Line 295  sched_hook_cancel(void *task, void *arg __unused) Line 295  sched_hook_cancel(void *task, void *arg __unused)
                                 FD_CLR(TASK_FD(t), &r->root_fds[1]);                                  FD_CLR(TASK_FD(t), &r->root_fds[1]);
   
                                 /* optimize select */                                  /* optimize select */
                                for (i = r->root_kq - 1; i > 2; i--)                                for (i = r->root_kq - 1; i >= 0; i--)
                                        if (FD_ISSET(i, &r->root_fds[0]) || FD_ISSET(i, &r->root_fds[1]))                                        if (FD_ISSET(i, &r->root_fds[0]) || 
                                                         FD_ISSET(i, &r->root_fds[1]) || 
                                                         FD_ISSET(i, &r->root_fds[2]))
                                                 break;                                                  break;
                                if (i > 2)                                r->root_kq = i + 1;
                                        r->root_kq = i + 1; 
                         }                          }
 #endif  #endif
                         break;                          break;
                 case taskALARM:                  case taskALARM:
 #if SUP_ENABLE == KQ_SUPPORT  #if SUP_ENABLE == KQ_SUPPORT
                         /* check for multi subscribers */                          /* check for multi subscribers */
                         flg = 0;  
                         TAILQ_FOREACH_SAFE(tt, &r->root_alarm, task_node, tmp)                          TAILQ_FOREACH_SAFE(tt, &r->root_alarm, task_node, tmp)
                                if (TASK_DATA(tt) != TASK_DATA(t))                                if (TASK_DATA(tt) == TASK_DATA(t))
                                        continue; 
                                else 
                                         flg++;                                          flg++;
 #ifdef __NetBSD__  #ifdef __NetBSD__
                         EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, flg < 2 ? EV_DELETE : 0,                           EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, flg < 2 ? EV_DELETE : 0, 
Line 324  sched_hook_cancel(void *task, void *arg __unused) Line 322  sched_hook_cancel(void *task, void *arg __unused)
                 case taskNODE:                  case taskNODE:
 #if SUP_ENABLE == KQ_SUPPORT  #if SUP_ENABLE == KQ_SUPPORT
                         /* check for multi subscribers */                          /* check for multi subscribers */
                         flg = 0;  
                         TAILQ_FOREACH_SAFE(tt, &r->root_node, task_node, tmp)                          TAILQ_FOREACH_SAFE(tt, &r->root_node, task_node, tmp)
                                if (TASK_FD(tt) != TASK_FD(t))                                if (TASK_FD(tt) == TASK_FD(t))
                                        continue; 
                                else 
                                         flg++;                                          flg++;
 #ifdef __NetBSD__  #ifdef __NetBSD__
                         EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, flg < 2 ? EV_DELETE : 0,                           EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, flg < 2 ? EV_DELETE : 0, 
Line 342  sched_hook_cancel(void *task, void *arg __unused) Line 337  sched_hook_cancel(void *task, void *arg __unused)
                 case taskPROC:                  case taskPROC:
 #if SUP_ENABLE == KQ_SUPPORT  #if SUP_ENABLE == KQ_SUPPORT
                         /* check for multi subscribers */                          /* check for multi subscribers */
                         flg = 0;  
                         TAILQ_FOREACH_SAFE(tt, &r->root_proc, task_node, tmp)                          TAILQ_FOREACH_SAFE(tt, &r->root_proc, task_node, tmp)
                                if (TASK_VAL(tt) != TASK_VAL(t))                                if (TASK_VAL(tt) == TASK_VAL(t))
                                        continue; 
                                else 
                                         flg++;                                          flg++;
 #ifdef __NetBSD__  #ifdef __NetBSD__
                         EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, flg < 2 ? EV_DELETE : 0,                           EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, flg < 2 ? EV_DELETE : 0, 
Line 358  sched_hook_cancel(void *task, void *arg __unused) Line 350  sched_hook_cancel(void *task, void *arg __unused)
 #endif  #endif
                         break;                          break;
                 case taskSIGNAL:                  case taskSIGNAL:
 #if SUP_ENABLE == KQ_SUPPORT  
                         /* check for multi subscribers */                          /* check for multi subscribers */
                         flg = 0;  
                         TAILQ_FOREACH_SAFE(tt, &r->root_signal, task_node, tmp)                          TAILQ_FOREACH_SAFE(tt, &r->root_signal, task_node, tmp)
                                if (TASK_VAL(tt) != TASK_VAL(t))                                if (TASK_VAL(tt) == TASK_VAL(t))
                                        continue; 
                                else 
                                         flg++;                                          flg++;
   #if SUP_ENABLE == KQ_SUPPORT
 #ifdef __NetBSD__  #ifdef __NetBSD__
                         EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, flg < 2 ? EV_DELETE : 0,                           EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, flg < 2 ? EV_DELETE : 0, 
                                         0, 0, (intptr_t) TASK_VAL(t));                                          0, 0, (intptr_t) TASK_VAL(t));
Line 373  sched_hook_cancel(void *task, void *arg __unused) Line 362  sched_hook_cancel(void *task, void *arg __unused)
                         EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, flg < 2 ? EV_DELETE : 0,                           EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, flg < 2 ? EV_DELETE : 0, 
                                         0, 0, (void*) TASK_VAL(t));                                          0, 0, (void*) TASK_VAL(t));
 #endif  #endif
                         /* restore signal */  
                         if (flg < 2)  
                                 signal(TASK_VAL(t), SIG_DFL);  
 #endif  #endif
                           if (flg < 2) {
                                   pthread_mutex_lock(&TASK_ROOT(t)->root_sigmtx);
                                   sigdelset(&TASK_ROOT(t)->root_sigset, TASK_VAL(t));
                                   pthread_mutex_unlock(&TASK_ROOT(t)->root_sigmtx);
                           }
                         break;                          break;
 #ifdef AIO_SUPPORT  #ifdef AIO_SUPPORT
                 case taskAIO:                  case taskAIO:
 #if SUP_ENABLE == KQ_SUPPORT  #if SUP_ENABLE == KQ_SUPPORT
                         /* check for multi subscribers */                          /* check for multi subscribers */
                         flg = 0;  
                         TAILQ_FOREACH_SAFE(tt, &r->root_aio, task_node, tmp)                          TAILQ_FOREACH_SAFE(tt, &r->root_aio, task_node, tmp)
                                if (TASK_VAL(tt) != TASK_VAL(t))                                if (TASK_VAL(tt) == TASK_VAL(t))
                                        continue; 
                                else 
                                         flg++;                                          flg++;
 #ifdef __NetBSD__  #ifdef __NetBSD__
                         EV_SET(&chg[0], TASK_VAL(t), EVFILT_AIO, flg < 2 ? EV_DELETE : 0,                           EV_SET(&chg[0], TASK_VAL(t), EVFILT_AIO, flg < 2 ? EV_DELETE : 0, 
Line 399  sched_hook_cancel(void *task, void *arg __unused) Line 387  sched_hook_cancel(void *task, void *arg __unused)
                         if (acb) {                          if (acb) {
                                 if (aio_cancel(acb->aio_fildes, acb) == AIO_CANCELED)                                  if (aio_cancel(acb->aio_fildes, acb) == AIO_CANCELED)
                                         aio_return(acb);                                          aio_return(acb);
                                free(acb);                                e_free(acb);
                                 TASK_VAL(t) = 0;                                  TASK_VAL(t) = 0;
                         }                          }
 #endif  #endif
Line 408  sched_hook_cancel(void *task, void *arg __unused) Line 396  sched_hook_cancel(void *task, void *arg __unused)
                 case taskLIO:                  case taskLIO:
 #if SUP_ENABLE == KQ_SUPPORT  #if SUP_ENABLE == KQ_SUPPORT
                         /* check for multi subscribers */                          /* check for multi subscribers */
                         flg = 0;  
                         TAILQ_FOREACH_SAFE(tt, &r->root_lio, task_node, tmp)                          TAILQ_FOREACH_SAFE(tt, &r->root_lio, task_node, tmp)
                                if (TASK_VAL(tt) != TASK_VAL(t))                                if (TASK_VAL(tt) == TASK_VAL(t))
                                        continue; 
                                else 
                                         flg++;                                          flg++;
 #ifdef __NetBSD__  #ifdef __NetBSD__
                         EV_SET(&chg[0], TASK_VAL(t), EVFILT_LIO, flg < 2 ? EV_DELETE : 0,                           EV_SET(&chg[0], TASK_VAL(t), EVFILT_LIO, flg < 2 ? EV_DELETE : 0, 
Line 426  sched_hook_cancel(void *task, void *arg __unused) Line 411  sched_hook_cancel(void *task, void *arg __unused)
                                 for (i = 0; i < TASK_DATLEN(t); i++) {                                  for (i = 0; i < TASK_DATLEN(t); i++) {
                                         if (aio_cancel(acbs[i]->aio_fildes, acbs[i]) == AIO_CANCELED)                                          if (aio_cancel(acbs[i]->aio_fildes, acbs[i]) == AIO_CANCELED)
                                                 aio_return(acbs[i]);                                                  aio_return(acbs[i]);
                                        free(acbs[i]);                                        e_free(acbs[i]);
                                 }                                  }
                                free(acbs);                                e_free(acbs);
                                 TASK_VAL(t) = 0;                                  TASK_VAL(t) = 0;
                         }                          }
 #endif  #endif
Line 439  sched_hook_cancel(void *task, void *arg __unused) Line 424  sched_hook_cancel(void *task, void *arg __unused)
                 case taskUSER:                  case taskUSER:
 #if SUP_ENABLE == KQ_SUPPORT  #if SUP_ENABLE == KQ_SUPPORT
                         /* check for multi subscribers */                          /* check for multi subscribers */
                         flg = 0;  
                         TAILQ_FOREACH_SAFE(tt, &r->root_user, task_node, tmp)                          TAILQ_FOREACH_SAFE(tt, &r->root_user, task_node, tmp)
                                if (TASK_VAL(tt) != TASK_VAL(t))                                if (TASK_VAL(tt) == TASK_VAL(t))
                                        continue; 
                                else 
                                         flg++;                                          flg++;
 #ifdef __NetBSD__  #ifdef __NetBSD__
                         EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, flg < 2 ? EV_DELETE : 0,                           EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, flg < 2 ? EV_DELETE : 0, 
Line 475  sched_hook_cancel(void *task, void *arg __unused) Line 457  sched_hook_cancel(void *task, void *arg __unused)
                         schedCancel((sched_task_t*) TASK_RET(t));                          schedCancel((sched_task_t*) TASK_RET(t));
 #else  #else
                         /* check for multi subscribers */                          /* check for multi subscribers */
                         flg = 0;  
                         TAILQ_FOREACH_SAFE(tt, &r->root_rtc, task_node, tmp)                          TAILQ_FOREACH_SAFE(tt, &r->root_rtc, task_node, tmp)
                                if (TASK_DATA(tt) != TASK_DATA(t))                                if (TASK_DATA(tt) == TASK_DATA(t))
                                        continue; 
                                else 
                                         flg++;                                          flg++;
   
                         /* restore signal */                          /* restore signal */
Line 495  sched_hook_cancel(void *task, void *arg __unused) Line 474  sched_hook_cancel(void *task, void *arg __unused)
 #if SUP_ENABLE == KQ_SUPPORT  #if SUP_ENABLE == KQ_SUPPORT
         kevent(r->root_kq, chg, 1, NULL, 0, &timeout);          kevent(r->root_kq, chg, 1, NULL, 0, &timeout);
 #elif SUP_ENABLE == EP_SUPPORT  #elif SUP_ENABLE == EP_SUPPORT
        epoll_ctl(r->root_kq, ee.events ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, ee.data.fd, &ee);        if (TASK_TYPE(t) == taskREAD || TASK_TYPE(t) == taskWRITE) {
                 epoll_ctl(r->root_kq, ee.events ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, ee.data.fd, &ee);
         }
 #endif  #endif
         return NULL;          return NULL;
 }  }
Line 545  sched_hook_thread(void *task, void *arg) Line 526  sched_hook_thread(void *task, void *arg)
  * return: <0 errors and 0 ok   * return: <0 errors and 0 ok
  */   */
 void *  void *
sched_hook_read(void *task, void *arg __unused)sched_hook_read(void *task, void *arg)
 {  {
         sched_task_t *t = task;          sched_task_t *t = task;
         sched_root_task_t *r = NULL;          sched_root_task_t *r = NULL;
           uintptr_t mask = (uintptr_t) arg;
 #if SUP_ENABLE == KQ_SUPPORT  #if SUP_ENABLE == KQ_SUPPORT
         struct kevent chg[1];          struct kevent chg[1];
         struct timespec timeout = { 0, 0 };          struct timespec timeout = { 0, 0 };
 #elif SUP_ENABLE == EP_SUPPORT  #elif SUP_ENABLE == EP_SUPPORT
        struct epoll_event ee = { .events = EPOLLIN | EPOLLPRI | EPOLLRDHUP, .data.fd = 0 };        struct epoll_event ee = { 0 };
         int flg = 0;          int flg = 0;
 #endif  #endif
   
Line 564  sched_hook_read(void *task, void *arg __unused) Line 546  sched_hook_read(void *task, void *arg __unused)
   
 #if SUP_ENABLE == KQ_SUPPORT  #if SUP_ENABLE == KQ_SUPPORT
 #ifdef __NetBSD__  #ifdef __NetBSD__
        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, (intptr_t) TASK_FD(t));        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD | EV_CLEAR | mask, 
                         0, 0, (intptr_t) TASK_FD(t));
 #else  #else
        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, (void*) TASK_FD(t));        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD | EV_CLEAR | mask, 
                         0, 0, (void*) TASK_FD(t));
 #endif  #endif
         if (kevent(r->root_kq, chg, 1, NULL, 0, &timeout) == -1) {          if (kevent(r->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                 if (r->root_hooks.hook_exec.exception)                  if (r->root_hooks.hook_exec.exception)
Line 576  sched_hook_read(void *task, void *arg __unused) Line 560  sched_hook_read(void *task, void *arg __unused)
                 return (void*) -1;                  return (void*) -1;
         }          }
 #elif SUP_ENABLE == EP_SUPPORT  #elif SUP_ENABLE == EP_SUPPORT
        if (FD_ISSET(TASK_FD(t), &r->root_fds[0]))        if (!mask)
                 mask = EPOLLIN | EPOLLPRI;
         ee.data.fd = TASK_FD(t);
         ee.events = mask;
         if (FD_ISSET(TASK_FD(t), &r->root_fds[2])) {
                 flg |= 4;
                 ee.events |= EPOLLPRI;
         }
         if (FD_ISSET(TASK_FD(t), &r->root_fds[0])) {
                 flg |= 1;                  flg |= 1;
                   ee.events |= EPOLLIN;
           }
         if (FD_ISSET(TASK_FD(t), &r->root_fds[1])) {          if (FD_ISSET(TASK_FD(t), &r->root_fds[1])) {
                 flg |= 2;                  flg |= 2;
                 ee.events |= EPOLLOUT;                  ee.events |= EPOLLOUT;
         }          }
   
         ee.data.fd = TASK_FD(t);  
         if (epoll_ctl(r->root_kq, flg ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, TASK_FD(t), &ee) == -1) {          if (epoll_ctl(r->root_kq, flg ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, TASK_FD(t), &ee) == -1) {
                 if (r->root_hooks.hook_exec.exception)                  if (r->root_hooks.hook_exec.exception)
                         r->root_hooks.hook_exec.exception(r, NULL);                          r->root_hooks.hook_exec.exception(r, NULL);
                 else                  else
                         LOGERR;                          LOGERR;
                 return (void*) -1;                  return (void*) -1;
        } else        } else {
                FD_SET(TASK_FD(t), &r->root_fds[0]);                if (mask & EPOLLIN)
                         FD_SET(TASK_FD(t), &r->root_fds[0]);
                 if (mask & EPOLLPRI)
                         FD_SET(TASK_FD(t), &r->root_fds[2]);
         }
 #else  #else
        FD_SET(TASK_FD(t), &r->root_fds[0]);        if (!mask) {
                 FD_SET(TASK_FD(t), &r->root_fds[0]);
                 FD_SET(TASK_FD(t), &r->root_fds[2]);
         } else {
                 if (mask & 1)
                         FD_SET(TASK_FD(t), &r->root_fds[0]);
                 if (mask & 2)
                         FD_SET(TASK_FD(t), &r->root_fds[2]);
         }
 
         if (TASK_FD(t) >= r->root_kq)          if (TASK_FD(t) >= r->root_kq)
                 r->root_kq = TASK_FD(t) + 1;                  r->root_kq = TASK_FD(t) + 1;
 #endif  #endif
Line 609  sched_hook_read(void *task, void *arg __unused) Line 615  sched_hook_read(void *task, void *arg __unused)
  * return: <0 errors and 0 ok   * return: <0 errors and 0 ok
  */   */
 void *  void *
sched_hook_write(void *task, void *arg __unused)sched_hook_write(void *task, void *arg)
 {  {
         sched_task_t *t = task;          sched_task_t *t = task;
         sched_root_task_t *r = NULL;          sched_root_task_t *r = NULL;
           uintptr_t mask = (uintptr_t) arg;
 #if SUP_ENABLE == KQ_SUPPORT  #if SUP_ENABLE == KQ_SUPPORT
         struct kevent chg[1];          struct kevent chg[1];
         struct timespec timeout = { 0, 0 };          struct timespec timeout = { 0, 0 };
 #elif SUP_ENABLE == EP_SUPPORT  #elif SUP_ENABLE == EP_SUPPORT
        struct epoll_event ee = { .events = EPOLLOUT, .data.fd = 0 };        struct epoll_event ee = { 0 };
         int flg = 0;          int flg = 0;
 #endif  #endif
   
Line 628  sched_hook_write(void *task, void *arg __unused) Line 635  sched_hook_write(void *task, void *arg __unused)
   
 #if SUP_ENABLE == KQ_SUPPORT  #if SUP_ENABLE == KQ_SUPPORT
 #ifdef __NetBSD__  #ifdef __NetBSD__
        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, (intptr_t) TASK_FD(t));        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD | EV_CLEAR | mask, 
                         0, 0, (intptr_t) TASK_FD(t));
 #else  #else
        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, (void*) TASK_FD(t));        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD | EV_CLEAR | mask, 
                         0, 0, (void*) TASK_FD(t));
 #endif  #endif
         if (kevent(r->root_kq, chg, 1, NULL, 0, &timeout) == -1) {          if (kevent(r->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                 if (r->root_hooks.hook_exec.exception)                  if (r->root_hooks.hook_exec.exception)
Line 640  sched_hook_write(void *task, void *arg __unused) Line 649  sched_hook_write(void *task, void *arg __unused)
                 return (void*) -1;                  return (void*) -1;
         }          }
 #elif SUP_ENABLE == EP_SUPPORT  #elif SUP_ENABLE == EP_SUPPORT
           if (!mask)
                   mask = EPOLLOUT;
           ee.data.fd = TASK_FD(t);
           ee.events = mask;
   
           if (FD_ISSET(TASK_FD(t), &r->root_fds[2])) {
                   flg |= 4;
                   ee.events |= EPOLLPRI;
           }
         if (FD_ISSET(TASK_FD(t), &r->root_fds[0])) {          if (FD_ISSET(TASK_FD(t), &r->root_fds[0])) {
                 flg |= 1;                  flg |= 1;
                ee.events |= EPOLLIN | EPOLLPRI | EPOLLRDHUP;                ee.events |= EPOLLIN;
         }          }
        if (FD_ISSET(TASK_FD(t), &r->root_fds[1]))        if (FD_ISSET(TASK_FD(t), &r->root_fds[1])) {
                 flg |= 2;                  flg |= 2;
                   ee.events |= EPOLLOUT;
           }
   
         ee.data.fd = TASK_FD(t);  
         if (epoll_ctl(r->root_kq, flg ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, TASK_FD(t), &ee) == -1) {          if (epoll_ctl(r->root_kq, flg ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, TASK_FD(t), &ee) == -1) {
                 if (r->root_hooks.hook_exec.exception)                  if (r->root_hooks.hook_exec.exception)
                         r->root_hooks.hook_exec.exception(r, NULL);                          r->root_hooks.hook_exec.exception(r, NULL);
Line 655  sched_hook_write(void *task, void *arg __unused) Line 674  sched_hook_write(void *task, void *arg __unused)
                         LOGERR;                          LOGERR;
                 return (void*) -1;                  return (void*) -1;
         } else          } else
                FD_SET(TASK_FD(t), &r->root_fds[1]);                if (mask & EPOLLOUT)
                         FD_SET(TASK_FD(t), &r->root_fds[1]);
 #else  #else
        FD_SET(TASK_FD(t), &r->root_fds[1]);        if (!mask)
                 FD_SET(TASK_FD(t), &r->root_fds[1]);
         else
                 if (mask & 1)
                         FD_SET(TASK_FD(t), &r->root_fds[1]);
 
         if (TASK_FD(t) >= r->root_kq)          if (TASK_FD(t) >= r->root_kq)
                 r->root_kq = TASK_FD(t) + 1;                  r->root_kq = TASK_FD(t) + 1;
 #endif  #endif
Line 708  sched_hook_alarm(void *task, void *arg __unused) Line 733  sched_hook_alarm(void *task, void *arg __unused)
  * sched_hook_node() - Default NODE hook   * sched_hook_node() - Default NODE hook
  *   *
  * @task = current task   * @task = current task
 * @arg = unused * @arg = if arg == 42 then waiting for all events
  * return: <0 errors and 0 ok   * return: <0 errors and 0 ok
  */   */
 void *  void *
sched_hook_node(void *task, void *arg __unused)sched_hook_node(void *task, void *arg)
 {  {
 #if SUP_ENABLE == KQ_SUPPORT  #if SUP_ENABLE == KQ_SUPPORT
         sched_task_t *t = task;          sched_task_t *t = task;
         struct kevent chg[1];          struct kevent chg[1];
         struct timespec timeout = { 0, 0 };          struct timespec timeout = { 0, 0 };
           u_int addflags = (u_int) (uintptr_t) arg;
   
         if (!t || !TASK_ROOT(t))          if (!t || !TASK_ROOT(t))
                 return (void*) -1;                  return (void*) -1;
Line 725  sched_hook_node(void *task, void *arg __unused) Line 751  sched_hook_node(void *task, void *arg __unused)
 #ifdef __NetBSD__  #ifdef __NetBSD__
         EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_ADD | EV_CLEAR,           EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_ADD | EV_CLEAR, 
                         NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB |                           NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | 
                        NOTE_LINK | NOTE_RENAME | NOTE_REVOKE, 0, (intptr_t) TASK_FD(t));                        NOTE_LINK | NOTE_RENAME | NOTE_REVOKE | addflags, 0, (intptr_t) TASK_FD(t));
 #else  #else
         EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_ADD | EV_CLEAR,           EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_ADD | EV_CLEAR, 
                         NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB |                           NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | 
                        NOTE_LINK | NOTE_RENAME | NOTE_REVOKE, 0, (void*) TASK_FD(t));                        NOTE_LINK | NOTE_RENAME | NOTE_REVOKE | addflags, 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 790  sched_hook_proc(void *task, void *arg __unused) Line 816  sched_hook_proc(void *task, void *arg __unused)
 void *  void *
 sched_hook_signal(void *task, void *arg __unused)  sched_hook_signal(void *task, void *arg __unused)
 {  {
 #if SUP_ENABLE == KQ_SUPPORT  
         sched_task_t *t = task;          sched_task_t *t = task;
   #if SUP_ENABLE == KQ_SUPPORT
         struct kevent chg[1];          struct kevent chg[1];
         struct timespec timeout = { 0, 0 };          struct timespec timeout = { 0, 0 };
   #endif
   
         if (!t || !TASK_ROOT(t))          if (!t || !TASK_ROOT(t))
                 return (void*) -1;                  return (void*) -1;
   
        /* ignore signal */#if SUP_ENABLE == KQ_SUPPORT
        signal(TASK_VAL(t), SIG_IGN); 
 
 #ifdef __NetBSD__  #ifdef __NetBSD__
         EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_ADD | EV_CLEAR, 0, 0, (intptr_t) TASK_VAL(t));          EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_ADD | EV_CLEAR, 0, 0, (intptr_t) TASK_VAL(t));
 #else  #else
Line 814  sched_hook_signal(void *task, void *arg __unused) Line 839  sched_hook_signal(void *task, void *arg __unused)
                 return (void*) -1;                  return (void*) -1;
         }          }
 #endif  #endif
   
           pthread_mutex_lock(&TASK_ROOT(t)->root_sigmtx);
           sigaddset(&TASK_ROOT(t)->root_sigset, TASK_VAL(t));
           pthread_mutex_unlock(&TASK_ROOT(t)->root_sigmtx);
   
         return NULL;          return NULL;
 }  }
   
Line 861  static inline void  Line 891  static inline void 
 fetch_hook_kevent_proceed(int en, struct kevent *res, sched_root_task_t *r)  fetch_hook_kevent_proceed(int en, struct kevent *res, sched_root_task_t *r)
 {  {
         struct kevent evt[1];          struct kevent evt[1];
        register int i;        register int i, flg;
         sched_task_t *task, *tmp;          sched_task_t *task, *tmp;
         struct timespec now = { 0, 0 };          struct timespec now = { 0, 0 };
 #ifdef AIO_SUPPORT  #ifdef AIO_SUPPORT
Line 869  fetch_hook_kevent_proceed(int en, struct kevent *res,  Line 899  fetch_hook_kevent_proceed(int en, struct kevent *res, 
         struct aiocb *acb;          struct aiocb *acb;
 #ifdef EVFILT_LIO  #ifdef EVFILT_LIO
         int l;          int l;
         register int j;  
         off_t off;          off_t off;
         struct aiocb **acbs;          struct aiocb **acbs;
         struct iovec *iv;          struct iovec *iv;
Line 880  fetch_hook_kevent_proceed(int en, struct kevent *res,  Line 909  fetch_hook_kevent_proceed(int en, struct kevent *res, 
                 memcpy(evt, &res[i], sizeof evt);                  memcpy(evt, &res[i], sizeof evt);
                 evt->flags = EV_DELETE;                  evt->flags = EV_DELETE;
                 /* Put read/write task to ready queue */                  /* Put read/write task to ready queue */
                   flg = 0;
                 switch (res[i].filter) {                  switch (res[i].filter) {
                         case EVFILT_READ:                          case EVFILT_READ:
                                 TAILQ_FOREACH_SAFE(task, &r->root_read, task_node, tmp) {                                  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;                                                if (!flg) {
                                        else {                                                        TASK_RET(task) = res[i].data;
                                                TASK_RET(task) = res[i].data;                                                        TASK_FLAG(task) = (u_long) res[i].fflags;
                                                TASK_FLAG(task) = (u_long) res[i].fflags; 
                                        } 
                                        /* remove read handle */ 
                                        remove_task_from(task, &r->root_read); 
   
                                        if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {                                                        /* remove read handle */
                                                if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {                                                        remove_task_from(task, &r->root_read);
                                                        task->task_type = taskUNUSE;
                                                        insert_task_to(task, &r->root_unuse);                                                        if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
                                                } else {                                                                if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
                                                        task->task_type = taskREADY;                                                                        task->task_type = taskUNUSE;
                                                        insert_task_to(task, &r->root_ready);                                                                        insert_task_to(task, &r->root_unuse);
                                                                 } else {
                                                                         task->task_type = taskREADY;
                                                                         insert_task_to(task, &r->root_ready);
                                                                 }
                                                         } else {
                                                                 task->task_type = taskREADY;
                                                                 insert_task_to(task, &r->root_ready);
                                                         }
                                                 }                                                  }
                                        } else {                                                flg++;
                                                task->task_type = taskREADY; 
                                                insert_task_to(task, &r->root_ready); 
                                         }                                          }
                                 }                                  }
                                 break;                                  break;
                         case EVFILT_WRITE:                          case EVFILT_WRITE:
                                 TAILQ_FOREACH_SAFE(task, &r->root_write, task_node, tmp) {                                  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;                                                if (!flg) {
                                        else {                                                        TASK_RET(task) = res[i].data;
                                                TASK_RET(task) = res[i].data;                                                        TASK_FLAG(task) = (u_long) res[i].fflags;
                                                TASK_FLAG(task) = (u_long) res[i].fflags; 
                                        } 
                                        /* remove write handle */ 
                                        remove_task_from(task, &r->root_write); 
   
                                        if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {                                                        /* remove write handle */
                                                if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {                                                        remove_task_from(task, &r->root_write);
                                                        task->task_type = taskUNUSE;
                                                        insert_task_to(task, &r->root_unuse);                                                        if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
                                                } else {                                                                if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
                                                        task->task_type = taskREADY;                                                                        task->task_type = taskUNUSE;
                                                        insert_task_to(task, &r->root_ready);                                                                        insert_task_to(task, &r->root_unuse);
                                                                 } else {
                                                                         task->task_type = taskREADY;
                                                                         insert_task_to(task, &r->root_ready);
                                                                 }
                                                         } else {
                                                                 task->task_type = taskREADY;
                                                                 insert_task_to(task, &r->root_ready);
                                                         }
                                                 }                                                  }
                                        } else {                                                flg++;
                                                task->task_type = taskREADY; 
                                                insert_task_to(task, &r->root_ready); 
                                         }                                          }
                                 }                                  }
                                 break;                                  break;
                         case EVFILT_TIMER:                          case EVFILT_TIMER:
                                 TAILQ_FOREACH_SAFE(task, &r->root_alarm, task_node, tmp) {                                  TAILQ_FOREACH_SAFE(task, &r->root_alarm, task_node, tmp) {
                                        if ((uintptr_t) TASK_DATA(task) != ((uintptr_t) res[i].udata))                                        if ((uintptr_t) TASK_DATA(task) == ((uintptr_t) res[i].udata)) {
                                                continue;                                                if (!flg) {
                                        else {                                                        TASK_RET(task) = res[i].data;
                                                TASK_RET(task) = res[i].data;                                                        TASK_FLAG(task) = (u_long) res[i].fflags;
                                                TASK_FLAG(task) = (u_long) res[i].fflags;
                                                         /* remove alarm handle */
                                                         transit_task2ready(task, &r->root_alarm);
                                                 }
                                                 flg++;
                                         }                                          }
                                         /* remove alarm handle */  
                                         transit_task2ready(task, &r->root_alarm);  
                                 }                                  }
                                 break;                                  break;
                         case EVFILT_VNODE:                          case EVFILT_VNODE:
                                 TAILQ_FOREACH_SAFE(task, &r->root_node, task_node, tmp) {                                  TAILQ_FOREACH_SAFE(task, &r->root_node, task_node, tmp) {
                                        if (TASK_FD(task) != ((intptr_t) res[i].udata))                                        if (TASK_FD(task) == ((intptr_t) res[i].udata)) {
                                                continue;                                                if (!flg) {
                                        else {                                                        TASK_RET(task) = res[i].data;
                                                TASK_RET(task) = res[i].data;                                                        TASK_FLAG(task) = (u_long) res[i].fflags;
                                                TASK_FLAG(task) = (u_long) res[i].fflags;
                                                         /* remove node handle */
                                                         transit_task2ready(task, &r->root_node);
                                                 }
                                                 flg++;
                                         }                                          }
                                         /* remove node handle */  
                                         transit_task2ready(task, &r->root_node);  
                                 }                                  }
                                 break;                                  break;
                         case EVFILT_PROC:                          case EVFILT_PROC:
                                 TAILQ_FOREACH_SAFE(task, &r->root_proc, task_node, tmp) {                                  TAILQ_FOREACH_SAFE(task, &r->root_proc, task_node, tmp) {
                                        if (TASK_VAL(task) != ((uintptr_t) res[i].udata))                                        if (TASK_VAL(task) == ((uintptr_t) res[i].udata)) {
                                                continue;                                                if (!flg) {
                                        else {                                                        TASK_RET(task) = res[i].data;
                                                TASK_RET(task) = res[i].data;                                                        TASK_FLAG(task) = (u_long) res[i].fflags;
                                                TASK_FLAG(task) = (u_long) res[i].fflags;
                                                         /* remove proc handle */
                                                         transit_task2ready(task, &r->root_proc);
                                                 }
                                                 flg++;
                                         }                                          }
                                         /* remove proc handle */  
                                         transit_task2ready(task, &r->root_proc);  
                                 }                                  }
                                 break;                                  break;
                         case EVFILT_SIGNAL:                          case EVFILT_SIGNAL:
                                 TAILQ_FOREACH_SAFE(task, &r->root_signal, task_node, tmp) {                                  TAILQ_FOREACH_SAFE(task, &r->root_signal, task_node, tmp) {
                                        if (TASK_VAL(task) != ((uintptr_t) res[i].udata))                                        if (TASK_VAL(task) == ((uintptr_t) res[i].udata)) {
                                                continue;                                                if (!flg) {
                                        else {                                                        TASK_RET(task) = res[i].data;
                                                TASK_RET(task) = res[i].data;                                                        TASK_FLAG(task) = (u_long) res[i].fflags;
                                                TASK_FLAG(task) = (u_long) res[i].fflags;
                                                         /* remove signal handle */
                                                         transit_task2ready(task, &r->root_signal);
                                                 }
                                                 flg++;
                                         }                                          }
                                         /* remove signal handle */  
                                         transit_task2ready(task, &r->root_signal);  
                                 }                                  }
                                 break;                                  break;
 #ifdef AIO_SUPPORT  #ifdef AIO_SUPPORT
                         case EVFILT_AIO:                          case EVFILT_AIO:
                                 TAILQ_FOREACH_SAFE(task, &r->root_aio, task_node, tmp) {                                  TAILQ_FOREACH_SAFE(task, &r->root_aio, task_node, tmp) {
                                         acb = (struct aiocb*) TASK_VAL(task);                                          acb = (struct aiocb*) TASK_VAL(task);
                                        if (acb != ((struct aiocb*) res[i].udata))                                        if (acb == ((struct aiocb*) res[i].udata)) {
                                                continue;                                                if (!flg) {
                                        else {                                                        TASK_RET(task) = res[i].data;
                                                TASK_RET(task) = res[i].data;                                                        TASK_FLAG(task) = (u_long) res[i].fflags;
                                                TASK_FLAG(task) = (u_long) res[i].fflags; 
                                        } 
                                        /* remove user handle */ 
                                        transit_task2ready(task, &r->root_aio); 
   
                                        fd = acb->aio_fildes;                                                        /* remove user handle */
                                        if ((len = aio_return(acb)) != -1) {                                                        transit_task2ready(task, &r->root_aio);
                                                if (lseek(fd, acb->aio_offset + len, SEEK_CUR) == -1)
                                                        LOGERR;                                                        fd = acb->aio_fildes;
                                        } else                                                        if ((len = aio_return(acb)) != -1) {
                                                LOGERR;                                                                if (lseek(fd, acb->aio_offset + len, SEEK_CUR) == -1)
                                        free(acb);                                                                        LOGERR;
                                        TASK_DATLEN(task) = (u_long) len;                                                        } else
                                        TASK_FD(task) = fd;                                                                LOGERR;
                                                         e_free(acb);
                                                         TASK_DATLEN(task) = (u_long) len;
                                                         TASK_FD(task) = fd;
                                                 }
                                                 flg++;
                                         }
                                 }                                  }
                                 break;                                  break;
 #ifdef EVFILT_LIO  #ifdef EVFILT_LIO
                         case EVFILT_LIO:                          case EVFILT_LIO:
                                 TAILQ_FOREACH_SAFE(task, &r->root_lio, task_node, tmp) {                                  TAILQ_FOREACH_SAFE(task, &r->root_lio, task_node, tmp) {
                                         acbs = (struct aiocb**) TASK_VAL(task);                                          acbs = (struct aiocb**) TASK_VAL(task);
                                        if (acbs != ((struct aiocb**) res[i].udata))                                        if (acbs == ((struct aiocb**) res[i].udata)) {
                                                continue;                                                if (!flg) {
                                        else {                                                        TASK_RET(task) = res[i].data;
                                                TASK_RET(task) = res[i].data;                                                        TASK_FLAG(task) = (u_long) res[i].fflags;
                                                TASK_FLAG(task) = (u_long) res[i].fflags; 
                                        } 
                                        /* remove user handle */ 
                                        transit_task2ready(task, &r->root_lio); 
   
                                        iv = (struct iovec*) TASK_DATA(task);                                                        /* remove user handle */
                                        fd = acbs[0]->aio_fildes;                                                        transit_task2ready(task, &r->root_lio);
                                        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)                                                        iv = (struct iovec*) TASK_DATA(task);
                                                LOGERR;                                                        fd = acbs[0]->aio_fildes;
                                                         off = acbs[0]->aio_offset;
                                                         for (len = 0; i < TASK_DATLEN(task); len += l, i++) {
                                                                 if ((iv[i].iov_len = aio_return(acbs[i])) == -1)
                                                                         l = 0;
                                                                 else
                                                                         l = iv[i].iov_len;
                                                                 e_free(acbs[i]);
                                                         }
                                                         e_free(acbs);
                                                         TASK_DATLEN(task) = (u_long) len;
                                                         TASK_FD(task) = fd;
 
                                                         if (lseek(fd, off + len, SEEK_CUR) == -1)
                                                                 LOGERR;
                                                 }
                                                 flg++;
                                         }
                                 }                                  }
                                 break;                                  break;
 #endif  /* EVFILT_LIO */  #endif  /* EVFILT_LIO */
Line 1039  fetch_hook_kevent_proceed(int en, struct kevent *res,  Line 1085  fetch_hook_kevent_proceed(int en, struct kevent *res, 
 #ifdef EVFILT_USER  #ifdef EVFILT_USER
                         case EVFILT_USER:                          case EVFILT_USER:
                                 TAILQ_FOREACH_SAFE(task, &r->root_user, task_node, tmp) {                                  TAILQ_FOREACH_SAFE(task, &r->root_user, task_node, tmp) {
                                        if (TASK_VAL(task) != ((uintptr_t) res[i].udata))                                        if (TASK_VAL(task) == ((uintptr_t) res[i].udata)) {
                                                continue;                                                if (!flg) {
                                        else {                                                        TASK_RET(task) = res[i].data;
                                                TASK_RET(task) = res[i].data;                                                        TASK_FLAG(task) = (u_long) res[i].fflags;
                                                TASK_FLAG(task) = (u_long) res[i].fflags;
                                                         /* remove user handle */
                                                         transit_task2ready(task, &r->root_user);
                                                 }
                                                 flg++;
                                         }                                          }
                                         /* remove user handle */  
                                         transit_task2ready(task, &r->root_user);  
                                 }                                  }
                                 break;                                  break;
 #endif  /* EVFILT_USER */  #endif  /* EVFILT_USER */
                 }                  }
   
                   if (flg > 1)
                           evt->flags &= ~EV_DELETE;
   
                 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)
                                 r->root_hooks.hook_exec.exception(r, NULL);                                  r->root_hooks.hook_exec.exception(r, NULL);
Line 1066  fetch_hook_kevent_proceed(int en, struct kevent *res,  Line 1117  fetch_hook_kevent_proceed(int en, struct kevent *res, 
 static inline void  static inline void
 fetch_hook_epoll_proceed(int en, struct epoll_event *res, sched_root_task_t *r)  fetch_hook_epoll_proceed(int en, struct epoll_event *res, sched_root_task_t *r)
 {  {
        register int i, flg;        register int i, rflg, wflg;
         int ops = EPOLL_CTL_DEL;          int ops = EPOLL_CTL_DEL;
        sched_task_t *task, *tmp;        sched_task_t *t, *tmp, *task;
         struct epoll_event evt[1];          struct epoll_event evt[1];
   
         for (i = 0; i < en; i++) {          for (i = 0; i < en; i++) {
                 memcpy(evt, &res[i], sizeof evt);                  memcpy(evt, &res[i], sizeof evt);
                   evt->events ^= evt->events;
                   rflg = wflg = 0;
   
                if (evt->events & (EPOLLIN | EPOLLPRI | EPOLLET)) {                if (res[i].events & (EPOLLIN | EPOLLPRI)) {
                        flg = 0;                        task = NULL;
                        TAILQ_FOREACH_SAFE(task, &r->root_read, task_node, tmp) {                        TAILQ_FOREACH_SAFE(t, &r->root_read, task_node, tmp) {
                                if (TASK_FD(task) != evt->data.fd)                                if (TASK_FD(t) == evt->data.fd) {
                                        continue;                                        if (!task)
                                else {                                                task = t;
                                        flg++;                                        rflg++;
                                        FD_CLR(TASK_FD(task), &r->root_fds[0]); 
                                        TASK_FLAG(task) = ioctl(TASK_FD(task), FIONREAD, &TASK_RET(task)); 
 
                                        evt->events &= ~(EPOLLIN | EPOLLPRI | EPOLLET | EPOLLRDHUP); 
                                        if (FD_ISSET(TASK_FD(task), &r->root_fds[1])) { 
                                                ops = EPOLL_CTL_MOD; 
                                                evt->events |= EPOLLOUT; 
                                        } 
                                 }                                  }
                           }
   
                           if (task) {
                                   TASK_FLAG(task) = ioctl(TASK_FD(task), FIONREAD, &TASK_RET(task));
                                 /* remove read handle */                                  /* remove read handle */
                                 remove_task_from(task, &r->root_read);                                  remove_task_from(task, &r->root_read);
   
Line 1106  fetch_hook_epoll_proceed(int en, struct epoll_event *r Line 1155  fetch_hook_epoll_proceed(int en, struct epoll_event *r
                                         task->task_type = taskREADY;                                          task->task_type = taskREADY;
                                         insert_task_to(task, &r->root_ready);                                          insert_task_to(task, &r->root_ready);
                                 }                                  }
   
                                   if (!(res[i].events & EPOLLOUT) && FD_ISSET(evt->data.fd, &r->root_fds[1])) {
                                           evt->events |= EPOLLOUT;
                                           wflg = 42;
                                   }
                                   if (rflg > 1) {
                                           if (FD_ISSET(evt->data.fd, &r->root_fds[0]))
                                                   evt->events |= EPOLLIN;
                                           if (FD_ISSET(evt->data.fd, &r->root_fds[2]))
                                                   evt->events |= EPOLLPRI;
                                   } else {
                                           FD_CLR(evt->data.fd, &r->root_fds[0]);
                                           FD_CLR(evt->data.fd, &r->root_fds[2]);
                                   }
                         }                          }
                         if (flg > 1)  
                                 ops = EPOLL_CTL_MOD;  
                 }                  }
                if (res[i].events & EPOLLOUT) {
                if (evt->events & EPOLLOUT) {                        task = NULL;
                        flg = 0;                        TAILQ_FOREACH_SAFE(t, &r->root_write, task_node, tmp) {
                        TAILQ_FOREACH_SAFE(task, &r->root_write, task_node, tmp) {                                if (TASK_FD(t) == evt->data.fd) {
                                if (TASK_FD(task) != evt->data.fd)                                        if (!task)
                                        continue;                                                task = t;
                                else {                                        wflg++;
                                        flg++; 
                                        FD_CLR(TASK_FD(task), &r->root_fds[1]); 
                                        TASK_FLAG(task) = ioctl(TASK_FD(task),  
                                                        FIONWRITE, &TASK_RET(task)); 
 
                                        evt->events &= ~EPOLLOUT; 
                                        if (FD_ISSET(TASK_FD(task), &r->root_fds[0])) { 
                                                ops = EPOLL_CTL_MOD; 
                                                evt->events |= EPOLLIN | EPOLLPRI | EPOLLRDHUP; 
                                        } 
                                 }                                  }
                           }
   
                           if (task) {
                                   TASK_FLAG(task) = ioctl(TASK_FD(task), FIONWRITE, &TASK_RET(task));
                                 /* remove write handle */                                  /* remove write handle */
                                 remove_task_from(task, &r->root_write);                                  remove_task_from(task, &r->root_write);
   
Line 1144  fetch_hook_epoll_proceed(int en, struct epoll_event *r Line 1199  fetch_hook_epoll_proceed(int en, struct epoll_event *r
                                         task->task_type = taskREADY;                                          task->task_type = taskREADY;
                                         insert_task_to(task, &r->root_ready);                                          insert_task_to(task, &r->root_ready);
                                 }                                  }
   
                                   if (!(res[i].events & EPOLLIN) && FD_ISSET(evt->data.fd, &r->root_fds[0])) {
                                           evt->events |= EPOLLIN;
                                           rflg = 42;
                                   }
                                   if (!(res[i].events & EPOLLPRI) && FD_ISSET(evt->data.fd, &r->root_fds[2])) {
                                           evt->events |= EPOLLPRI;
                                           rflg = 42;
                                   }
                                   if (wflg > 1)
                                           evt->events |= EPOLLOUT;
                                   else
                                           FD_CLR(evt->data.fd, &r->root_fds[1]);
                         }                          }
                         if (flg > 1)  
                                 ops = EPOLL_CTL_MOD;  
                 }                  }
   
                   ops = EPOLL_CTL_DEL;
                   if (rflg > 1 || wflg > 1)
                           ops = EPOLL_CTL_MOD;
   
                 if (epoll_ctl(r->root_kq, ops, evt->data.fd, evt) == -1) {                  if (epoll_ctl(r->root_kq, ops, evt->data.fd, evt) == -1) {
                         if (r->root_hooks.hook_exec.exception) {                          if (r->root_hooks.hook_exec.exception) {
                                 r->root_hooks.hook_exec.exception(r, NULL);                                  r->root_hooks.hook_exec.exception(r, NULL);
Line 1163  fetch_hook_epoll_proceed(int en, struct epoll_event *r Line 1233  fetch_hook_epoll_proceed(int en, struct epoll_event *r
 static inline void   static inline void 
 fetch_hook_select_proceed(int en, fd_set rfd, fd_set wfd, fd_set xfd, sched_root_task_t *r)  fetch_hook_select_proceed(int en, fd_set rfd, fd_set wfd, fd_set xfd, sched_root_task_t *r)
 {  {
        register int i, flg;        register int i, rflg, wflg;
        sched_task_t *task, *tmp;        sched_task_t *t, *tmp, *task;
   
         /* skip select check if return value from select is zero */          /* skip select check if return value from select is zero */
         if (!en)          if (!en)
                 return;                  return;
   
         for (i = 0; i < r->root_kq; i++) {          for (i = 0; i < r->root_kq; i++) {
                   if (!FD_ISSET(i, &r->root_fds[0]) && 
                                   !FD_ISSET(i, &r->root_fds[1]) && 
                                   !FD_ISSET(i, &r->root_fds[2]))
                           continue;
   
                   rflg = wflg = 0;
   
                 if (FD_ISSET(i, &rfd) || FD_ISSET(i, &xfd)) {                  if (FD_ISSET(i, &rfd) || FD_ISSET(i, &xfd)) {
                        flg = 0;                        task = NULL;
                        TAILQ_FOREACH_SAFE(task, &r->root_read, task_node, tmp) {                        TAILQ_FOREACH_SAFE(t, &r->root_read, task_node, tmp) {
                                if (TASK_FD(task) != i)                                if (TASK_FD(t) == i) {
                                        continue;                                        if (!task)
                                else {                                                task = t;
                                        flg++;                                        rflg++;
                                        TASK_FLAG(task) = ioctl(TASK_FD(task),  
                                                        FIONREAD, &TASK_RET(task)); 
                                 }                                  }
                           }
   
                           if (task) {
                                   TASK_FLAG(task) = ioctl(TASK_FD(task), FIONREAD, &TASK_RET(task));
   
                                 /* remove read handle */                                  /* remove read handle */
                                 remove_task_from(task, &r->root_read);                                  remove_task_from(task, &r->root_read);
   
Line 1196  fetch_hook_select_proceed(int en, fd_set rfd, fd_set w Line 1276  fetch_hook_select_proceed(int en, fd_set rfd, fd_set w
                                         task->task_type = taskREADY;                                          task->task_type = taskREADY;
                                         insert_task_to(task, &r->root_ready);                                          insert_task_to(task, &r->root_ready);
                                 }                                  }
   
                                   /* remove resouce */
                                   if (rflg == 1) {
                                           FD_CLR(i, &r->root_fds[0]);
                                           FD_CLR(i, &r->root_fds[2]);
                                   }
                         }                          }
                         /* remove resouce */  
                         if (flg)  
                                 FD_CLR(i, &r->root_fds[0]);  
                 }                  }
   
                 if (FD_ISSET(i, &wfd)) {                  if (FD_ISSET(i, &wfd)) {
                        flg = 0;                        task = NULL;
                        TAILQ_FOREACH_SAFE(task, &r->root_write, task_node, tmp) {                        TAILQ_FOREACH_SAFE(t, &r->root_write, task_node, tmp) {
                                if (TASK_FD(task) != i)                                if (TASK_FD(t) == i) {
                                        continue;                                        if (!task)
                                else {                                                task = t;
                                        flg++;                                        wflg++;
                                        TASK_FLAG(task) = ioctl(TASK_FD(task),  
                                                        FIONWRITE, &TASK_RET(task)); 
                                 }                                  }
                           }
   
                           if (task) {
                                   TASK_FLAG(task) = ioctl(TASK_FD(task), FIONWRITE, &TASK_RET(task));
   
                                 /* remove write handle */                                  /* remove write handle */
                                 remove_task_from(task, &r->root_write);                                  remove_task_from(task, &r->root_write);
   
Line 1227  fetch_hook_select_proceed(int en, fd_set rfd, fd_set w Line 1312  fetch_hook_select_proceed(int en, fd_set rfd, fd_set w
                                         task->task_type = taskREADY;                                          task->task_type = taskREADY;
                                         insert_task_to(task, &r->root_ready);                                          insert_task_to(task, &r->root_ready);
                                 }                                  }
   
                                   /* remove resouce */
                                   if (wflg == 1)
                                           FD_CLR(i, &r->root_fds[1]);
                         }                          }
                         /* remove resouce */  
                         if (flg)  
                                 FD_CLR(i, &r->root_fds[1]);  
                 }                  }
         }          }
   
         /* optimize select */          /* optimize select */
        for (i = r->root_kq - 1; i > 2; i--)        for (i = r->root_kq - 1; i >= 0; i--)
                if (FD_ISSET(i, &r->root_fds[0]) || FD_ISSET(i, &r->root_fds[1]))                if (FD_ISSET(i, &r->root_fds[0]) || 
                                 FD_ISSET(i, &r->root_fds[1]) || 
                                 FD_ISSET(i, &r->root_fds[2]))
                         break;                          break;
        if (i > 2)        r->root_kq = i + 1;
                r->root_kq = i + 1; 
 }  }
 #endif  #endif
   
Line 1255  sched_hook_fetch(void *root, void *arg __unused) Line 1342  sched_hook_fetch(void *root, void *arg __unused)
 {  {
         sched_root_task_t *r = root;          sched_root_task_t *r = root;
         sched_task_t *task, *tmp;          sched_task_t *task, *tmp;
        struct timespec now, m, mtmp;        struct timespec now, m, mtmp, *tsmin;
 #if SUP_ENABLE == KQ_SUPPORT  #if SUP_ENABLE == KQ_SUPPORT
         struct kevent res[KQ_EVENTS];          struct kevent res[KQ_EVENTS];
         struct timespec *timeout;          struct timespec *timeout;
Line 1281  sched_hook_fetch(void *root, void *arg __unused) Line 1368  sched_hook_fetch(void *root, void *arg __unused)
                 return task;                  return task;
         }          }
   
           /* if present member of task, set NOWAIT */
           if (!TAILQ_FIRST(&r->root_task)) {
                   /* timer tasks */
 #ifdef TIMER_WITHOUT_SORT  #ifdef TIMER_WITHOUT_SORT
        clock_gettime(CLOCK_MONOTONIC, &now);                clock_gettime(CLOCK_MONOTONIC, &now);
   
        sched_timespecclear(&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 (!sched_timespecisset(&r->root_wait))                        if (!sched_timespecisset(&r->root_wait))
                        r->root_wait = TASK_TS(task);                                r->root_wait = TASK_TS(task);
                else if (sched_timespeccmp(&TASK_TS(task), &r->root_wait, -) < 0)                        else if (sched_timespeccmp(&TASK_TS(task), &r->root_wait, -) < 0)
                        r->root_wait = TASK_TS(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;
                sched_timespecsub(&m, &now, &mtmp);                        sched_timespecsub(&m, &now, &mtmp);
                r->root_wait = mtmp;                        if (mtmp.tv_sec < 0 || mtmp.tv_nsec < 0)
        } else {                                /* don't wait for events. we have ready timer */
                /* set wait INFTIM */                                sched_timespecclear(&r->root_wait);
                sched_timespecinf(&r->root_wait);                        else
        }                                r->root_wait = mtmp;
                 } else {
                         /* set wait INFTIM */
                         sched_timespecinf(&r->root_wait);
                 }
 #else   /* ! TIMER_WITHOUT_SORT */  #else   /* ! TIMER_WITHOUT_SORT */
        if (!TAILQ_FIRST(&r->root_task) && (task = TAILQ_FIRST(&r->root_timer))) {                if ((task = TAILQ_FIRST(&r->root_timer))) {
                clock_gettime(CLOCK_MONOTONIC, &now);                        clock_gettime(CLOCK_MONOTONIC, &now);
   
                m = TASK_TS(task);                        m = TASK_TS(task);
                sched_timespecsub(&m, &now, &mtmp);                        sched_timespecsub(&m, &now, &mtmp);
                r->root_wait = mtmp;                        if (mtmp.tv_sec < 0 || mtmp.tv_nsec < 0)
        } else {                                /* don't wait for events. we have ready timer */
                /* set wait INFTIM */                                sched_timespecclear(&r->root_wait);
                sched_timespecinf(&r->root_wait);                        else
        }                                r->root_wait = mtmp;
                 } else {
                         /* set wait INFTIM */
                         sched_timespecinf(&r->root_wait);
                 }
 #endif  /* TIMER_WITHOUT_SORT */  #endif  /* TIMER_WITHOUT_SORT */
        /* if present member of task, set NOWAIT */        } else  /* no waiting for event, because we have ready task */
        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 (!sched_timespecisinf(&r->root_wait)) {
                 tsmin = sched_timespecmin(&r->root_wait, &r->root_poll);
 #if SUP_ENABLE == KQ_SUPPORT  #if SUP_ENABLE == KQ_SUPPORT
                timeout = &r->root_wait;                timeout = tsmin;
 #elif SUP_ENABLE == EP_SUPPORT  #elif SUP_ENABLE == EP_SUPPORT
                timeout = r->root_wait.tv_sec * 1000 + r->root_wait.tv_nsec / 1000000;                timeout = tsmin->tv_sec * 1000 + tsmin->tv_nsec / 1000000;
 #else  #else
                sched_timespec2val(&r->root_wait, &tv);                sched_timespec2val(tsmin, &tv);
                 timeout = &tv;                  timeout = &tv;
 #endif  /* KQ_SUPPORT */  #endif  /* KQ_SUPPORT */
         } else if (sched_timespecisinf(&r->root_poll))          } else if (sched_timespecisinf(&r->root_poll))
Line 1347  sched_hook_fetch(void *root, void *arg __unused) Line 1445  sched_hook_fetch(void *root, void *arg __unused)
 #elif SUP_ENABLE == EP_SUPPORT  #elif SUP_ENABLE == EP_SUPPORT
         if ((en = epoll_wait(r->root_kq, res, KQ_EVENTS, timeout)) == -1) {          if ((en = epoll_wait(r->root_kq, res, KQ_EVENTS, timeout)) == -1) {
 #else  #else
        rfd = xfd = r->root_fds[0];        xfd = r->root_fds[2];
         rfd = r->root_fds[0];
         wfd = r->root_fds[1];          wfd = r->root_fds[1];
         if ((en = select(r->root_kq, &rfd, &wfd, &xfd, timeout)) == -1) {          if ((en = select(r->root_kq, &rfd, &wfd, &xfd, timeout)) == -1) {
 #endif  /* KQ_SUPPORT */  #endif  /* KQ_SUPPORT */

Removed from v.1.30  
changed lines
  Added in v.1.42


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