Annotation of libaitsched/src/hooks.c, revision 1.42

1.1       misho       1: /*************************************************************************
                      2: * (C) 2011 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
                      3: *  by Michael Pounov <misho@openbsd-bg.org>
                      4: *
                      5: * $Author: misho $
1.42    ! misho       6: * $Id: hooks.c,v 1.41.4.1 2023/08/17 14:13:07 misho Exp $
1.1       misho       7: *
                      8: **************************************************************************
                      9: The ELWIX and AITNET software is distributed under the following
                     10: terms:
                     11: 
                     12: All of the documentation and software included in the ELWIX and AITNET
                     13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
                     14: 
1.40      misho      15: Copyright 2004 - 2023
1.1       misho      16:        by Michael Pounov <misho@elwix.org>.  All rights reserved.
                     17: 
                     18: Redistribution and use in source and binary forms, with or without
                     19: modification, are permitted provided that the following conditions
                     20: are met:
                     21: 1. Redistributions of source code must retain the above copyright
                     22:    notice, this list of conditions and the following disclaimer.
                     23: 2. Redistributions in binary form must reproduce the above copyright
                     24:    notice, this list of conditions and the following disclaimer in the
                     25:    documentation and/or other materials provided with the distribution.
                     26: 3. All advertising materials mentioning features or use of this software
                     27:    must display the following acknowledgement:
                     28: This product includes software developed by Michael Pounov <misho@elwix.org>
                     29: ELWIX - Embedded LightWeight unIX and its contributors.
                     30: 4. Neither the name of AITNET nor the names of its contributors
                     31:    may be used to endorse or promote products derived from this software
                     32:    without specific prior written permission.
                     33: 
                     34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
                     35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     37: ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     44: SUCH DAMAGE.
                     45: */
                     46: #include "global.h"
                     47: #include "hooks.h"
                     48: 
                     49: 
1.28      misho      50: #ifdef HAVE_LIBPTHREAD
                     51: static void *
                     52: _sched_threadWrapper(sched_task_t *t)
                     53: {
                     54:        void *ret = NULL;
                     55:        sched_root_task_t *r;
                     56: 
                     57:        if (!t || !TASK_ROOT(t))
                     58:                pthread_exit(ret);
                     59:        else
                     60:                r = (sched_root_task_t*) TASK_ROOT(t);
                     61: 
                     62:        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
                     63:        /*
                     64:        pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
                     65:        */
                     66: 
                     67:        /* notify parent, thread is ready for execution */
                     68:        pthread_testcancel();
                     69: 
                     70:        ret = schedCall(t);
                     71:        r->root_ret = ret;
                     72: 
                     73:        if (TASK_VAL(t)) {
                     74:                transit_task2unuse(t, &r->root_thread);
                     75:                TASK_VAL(t) = 0;
                     76:        }
                     77: 
                     78:        pthread_exit(ret);
                     79: }
                     80: #endif
                     81: 
1.29      misho      82: #if defined(HAVE_LIBRT) && defined(HAVE_TIMER_CREATE) && \
                     83:        defined(HAVE_TIMER_SETTIME) && defined(HAVE_TIMER_DELETE)
1.28      misho      84: #if SUP_ENABLE == KQ_SUPPORT
                     85: static void *
                     86: _sched_rtcWrapper(sched_task_t *t)
                     87: {
                     88:        sched_task_t *task;
                     89:        void *ret;
                     90: 
                     91:        if (!t || !TASK_ROOT(t) || !TASK_DATA(t))
                     92:                return NULL;
                     93:        else {
                     94:                task = (sched_task_t*) TASK_DATA(t);
                     95:                timer_delete((timer_t) TASK_DATLEN(t));
                     96:        }
                     97: 
                     98:        ret = schedCall(task);
                     99: 
                    100:        transit_task2unuse(task, &(TASK_ROOT(task))->root_rtc);
                    101:        return ret;
                    102: }
                    103: #else
                    104: static void
                    105: _sched_rtcSigWrapper(int sig, siginfo_t *si, void *uc)
                    106: {
                    107:        sched_task_t *task;
                    108: 
                    109:        if (si && si->si_value.sival_ptr) {
                    110:                task = (sched_task_t*) si->si_value.sival_ptr;
                    111:                timer_delete((timer_t) TASK_FLAG(task));
                    112: 
                    113:                TASK_RET(task) = (intptr_t) schedCall(task);
                    114: 
                    115:                transit_task2unuse(task, &(TASK_ROOT(task))->root_rtc);
                    116:        }
                    117: }
                    118: #endif
                    119: #endif
                    120: 
1.1       misho     121: /*
                    122:  * sched_hook_init() - Default INIT hook
1.5       misho     123:  *
1.1       misho     124:  * @root = root task
1.6       misho     125:  * @arg = unused
1.1       misho     126:  * return: <0 errors and 0 ok
                    127:  */
                    128: void *
1.6       misho     129: sched_hook_init(void *root, void *arg __unused)
1.1       misho     130: {
                    131:        sched_root_task_t *r = root;
                    132: 
1.6       misho     133:        if (!r)
1.1       misho     134:                return (void*) -1;
                    135: 
1.28      misho     136: #if SUP_ENABLE == KQ_SUPPORT
1.1       misho     137:        r->root_kq = kqueue();
                    138:        if (r->root_kq == -1) {
                    139:                LOGERR;
                    140:                return (void*) -1;
                    141:        }
1.28      misho     142: #elif SUP_ENABLE == EP_SUPPORT
                    143:        r->root_kq = epoll_create(KQ_EVENTS);
                    144:        if (r->root_kq == -1) {
                    145:                LOGERR;
                    146:                return (void*) -1;
                    147:        }
1.25      misho     148: #else
                    149:        r->root_kq ^= r->root_kq;
1.38      misho     150: #endif
                    151: 
1.25      misho     152:        FD_ZERO(&r->root_fds[0]);
                    153:        FD_ZERO(&r->root_fds[1]);
1.38      misho     154:        FD_ZERO(&r->root_fds[2]);
1.1       misho     155: 
                    156:        return NULL;
                    157: }
                    158: 
                    159: /*
                    160:  * sched_hook_fini() - Default FINI hook
1.5       misho     161:  *
1.1       misho     162:  * @root = root task
                    163:  * @arg = unused
                    164:  * return: <0 errors and 0 ok
                    165:  */
                    166: void *
                    167: sched_hook_fini(void *root, void *arg __unused)
                    168: {
                    169:        sched_root_task_t *r = root;
                    170: 
                    171:        if (!r)
                    172:                return (void*) -1;
                    173: 
1.28      misho     174: #if SUP_ENABLE == KQ_SUPPORT || SUP_ENABLE == EP_SUPPORT
1.1       misho     175:        if (r->root_kq > 2) {
                    176:                close(r->root_kq);
                    177:                r->root_kq = 0;
                    178:        }
1.25      misho     179: #else
1.38      misho     180:        r->root_kq ^= r->root_kq;
                    181: #endif
                    182: 
                    183:        FD_ZERO(&r->root_fds[2]);
1.25      misho     184:        FD_ZERO(&r->root_fds[1]);
                    185:        FD_ZERO(&r->root_fds[0]);
1.1       misho     186: 
                    187:        return NULL;
                    188: }
                    189: 
                    190: /*
                    191:  * sched_hook_cancel() - Default CANCEL hook
1.5       misho     192:  *
1.1       misho     193:  * @task = current task
                    194:  * @arg = unused
                    195:  * return: <0 errors and 0 ok
                    196:  */
                    197: void *
                    198: sched_hook_cancel(void *task, void *arg __unused)
                    199: {
1.28      misho     200:        sched_task_t *t = task, *tmp, *tt;
                    201:        sched_root_task_t *r = NULL;
1.37      misho     202:        int flg = 0;
1.28      misho     203: #if SUP_ENABLE == KQ_SUPPORT
1.1       misho     204:        struct kevent chg[1];
1.2       misho     205:        struct timespec timeout = { 0, 0 };
1.28      misho     206: #elif SUP_ENABLE == EP_SUPPORT
1.39      misho     207:        struct epoll_event ee = { .events = 0, .data.u64 = 0l };
1.25      misho     208: #else
                    209:        register int i;
                    210: #endif
1.11      misho     211: #ifdef AIO_SUPPORT
                    212:        struct aiocb *acb;
                    213: #ifdef EVFILT_LIO
1.15      misho     214:        register int i = 0;
1.11      misho     215:        struct aiocb **acbs;
                    216: #endif /* EVFILT_LIO */
                    217: #endif /* AIO_SUPPORT */
1.1       misho     218: 
1.6       misho     219:        if (!t || !TASK_ROOT(t))
1.1       misho     220:                return (void*) -1;
1.28      misho     221:        else
                    222:                r = TASK_ROOT(t);
1.1       misho     223: 
1.4       misho     224:        switch (TASK_TYPE(t)) {
1.1       misho     225:                case taskREAD:
1.28      misho     226:                        /* check for multi subscribers */
                    227:                        TAILQ_FOREACH_SAFE(tt, &r->root_read, task_node, tmp)
1.37      misho     228:                                if (TASK_FD(tt) == TASK_FD(t))
1.28      misho     229:                                        flg++;
                    230: #if SUP_ENABLE == KQ_SUPPORT
1.2       misho     231: #ifdef __NetBSD__
1.28      misho     232:                        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, flg < 2 ? EV_DELETE : 0, 
                    233:                                        0, 0, (intptr_t) TASK_FD(t));
1.2       misho     234: #else
1.28      misho     235:                        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, flg < 2 ? EV_DELETE : 0, 
                    236:                                        0, 0, (void*) TASK_FD(t));
1.2       misho     237: #endif
1.28      misho     238: #elif SUP_ENABLE == EP_SUPPORT
                    239:                        ee.data.fd = TASK_FD(t);
1.32      misho     240:                        ee.events ^= ee.events;
1.28      misho     241:                        if (FD_ISSET(TASK_FD(t), &r->root_fds[1]))
1.38      misho     242:                                ee.events |= EPOLLOUT;
1.28      misho     243: 
1.38      misho     244:                        if (flg < 2) {
1.28      misho     245:                                FD_CLR(TASK_FD(t), &r->root_fds[0]);
1.38      misho     246:                                FD_CLR(TASK_FD(t), &r->root_fds[2]);
                    247:                        } else {
                    248:                                if (FD_ISSET(TASK_FD(t), &r->root_fds[0]))
                    249:                                        ee.events |= EPOLLIN;
                    250:                                if (FD_ISSET(TASK_FD(t), &r->root_fds[2]))
                    251:                                        ee.events |= EPOLLPRI;
                    252:                        }
1.28      misho     253: #else
                    254:                        if (flg < 2) {
                    255:                                FD_CLR(TASK_FD(t), &r->root_fds[0]);
1.38      misho     256:                                FD_CLR(TASK_FD(t), &r->root_fds[2]);
1.28      misho     257: 
                    258:                                /* optimize select */
1.37      misho     259:                                for (i = r->root_kq - 1; i >= 0; i--)
1.38      misho     260:                                        if (FD_ISSET(i, &r->root_fds[0]) || 
                    261:                                                        FD_ISSET(i, &r->root_fds[1]) || 
                    262:                                                        FD_ISSET(i, &r->root_fds[2]))
1.28      misho     263:                                                break;
1.37      misho     264:                                r->root_kq = i + 1;
1.28      misho     265:                        }
1.25      misho     266: #endif
1.1       misho     267:                        break;
                    268:                case taskWRITE:
1.28      misho     269:                        /* check for multi subscribers */
                    270:                        TAILQ_FOREACH_SAFE(tt, &r->root_write, task_node, tmp)
1.37      misho     271:                                if (TASK_FD(tt) == TASK_FD(t))
1.28      misho     272:                                        flg++;
                    273: #if SUP_ENABLE == KQ_SUPPORT
1.2       misho     274: #ifdef __NetBSD__
1.28      misho     275:                        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, flg < 2 ? EV_DELETE : 0, 
                    276:                                        0, 0, (intptr_t) TASK_FD(t));
1.2       misho     277: #else
1.28      misho     278:                        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, flg < 2 ? EV_DELETE : 0, 
                    279:                                        0, 0, (void*) TASK_FD(t));
1.2       misho     280: #endif
1.28      misho     281: #elif SUP_ENABLE == EP_SUPPORT
                    282:                        ee.data.fd = TASK_FD(t);
1.32      misho     283:                        ee.events ^= ee.events;
1.28      misho     284:                        if (FD_ISSET(TASK_FD(t), &r->root_fds[0]))
1.38      misho     285:                                ee.events |= EPOLLIN;
                    286:                        if (FD_ISSET(TASK_FD(t), &r->root_fds[2]))
                    287:                                ee.events |= EPOLLPRI;
1.28      misho     288: 
                    289:                        if (flg < 2)
                    290:                                FD_CLR(TASK_FD(t), &r->root_fds[1]);
                    291:                        else
                    292:                                ee.events |= EPOLLOUT;
                    293: #else
                    294:                        if (flg < 2) {
                    295:                                FD_CLR(TASK_FD(t), &r->root_fds[1]);
                    296: 
                    297:                                /* optimize select */
1.37      misho     298:                                for (i = r->root_kq - 1; i >= 0; i--)
1.38      misho     299:                                        if (FD_ISSET(i, &r->root_fds[0]) || 
                    300:                                                        FD_ISSET(i, &r->root_fds[1]) || 
                    301:                                                        FD_ISSET(i, &r->root_fds[2]))
1.28      misho     302:                                                break;
1.37      misho     303:                                r->root_kq = i + 1;
1.28      misho     304:                        }
1.25      misho     305: #endif
1.1       misho     306:                        break;
1.7       misho     307:                case taskALARM:
1.28      misho     308: #if SUP_ENABLE == KQ_SUPPORT
                    309:                        /* check for multi subscribers */
                    310:                        TAILQ_FOREACH_SAFE(tt, &r->root_alarm, task_node, tmp)
1.37      misho     311:                                if (TASK_DATA(tt) == TASK_DATA(t))
1.28      misho     312:                                        flg++;
1.7       misho     313: #ifdef __NetBSD__
1.28      misho     314:                        EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, flg < 2 ? EV_DELETE : 0, 
1.7       misho     315:                                        0, 0, (intptr_t) TASK_DATA(t));
                    316: #else
1.28      misho     317:                        EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, flg < 2 ? EV_DELETE : 0, 
1.7       misho     318:                                        0, 0, (void*) TASK_DATA(t));
                    319: #endif
1.25      misho     320: #endif
1.8       misho     321:                        break;
                    322:                case taskNODE:
1.28      misho     323: #if SUP_ENABLE == KQ_SUPPORT
                    324:                        /* check for multi subscribers */
                    325:                        TAILQ_FOREACH_SAFE(tt, &r->root_node, task_node, tmp)
1.37      misho     326:                                if (TASK_FD(tt) == TASK_FD(t))
1.28      misho     327:                                        flg++;
1.8       misho     328: #ifdef __NetBSD__
1.28      misho     329:                        EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, flg < 2 ? EV_DELETE : 0, 
                    330:                                        0, 0, (intptr_t) TASK_FD(t));
1.8       misho     331: #else
1.28      misho     332:                        EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, flg < 2 ? EV_DELETE : 0, 
                    333:                                        0, 0, (void*) TASK_FD(t));
1.8       misho     334: #endif
1.25      misho     335: #endif
1.8       misho     336:                        break;
                    337:                case taskPROC:
1.28      misho     338: #if SUP_ENABLE == KQ_SUPPORT
                    339:                        /* check for multi subscribers */
                    340:                        TAILQ_FOREACH_SAFE(tt, &r->root_proc, task_node, tmp)
1.37      misho     341:                                if (TASK_VAL(tt) == TASK_VAL(t))
1.28      misho     342:                                        flg++;
1.8       misho     343: #ifdef __NetBSD__
1.28      misho     344:                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, flg < 2 ? EV_DELETE : 0, 
                    345:                                        0, 0, (intptr_t) TASK_VAL(t));
1.8       misho     346: #else
1.28      misho     347:                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, flg < 2 ? EV_DELETE : 0, 
                    348:                                        0, 0, (void*) TASK_VAL(t));
1.8       misho     349: #endif
1.25      misho     350: #endif
1.8       misho     351:                        break;
                    352:                case taskSIGNAL:
1.28      misho     353:                        /* check for multi subscribers */
                    354:                        TAILQ_FOREACH_SAFE(tt, &r->root_signal, task_node, tmp)
1.37      misho     355:                                if (TASK_VAL(tt) == TASK_VAL(t))
1.28      misho     356:                                        flg++;
1.40      misho     357: #if SUP_ENABLE == KQ_SUPPORT
1.8       misho     358: #ifdef __NetBSD__
1.28      misho     359:                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, flg < 2 ? EV_DELETE : 0, 
                    360:                                        0, 0, (intptr_t) TASK_VAL(t));
1.8       misho     361: #else
1.28      misho     362:                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, flg < 2 ? EV_DELETE : 0, 
                    363:                                        0, 0, (void*) TASK_VAL(t));
1.8       misho     364: #endif
1.41      misho     365: #endif
1.40      misho     366:                        if (flg < 2) {
                    367:                                pthread_mutex_lock(&TASK_ROOT(t)->root_sigmtx);
                    368:                                sigdelset(&TASK_ROOT(t)->root_sigset, TASK_VAL(t));
                    369:                                pthread_mutex_unlock(&TASK_ROOT(t)->root_sigmtx);
                    370:                        }
1.8       misho     371:                        break;
1.11      misho     372: #ifdef AIO_SUPPORT
                    373:                case taskAIO:
1.28      misho     374: #if SUP_ENABLE == KQ_SUPPORT
                    375:                        /* check for multi subscribers */
                    376:                        TAILQ_FOREACH_SAFE(tt, &r->root_aio, task_node, tmp)
1.37      misho     377:                                if (TASK_VAL(tt) == TASK_VAL(t))
1.28      misho     378:                                        flg++;
1.11      misho     379: #ifdef __NetBSD__
1.28      misho     380:                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_AIO, flg < 2 ? EV_DELETE : 0, 
                    381:                                        0, 0, (intptr_t) TASK_VAL(t));
1.11      misho     382: #else
1.28      misho     383:                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_AIO, flg < 2 ? EV_DELETE : 0, 
                    384:                                        0, 0, (void*) TASK_VAL(t));
1.11      misho     385: #endif
                    386:                        acb = (struct aiocb*) TASK_VAL(t);
                    387:                        if (acb) {
                    388:                                if (aio_cancel(acb->aio_fildes, acb) == AIO_CANCELED)
                    389:                                        aio_return(acb);
1.37      misho     390:                                e_free(acb);
1.11      misho     391:                                TASK_VAL(t) = 0;
                    392:                        }
1.25      misho     393: #endif
1.11      misho     394:                        break;
                    395: #ifdef EVFILT_LIO
                    396:                case taskLIO:
1.28      misho     397: #if SUP_ENABLE == KQ_SUPPORT
                    398:                        /* check for multi subscribers */
                    399:                        TAILQ_FOREACH_SAFE(tt, &r->root_lio, task_node, tmp)
1.37      misho     400:                                if (TASK_VAL(tt) == TASK_VAL(t))
1.28      misho     401:                                        flg++;
1.11      misho     402: #ifdef __NetBSD__
1.28      misho     403:                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_LIO, flg < 2 ? EV_DELETE : 0, 
                    404:                                        0, 0, (intptr_t) TASK_VAL(t));
1.11      misho     405: #else
1.28      misho     406:                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_LIO, flg < 2 ? EV_DELETE : 0, 
                    407:                                        0, 0, (void*) TASK_VAL(t));
1.11      misho     408: #endif
                    409:                        acbs = (struct aiocb**) TASK_VAL(t);
                    410:                        if (acbs) {
                    411:                                for (i = 0; i < TASK_DATLEN(t); i++) {
                    412:                                        if (aio_cancel(acbs[i]->aio_fildes, acbs[i]) == AIO_CANCELED)
                    413:                                                aio_return(acbs[i]);
1.37      misho     414:                                        e_free(acbs[i]);
1.11      misho     415:                                }
1.37      misho     416:                                e_free(acbs);
1.11      misho     417:                                TASK_VAL(t) = 0;
                    418:                        }
1.25      misho     419: #endif
1.11      misho     420:                        break;
                    421: #endif /* EVFILT_LIO */
                    422: #endif /* AIO_SUPPORT */
1.8       misho     423: #ifdef EVFILT_USER
                    424:                case taskUSER:
1.28      misho     425: #if SUP_ENABLE == KQ_SUPPORT
                    426:                        /* check for multi subscribers */
                    427:                        TAILQ_FOREACH_SAFE(tt, &r->root_user, task_node, tmp)
1.37      misho     428:                                if (TASK_VAL(tt) == TASK_VAL(t))
1.28      misho     429:                                        flg++;
1.8       misho     430: #ifdef __NetBSD__
1.28      misho     431:                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, flg < 2 ? EV_DELETE : 0, 
                    432:                                        0, 0, (intptr_t) TASK_VAL(t));
1.8       misho     433: #else
1.28      misho     434:                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, flg < 2 ? EV_DELETE : 0, 
                    435:                                        0, 0, (void*) TASK_VAL(t));
1.8       misho     436: #endif
1.25      misho     437: #endif
1.10      misho     438:                        break;
1.19      misho     439: #endif /* EVFILT_USER */
1.14      misho     440:                case taskTHREAD:
                    441: #ifdef HAVE_LIBPTHREAD
1.28      misho     442:                        if (TASK_VAL(t)) {
                    443:                                pthread_cancel((pthread_t) TASK_VAL(t));
                    444:                                pthread_join((pthread_t) TASK_VAL(t), NULL);
                    445:                                if (TASK_VAL(t)) {
                    446:                                        transit_task2unuse(t, &(TASK_ROOT(t))->root_thread);
                    447:                                        TASK_VAL(t) = 0;
                    448:                                }
                    449:                        }
1.14      misho     450: #endif
1.19      misho     451:                        return NULL;
1.29      misho     452: #if defined(HAVE_LIBRT) && defined(HAVE_TIMER_CREATE) && \
                    453:        defined(HAVE_TIMER_SETTIME) && defined(HAVE_TIMER_DELETE)
1.19      misho     454:                case taskRTC:
                    455:                        timer_delete((timer_t) TASK_FLAG(t));
1.28      misho     456: #if SUP_ENABLE == KQ_SUPPORT
1.19      misho     457:                        schedCancel((sched_task_t*) TASK_RET(t));
1.28      misho     458: #else
                    459:                        /* check for multi subscribers */
                    460:                        TAILQ_FOREACH_SAFE(tt, &r->root_rtc, task_node, tmp)
1.37      misho     461:                                if (TASK_DATA(tt) == TASK_DATA(t))
1.28      misho     462:                                        flg++;
                    463: 
                    464:                        /* restore signal */
                    465:                        if (flg < 2)
                    466:                                signal((intptr_t) TASK_DATA(t) + SIGRTMIN, SIG_DFL);
                    467: #endif
1.19      misho     468:                        return NULL;
                    469: #endif /* HAVE_TIMER_CREATE */
1.1       misho     470:                default:
1.8       misho     471:                        return NULL;
1.1       misho     472:        }
                    473: 
1.28      misho     474: #if SUP_ENABLE == KQ_SUPPORT
                    475:        kevent(r->root_kq, chg, 1, NULL, 0, &timeout);
                    476: #elif SUP_ENABLE == EP_SUPPORT
1.37      misho     477:        if (TASK_TYPE(t) == taskREAD || TASK_TYPE(t) == taskWRITE) {
                    478:                epoll_ctl(r->root_kq, ee.events ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, ee.data.fd, &ee);
                    479:        }
1.25      misho     480: #endif
1.1       misho     481:        return NULL;
                    482: }
                    483: 
1.14      misho     484: #ifdef HAVE_LIBPTHREAD
                    485: /*
                    486:  * sched_hook_thread() - Default THREAD hook
                    487:  *
                    488:  * @task = current task
                    489:  * @arg = pthread attributes
                    490:  * return: <0 errors and 0 ok
                    491:  */
                    492: void *
                    493: sched_hook_thread(void *task, void *arg)
                    494: {
                    495:        sched_task_t *t = task;
                    496:        pthread_t tid;
1.15      misho     497:        sigset_t s, o;
1.14      misho     498: 
                    499:        if (!t || !TASK_ROOT(t))
                    500:                return (void*) -1;
                    501: 
1.15      misho     502:        sigfillset(&s);
                    503:        pthread_sigmask(SIG_BLOCK, &s, &o);
1.28      misho     504:        errno = pthread_create(&tid, (pthread_attr_t*) arg, 
                    505:                        (void *(*)(void*)) _sched_threadWrapper, t);
                    506:        pthread_sigmask(SIG_SETMASK, &o, NULL);
                    507: 
                    508:        if (errno) {
1.14      misho     509:                LOGERR;
                    510:                return (void*) -1;
1.15      misho     511:        } else
                    512:                TASK_VAL(t) = (u_long) tid;
1.14      misho     513: 
                    514:        if (!TASK_ISLOCKED(t))
                    515:                TASK_LOCK(t);
                    516: 
                    517:        return NULL;
                    518: }
                    519: #endif
                    520: 
1.1       misho     521: /*
                    522:  * sched_hook_read() - Default READ hook
1.5       misho     523:  *
1.1       misho     524:  * @task = current task
                    525:  * @arg = unused
                    526:  * return: <0 errors and 0 ok
                    527:  */
                    528: void *
1.38      misho     529: sched_hook_read(void *task, void *arg)
1.1       misho     530: {
                    531:        sched_task_t *t = task;
1.28      misho     532:        sched_root_task_t *r = NULL;
1.38      misho     533:        uintptr_t mask = (uintptr_t) arg;
1.28      misho     534: #if SUP_ENABLE == KQ_SUPPORT
1.1       misho     535:        struct kevent chg[1];
1.2       misho     536:        struct timespec timeout = { 0, 0 };
1.28      misho     537: #elif SUP_ENABLE == EP_SUPPORT
1.39      misho     538:        struct epoll_event ee = { 0 };
1.28      misho     539:        int flg = 0;
1.25      misho     540: #endif
1.1       misho     541: 
1.6       misho     542:        if (!t || !TASK_ROOT(t))
1.1       misho     543:                return (void*) -1;
1.28      misho     544:        else
                    545:                r = TASK_ROOT(t);
1.1       misho     546: 
1.28      misho     547: #if SUP_ENABLE == KQ_SUPPORT
1.2       misho     548: #ifdef __NetBSD__
1.38      misho     549:        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD | EV_CLEAR | mask, 
                    550:                        0, 0, (intptr_t) TASK_FD(t));
1.2       misho     551: #else
1.38      misho     552:        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD | EV_CLEAR | mask, 
                    553:                        0, 0, (void*) TASK_FD(t));
1.2       misho     554: #endif
1.28      misho     555:        if (kevent(r->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                    556:                if (r->root_hooks.hook_exec.exception)
                    557:                        r->root_hooks.hook_exec.exception(r, NULL);
1.3       misho     558:                else
                    559:                        LOGERR;
1.1       misho     560:                return (void*) -1;
                    561:        }
1.28      misho     562: #elif SUP_ENABLE == EP_SUPPORT
1.38      misho     563:        if (!mask)
                    564:                mask = EPOLLIN | EPOLLPRI;
1.32      misho     565:        ee.data.fd = TASK_FD(t);
1.38      misho     566:        ee.events = mask;
                    567:        if (FD_ISSET(TASK_FD(t), &r->root_fds[2])) {
                    568:                flg |= 4;
                    569:                ee.events |= EPOLLPRI;
                    570:        }
                    571:        if (FD_ISSET(TASK_FD(t), &r->root_fds[0])) {
1.28      misho     572:                flg |= 1;
1.38      misho     573:                ee.events |= EPOLLIN;
                    574:        }
1.28      misho     575:        if (FD_ISSET(TASK_FD(t), &r->root_fds[1])) {
                    576:                flg |= 2;
                    577:                ee.events |= EPOLLOUT;
                    578:        }
                    579: 
                    580:        if (epoll_ctl(r->root_kq, flg ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, TASK_FD(t), &ee) == -1) {
                    581:                if (r->root_hooks.hook_exec.exception)
                    582:                        r->root_hooks.hook_exec.exception(r, NULL);
                    583:                else
                    584:                        LOGERR;
                    585:                return (void*) -1;
1.38      misho     586:        } else {
                    587:                if (mask & EPOLLIN)
                    588:                        FD_SET(TASK_FD(t), &r->root_fds[0]);
                    589:                if (mask & EPOLLPRI)
                    590:                        FD_SET(TASK_FD(t), &r->root_fds[2]);
                    591:        }
                    592: #else
                    593:        if (!mask) {
1.28      misho     594:                FD_SET(TASK_FD(t), &r->root_fds[0]);
1.38      misho     595:                FD_SET(TASK_FD(t), &r->root_fds[2]);
                    596:        } else {
                    597:                if (mask & 1)
                    598:                        FD_SET(TASK_FD(t), &r->root_fds[0]);
                    599:                if (mask & 2)
                    600:                        FD_SET(TASK_FD(t), &r->root_fds[2]);
                    601:        }
                    602: 
1.25      misho     603:        if (TASK_FD(t) >= r->root_kq)
                    604:                r->root_kq = TASK_FD(t) + 1;
                    605: #endif
1.1       misho     606: 
                    607:        return NULL;
                    608: }
                    609: 
                    610: /*
                    611:  * sched_hook_write() - Default WRITE hook
1.5       misho     612:  *
1.1       misho     613:  * @task = current task
                    614:  * @arg = unused
                    615:  * return: <0 errors and 0 ok
                    616:  */
                    617: void *
1.38      misho     618: sched_hook_write(void *task, void *arg)
1.1       misho     619: {
                    620:        sched_task_t *t = task;
1.28      misho     621:        sched_root_task_t *r = NULL;
1.38      misho     622:        uintptr_t mask = (uintptr_t) arg;
1.28      misho     623: #if SUP_ENABLE == KQ_SUPPORT
1.1       misho     624:        struct kevent chg[1];
1.2       misho     625:        struct timespec timeout = { 0, 0 };
1.28      misho     626: #elif SUP_ENABLE == EP_SUPPORT
1.39      misho     627:        struct epoll_event ee = { 0 };
1.28      misho     628:        int flg = 0;
1.25      misho     629: #endif
1.1       misho     630: 
1.6       misho     631:        if (!t || !TASK_ROOT(t))
1.1       misho     632:                return (void*) -1;
1.28      misho     633:        else
                    634:                r = TASK_ROOT(t);
1.1       misho     635: 
1.28      misho     636: #if SUP_ENABLE == KQ_SUPPORT
1.2       misho     637: #ifdef __NetBSD__
1.38      misho     638:        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD | EV_CLEAR | mask, 
                    639:                        0, 0, (intptr_t) TASK_FD(t));
1.2       misho     640: #else
1.38      misho     641:        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD | EV_CLEAR | mask, 
                    642:                        0, 0, (void*) TASK_FD(t));
1.2       misho     643: #endif
1.28      misho     644:        if (kevent(r->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                    645:                if (r->root_hooks.hook_exec.exception)
                    646:                        r->root_hooks.hook_exec.exception(r, NULL);
1.3       misho     647:                else
                    648:                        LOGERR;
1.1       misho     649:                return (void*) -1;
                    650:        }
1.28      misho     651: #elif SUP_ENABLE == EP_SUPPORT
1.38      misho     652:        if (!mask)
                    653:                mask = EPOLLOUT;
1.32      misho     654:        ee.data.fd = TASK_FD(t);
1.38      misho     655:        ee.events = mask;
1.32      misho     656: 
1.38      misho     657:        if (FD_ISSET(TASK_FD(t), &r->root_fds[2])) {
                    658:                flg |= 4;
                    659:                ee.events |= EPOLLPRI;
                    660:        }
1.28      misho     661:        if (FD_ISSET(TASK_FD(t), &r->root_fds[0])) {
                    662:                flg |= 1;
1.38      misho     663:                ee.events |= EPOLLIN;
1.28      misho     664:        }
1.37      misho     665:        if (FD_ISSET(TASK_FD(t), &r->root_fds[1])) {
1.28      misho     666:                flg |= 2;
1.38      misho     667:                ee.events |= EPOLLOUT;
1.37      misho     668:        }
1.28      misho     669: 
                    670:        if (epoll_ctl(r->root_kq, flg ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, TASK_FD(t), &ee) == -1) {
                    671:                if (r->root_hooks.hook_exec.exception)
                    672:                        r->root_hooks.hook_exec.exception(r, NULL);
                    673:                else
                    674:                        LOGERR;
                    675:                return (void*) -1;
                    676:        } else
1.38      misho     677:                if (mask & EPOLLOUT)
                    678:                        FD_SET(TASK_FD(t), &r->root_fds[1]);
                    679: #else
                    680:        if (!mask)
1.28      misho     681:                FD_SET(TASK_FD(t), &r->root_fds[1]);
1.38      misho     682:        else
                    683:                if (mask & 1)
                    684:                        FD_SET(TASK_FD(t), &r->root_fds[1]);
                    685: 
1.25      misho     686:        if (TASK_FD(t) >= r->root_kq)
                    687:                r->root_kq = TASK_FD(t) + 1;
                    688: #endif
1.1       misho     689: 
                    690:        return NULL;
                    691: }
                    692: 
                    693: /*
1.7       misho     694:  * sched_hook_alarm() - Default ALARM hook
                    695:  *
                    696:  * @task = current task
                    697:  * @arg = unused
                    698:  * return: <0 errors and 0 ok
                    699:  */
                    700: void *
                    701: sched_hook_alarm(void *task, void *arg __unused)
                    702: {
1.28      misho     703: #if SUP_ENABLE == KQ_SUPPORT
1.7       misho     704:        sched_task_t *t = task;
                    705:        struct kevent chg[1];
                    706:        struct timespec timeout = { 0, 0 };
                    707: 
                    708:        if (!t || !TASK_ROOT(t))
                    709:                return (void*) -1;
                    710: 
                    711: #ifdef __NetBSD__
1.19      misho     712:        EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_ADD | EV_CLEAR, 0, 
1.7       misho     713:                        t->task_val.ts.tv_sec * 1000 + t->task_val.ts.tv_nsec / 1000000, 
                    714:                        (intptr_t) TASK_DATA(t));
                    715: #else
1.19      misho     716:        EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_ADD | EV_CLEAR, 0, 
1.7       misho     717:                        t->task_val.ts.tv_sec * 1000 + t->task_val.ts.tv_nsec / 1000000, 
                    718:                        (void*) TASK_DATA(t));
                    719: #endif
                    720:        if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                    721:                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                    722:                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
                    723:                else
                    724:                        LOGERR;
                    725:                return (void*) -1;
                    726:        }
                    727: 
1.25      misho     728: #endif
1.7       misho     729:        return NULL;
                    730: }
                    731: 
                    732: /*
1.8       misho     733:  * sched_hook_node() - Default NODE hook
                    734:  *
                    735:  * @task = current task
1.34      misho     736:  * @arg = if arg == 42 then waiting for all events
1.8       misho     737:  * return: <0 errors and 0 ok
                    738:  */
                    739: void *
1.34      misho     740: sched_hook_node(void *task, void *arg)
1.8       misho     741: {
1.28      misho     742: #if SUP_ENABLE == KQ_SUPPORT
1.8       misho     743:        sched_task_t *t = task;
                    744:        struct kevent chg[1];
                    745:        struct timespec timeout = { 0, 0 };
1.35      misho     746:        u_int addflags = (u_int) (uintptr_t) arg;
1.8       misho     747: 
                    748:        if (!t || !TASK_ROOT(t))
                    749:                return (void*) -1;
                    750: 
                    751: #ifdef __NetBSD__
                    752:        EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_ADD | EV_CLEAR, 
                    753:                        NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | 
1.34      misho     754:                        NOTE_LINK | NOTE_RENAME | NOTE_REVOKE | addflags, 0, (intptr_t) TASK_FD(t));
1.8       misho     755: #else
                    756:        EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_ADD | EV_CLEAR, 
                    757:                        NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | 
1.34      misho     758:                        NOTE_LINK | NOTE_RENAME | NOTE_REVOKE | addflags, 0, (void*) TASK_FD(t));
1.8       misho     759: #endif
                    760:        if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                    761:                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                    762:                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
                    763:                else
                    764:                        LOGERR;
                    765:                return (void*) -1;
                    766:        }
                    767: 
1.25      misho     768: #endif
1.8       misho     769:        return NULL;
                    770: }
                    771: 
                    772: /*
                    773:  * sched_hook_proc() - Default PROC hook
                    774:  *
                    775:  * @task = current task
                    776:  * @arg = unused
                    777:  * return: <0 errors and 0 ok
                    778:  */
                    779: void *
                    780: sched_hook_proc(void *task, void *arg __unused)
                    781: {
1.28      misho     782: #if SUP_ENABLE == KQ_SUPPORT
1.8       misho     783:        sched_task_t *t = task;
                    784:        struct kevent chg[1];
                    785:        struct timespec timeout = { 0, 0 };
                    786: 
                    787:        if (!t || !TASK_ROOT(t))
                    788:                return (void*) -1;
                    789: 
                    790: #ifdef __NetBSD__
                    791:        EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_ADD | EV_CLEAR, 
                    792:                        NOTE_EXIT | NOTE_FORK | NOTE_EXEC | NOTE_TRACK, 0, (intptr_t) TASK_VAL(t));
                    793: #else
                    794:        EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_ADD | EV_CLEAR, 
                    795:                        NOTE_EXIT | NOTE_FORK | NOTE_EXEC | NOTE_TRACK, 0, (void*) TASK_VAL(t));
                    796: #endif
                    797:        if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                    798:                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                    799:                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
                    800:                else
                    801:                        LOGERR;
                    802:                return (void*) -1;
                    803:        }
                    804: 
1.25      misho     805: #endif
1.8       misho     806:        return NULL;
                    807: }
                    808: 
                    809: /*
                    810:  * sched_hook_signal() - Default SIGNAL hook
                    811:  *
                    812:  * @task = current task
                    813:  * @arg = unused
                    814:  * return: <0 errors and 0 ok
                    815:  */
                    816: void *
                    817: sched_hook_signal(void *task, void *arg __unused)
                    818: {
1.40      misho     819:        sched_task_t *t = task;
1.28      misho     820: #if SUP_ENABLE == KQ_SUPPORT
1.8       misho     821:        struct kevent chg[1];
                    822:        struct timespec timeout = { 0, 0 };
1.41      misho     823: #endif
1.8       misho     824: 
                    825:        if (!t || !TASK_ROOT(t))
                    826:                return (void*) -1;
                    827: 
1.41      misho     828: #if SUP_ENABLE == KQ_SUPPORT
1.8       misho     829: #ifdef __NetBSD__
1.19      misho     830:        EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_ADD | EV_CLEAR, 0, 0, (intptr_t) TASK_VAL(t));
1.8       misho     831: #else
1.19      misho     832:        EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_ADD | EV_CLEAR, 0, 0, (void*) TASK_VAL(t));
1.8       misho     833: #endif
                    834:        if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                    835:                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                    836:                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
                    837:                else
                    838:                        LOGERR;
                    839:                return (void*) -1;
                    840:        }
1.41      misho     841: #endif
                    842: 
1.40      misho     843:        pthread_mutex_lock(&TASK_ROOT(t)->root_sigmtx);
                    844:        sigaddset(&TASK_ROOT(t)->root_sigset, TASK_VAL(t));
                    845:        pthread_mutex_unlock(&TASK_ROOT(t)->root_sigmtx);
                    846: 
1.8       misho     847:        return NULL;
                    848: }
                    849: 
                    850: /*
                    851:  * sched_hook_user() - Default USER hook
                    852:  *
                    853:  * @task = current task
                    854:  * @arg = unused
                    855:  * return: <0 errors and 0 ok
                    856:  */
                    857: #ifdef EVFILT_USER
                    858: void *
                    859: sched_hook_user(void *task, void *arg __unused)
                    860: {
1.28      misho     861: #if SUP_ENABLE == KQ_SUPPORT
1.8       misho     862:        sched_task_t *t = task;
                    863:        struct kevent chg[1];
                    864:        struct timespec timeout = { 0, 0 };
                    865: 
                    866:        if (!t || !TASK_ROOT(t))
                    867:                return (void*) -1;
                    868: 
                    869: #ifdef __NetBSD__
                    870:        EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_ADD | EV_CLEAR, TASK_DATLEN(t), 
                    871:                        0, (intptr_t) TASK_VAL(t));
                    872: #else
                    873:        EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_ADD | EV_CLEAR, TASK_DATLEN(t), 
                    874:                        0, (void*) TASK_VAL(t));
                    875: #endif
                    876:        if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                    877:                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                    878:                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
                    879:                else
                    880:                        LOGERR;
                    881:                return (void*) -1;
                    882:        }
                    883: 
1.25      misho     884: #endif
1.8       misho     885:        return NULL;
                    886: }
                    887: #endif
                    888: 
1.28      misho     889: #if SUP_ENABLE == KQ_SUPPORT
                    890: static inline void 
                    891: fetch_hook_kevent_proceed(int en, struct kevent *res, sched_root_task_t *r)
1.1       misho     892: {
1.28      misho     893:        struct kevent evt[1];
1.35      misho     894:        register int i, flg;
1.6       misho     895:        sched_task_t *task, *tmp;
1.28      misho     896:        struct timespec now = { 0, 0 };
1.11      misho     897: #ifdef AIO_SUPPORT
                    898:        int len, fd;
                    899:        struct aiocb *acb;
                    900: #ifdef EVFILT_LIO
                    901:        int l;
                    902:        off_t off;
                    903:        struct aiocb **acbs;
                    904:        struct iovec *iv;
                    905: #endif /* EVFILT_LIO */
                    906: #endif /* AIO_SUPPORT */
1.1       misho     907: 
                    908:        for (i = 0; i < en; i++) {
                    909:                memcpy(evt, &res[i], sizeof evt);
                    910:                evt->flags = EV_DELETE;
                    911:                /* Put read/write task to ready queue */
1.35      misho     912:                flg = 0;
1.1       misho     913:                switch (res[i].filter) {
                    914:                        case EVFILT_READ:
1.6       misho     915:                                TAILQ_FOREACH_SAFE(task, &r->root_read, task_node, tmp) {
1.32      misho     916:                                        if (TASK_FD(task) == ((intptr_t) res[i].udata)) {
1.35      misho     917:                                                if (!flg) {
                    918:                                                        TASK_RET(task) = res[i].data;
                    919:                                                        TASK_FLAG(task) = (u_long) res[i].fflags;
                    920: 
                    921:                                                        /* remove read handle */
                    922:                                                        remove_task_from(task, &r->root_read);
                    923: 
                    924:                                                        if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
                    925:                                                                if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
                    926:                                                                        task->task_type = taskUNUSE;
                    927:                                                                        insert_task_to(task, &r->root_unuse);
                    928:                                                                } else {
                    929:                                                                        task->task_type = taskREADY;
                    930:                                                                        insert_task_to(task, &r->root_ready);
                    931:                                                                }
1.32      misho     932:                                                        } else {
                    933:                                                                task->task_type = taskREADY;
                    934:                                                                insert_task_to(task, &r->root_ready);
                    935:                                                        }
1.3       misho     936:                                                }
1.35      misho     937:                                                flg++;
1.3       misho     938:                                        }
1.1       misho     939:                                }
                    940:                                break;
                    941:                        case EVFILT_WRITE:
1.6       misho     942:                                TAILQ_FOREACH_SAFE(task, &r->root_write, task_node, tmp) {
1.32      misho     943:                                        if (TASK_FD(task) == ((intptr_t) res[i].udata)) {
1.35      misho     944:                                                if (!flg) {
                    945:                                                        TASK_RET(task) = res[i].data;
                    946:                                                        TASK_FLAG(task) = (u_long) res[i].fflags;
                    947: 
                    948:                                                        /* remove write handle */
                    949:                                                        remove_task_from(task, &r->root_write);
                    950: 
                    951:                                                        if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
                    952:                                                                if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
                    953:                                                                        task->task_type = taskUNUSE;
                    954:                                                                        insert_task_to(task, &r->root_unuse);
                    955:                                                                } else {
                    956:                                                                        task->task_type = taskREADY;
                    957:                                                                        insert_task_to(task, &r->root_ready);
                    958:                                                                }
1.32      misho     959:                                                        } else {
                    960:                                                                task->task_type = taskREADY;
                    961:                                                                insert_task_to(task, &r->root_ready);
                    962:                                                        }
1.3       misho     963:                                                }
1.35      misho     964:                                                flg++;
1.3       misho     965:                                        }
1.1       misho     966:                                }
                    967:                                break;
1.7       misho     968:                        case EVFILT_TIMER:
                    969:                                TAILQ_FOREACH_SAFE(task, &r->root_alarm, task_node, tmp) {
1.32      misho     970:                                        if ((uintptr_t) TASK_DATA(task) == ((uintptr_t) res[i].udata)) {
1.35      misho     971:                                                if (!flg) {
                    972:                                                        TASK_RET(task) = res[i].data;
                    973:                                                        TASK_FLAG(task) = (u_long) res[i].fflags;
1.32      misho     974: 
1.35      misho     975:                                                        /* remove alarm handle */
                    976:                                                        transit_task2ready(task, &r->root_alarm);
                    977:                                                }
                    978:                                                flg++;
1.14      misho     979:                                        }
1.7       misho     980:                                }
                    981:                                break;
1.8       misho     982:                        case EVFILT_VNODE:
                    983:                                TAILQ_FOREACH_SAFE(task, &r->root_node, task_node, tmp) {
1.32      misho     984:                                        if (TASK_FD(task) == ((intptr_t) res[i].udata)) {
1.35      misho     985:                                                if (!flg) {
                    986:                                                        TASK_RET(task) = res[i].data;
                    987:                                                        TASK_FLAG(task) = (u_long) res[i].fflags;
1.32      misho     988: 
1.35      misho     989:                                                        /* remove node handle */
                    990:                                                        transit_task2ready(task, &r->root_node);
                    991:                                                }
                    992:                                                flg++;
1.8       misho     993:                                        }
                    994:                                }
                    995:                                break;
                    996:                        case EVFILT_PROC:
                    997:                                TAILQ_FOREACH_SAFE(task, &r->root_proc, task_node, tmp) {
1.32      misho     998:                                        if (TASK_VAL(task) == ((uintptr_t) res[i].udata)) {
1.35      misho     999:                                                if (!flg) {
                   1000:                                                        TASK_RET(task) = res[i].data;
                   1001:                                                        TASK_FLAG(task) = (u_long) res[i].fflags;
1.32      misho    1002: 
1.35      misho    1003:                                                        /* remove proc handle */
                   1004:                                                        transit_task2ready(task, &r->root_proc);
                   1005:                                                }
                   1006:                                                flg++;
1.8       misho    1007:                                        }
                   1008:                                }
                   1009:                                break;
                   1010:                        case EVFILT_SIGNAL:
                   1011:                                TAILQ_FOREACH_SAFE(task, &r->root_signal, task_node, tmp) {
1.32      misho    1012:                                        if (TASK_VAL(task) == ((uintptr_t) res[i].udata)) {
1.35      misho    1013:                                                if (!flg) {
                   1014:                                                        TASK_RET(task) = res[i].data;
                   1015:                                                        TASK_FLAG(task) = (u_long) res[i].fflags;
1.32      misho    1016: 
1.35      misho    1017:                                                        /* remove signal handle */
                   1018:                                                        transit_task2ready(task, &r->root_signal);
                   1019:                                                }
                   1020:                                                flg++;
1.14      misho    1021:                                        }
1.8       misho    1022:                                }
                   1023:                                break;
1.11      misho    1024: #ifdef AIO_SUPPORT
                   1025:                        case EVFILT_AIO:
                   1026:                                TAILQ_FOREACH_SAFE(task, &r->root_aio, task_node, tmp) {
                   1027:                                        acb = (struct aiocb*) TASK_VAL(task);
1.32      misho    1028:                                        if (acb == ((struct aiocb*) res[i].udata)) {
1.35      misho    1029:                                                if (!flg) {
                   1030:                                                        TASK_RET(task) = res[i].data;
                   1031:                                                        TASK_FLAG(task) = (u_long) res[i].fflags;
                   1032: 
                   1033:                                                        /* remove user handle */
                   1034:                                                        transit_task2ready(task, &r->root_aio);
                   1035: 
                   1036:                                                        fd = acb->aio_fildes;
                   1037:                                                        if ((len = aio_return(acb)) != -1) {
                   1038:                                                                if (lseek(fd, acb->aio_offset + len, SEEK_CUR) == -1)
                   1039:                                                                        LOGERR;
                   1040:                                                        } else
1.32      misho    1041:                                                                LOGERR;
1.37      misho    1042:                                                        e_free(acb);
1.35      misho    1043:                                                        TASK_DATLEN(task) = (u_long) len;
                   1044:                                                        TASK_FD(task) = fd;
                   1045:                                                }
                   1046:                                                flg++;
1.14      misho    1047:                                        }
1.11      misho    1048:                                }
                   1049:                                break;
                   1050: #ifdef EVFILT_LIO
                   1051:                        case EVFILT_LIO:
                   1052:                                TAILQ_FOREACH_SAFE(task, &r->root_lio, task_node, tmp) {
                   1053:                                        acbs = (struct aiocb**) TASK_VAL(task);
1.32      misho    1054:                                        if (acbs == ((struct aiocb**) res[i].udata)) {
1.35      misho    1055:                                                if (!flg) {
                   1056:                                                        TASK_RET(task) = res[i].data;
                   1057:                                                        TASK_FLAG(task) = (u_long) res[i].fflags;
                   1058: 
                   1059:                                                        /* remove user handle */
                   1060:                                                        transit_task2ready(task, &r->root_lio);
                   1061: 
                   1062:                                                        iv = (struct iovec*) TASK_DATA(task);
                   1063:                                                        fd = acbs[0]->aio_fildes;
                   1064:                                                        off = acbs[0]->aio_offset;
                   1065:                                                        for (len = 0; i < TASK_DATLEN(task); len += l, i++) {
                   1066:                                                                if ((iv[i].iov_len = aio_return(acbs[i])) == -1)
                   1067:                                                                        l = 0;
                   1068:                                                                else
                   1069:                                                                        l = iv[i].iov_len;
1.37      misho    1070:                                                                e_free(acbs[i]);
1.35      misho    1071:                                                        }
1.37      misho    1072:                                                        e_free(acbs);
1.35      misho    1073:                                                        TASK_DATLEN(task) = (u_long) len;
                   1074:                                                        TASK_FD(task) = fd;
1.28      misho    1075: 
1.35      misho    1076:                                                        if (lseek(fd, off + len, SEEK_CUR) == -1)
                   1077:                                                                LOGERR;
1.32      misho    1078:                                                }
1.35      misho    1079:                                                flg++;
1.11      misho    1080:                                        }
                   1081:                                }
                   1082:                                break;
                   1083: #endif /* EVFILT_LIO */
                   1084: #endif /* AIO_SUPPORT */
1.8       misho    1085: #ifdef EVFILT_USER
                   1086:                        case EVFILT_USER:
                   1087:                                TAILQ_FOREACH_SAFE(task, &r->root_user, task_node, tmp) {
1.32      misho    1088:                                        if (TASK_VAL(task) == ((uintptr_t) res[i].udata)) {
1.35      misho    1089:                                                if (!flg) {
                   1090:                                                        TASK_RET(task) = res[i].data;
                   1091:                                                        TASK_FLAG(task) = (u_long) res[i].fflags;
1.32      misho    1092: 
1.35      misho    1093:                                                        /* remove user handle */
                   1094:                                                        transit_task2ready(task, &r->root_user);
                   1095:                                                }
                   1096:                                                flg++;
1.8       misho    1097:                                        }
                   1098:                                }
                   1099:                                break;
1.11      misho    1100: #endif /* EVFILT_USER */
1.1       misho    1101:                }
1.28      misho    1102: 
1.35      misho    1103:                if (flg > 1)
                   1104:                        evt->flags &= ~EV_DELETE;
                   1105: 
1.4       misho    1106:                if (kevent(r->root_kq, evt, 1, NULL, 0, &now) == -1) {
1.28      misho    1107:                        if (r->root_hooks.hook_exec.exception)
                   1108:                                r->root_hooks.hook_exec.exception(r, NULL);
                   1109:                        else
                   1110:                                LOGERR;
                   1111:                }
                   1112:        }
                   1113: }
                   1114: #endif
                   1115: 
                   1116: #if SUP_ENABLE == EP_SUPPORT
                   1117: static inline void
                   1118: fetch_hook_epoll_proceed(int en, struct epoll_event *res, sched_root_task_t *r)
                   1119: {
1.37      misho    1120:        register int i, rflg, wflg;
1.28      misho    1121:        int ops = EPOLL_CTL_DEL;
1.32      misho    1122:        sched_task_t *t, *tmp, *task;
1.28      misho    1123:        struct epoll_event evt[1];
                   1124: 
                   1125:        for (i = 0; i < en; i++) {
                   1126:                memcpy(evt, &res[i], sizeof evt);
1.37      misho    1127:                evt->events ^= evt->events;
                   1128:                rflg = wflg = 0;
1.28      misho    1129: 
1.37      misho    1130:                if (res[i].events & (EPOLLIN | EPOLLPRI)) {
1.32      misho    1131:                        task = NULL;
                   1132:                        TAILQ_FOREACH_SAFE(t, &r->root_read, task_node, tmp) {
                   1133:                                if (TASK_FD(t) == evt->data.fd) {
1.37      misho    1134:                                        if (!task)
1.32      misho    1135:                                                task = t;
1.37      misho    1136:                                        rflg++;
1.32      misho    1137:                                }
                   1138:                        }
1.28      misho    1139: 
1.37      misho    1140:                        if (task) {
1.32      misho    1141:                                TASK_FLAG(task) = ioctl(TASK_FD(task), FIONREAD, &TASK_RET(task));
1.28      misho    1142:                                /* remove read handle */
                   1143:                                remove_task_from(task, &r->root_read);
                   1144: 
                   1145:                                if (r->root_hooks.hook_exec.exception && evt->events & (EPOLLRDHUP | EPOLLERR | EPOLLHUP)) {
                   1146:                                        if (r->root_hooks.hook_exec.exception(r, (void*) (intptr_t)
                   1147:                                                                (evt->events & EPOLLERR ? EV_ERROR | EV_EOF : EV_EOF))) {
                   1148:                                                task->task_type = taskUNUSE;
                   1149:                                                insert_task_to(task, &r->root_unuse);
                   1150:                                        } else {
                   1151:                                                task->task_type = taskREADY;
                   1152:                                                insert_task_to(task, &r->root_ready);
                   1153:                                        }
                   1154:                                } else {
                   1155:                                        task->task_type = taskREADY;
                   1156:                                        insert_task_to(task, &r->root_ready);
                   1157:                                }
1.32      misho    1158: 
1.37      misho    1159:                                if (!(res[i].events & EPOLLOUT) && FD_ISSET(evt->data.fd, &r->root_fds[1])) {
1.32      misho    1160:                                        evt->events |= EPOLLOUT;
1.37      misho    1161:                                        wflg = 42;
1.32      misho    1162:                                }
1.38      misho    1163:                                if (rflg > 1) {
                   1164:                                        if (FD_ISSET(evt->data.fd, &r->root_fds[0]))
                   1165:                                                evt->events |= EPOLLIN;
                   1166:                                        if (FD_ISSET(evt->data.fd, &r->root_fds[2]))
                   1167:                                                evt->events |= EPOLLPRI;
                   1168:                                } else {
1.32      misho    1169:                                        FD_CLR(evt->data.fd, &r->root_fds[0]);
1.38      misho    1170:                                        FD_CLR(evt->data.fd, &r->root_fds[2]);
                   1171:                                }
1.28      misho    1172:                        }
1.37      misho    1173:                }
                   1174:                if (res[i].events & EPOLLOUT) {
1.32      misho    1175:                        task = NULL;
                   1176:                        TAILQ_FOREACH_SAFE(t, &r->root_write, task_node, tmp) {
                   1177:                                if (TASK_FD(t) == evt->data.fd) {
1.37      misho    1178:                                        if (!task)
1.32      misho    1179:                                                task = t;
1.37      misho    1180:                                        wflg++;
1.28      misho    1181:                                }
1.32      misho    1182:                        }
                   1183: 
1.37      misho    1184:                        if (task) {
1.32      misho    1185:                                TASK_FLAG(task) = ioctl(TASK_FD(task), FIONWRITE, &TASK_RET(task));
1.28      misho    1186:                                /* remove write handle */
                   1187:                                remove_task_from(task, &r->root_write);
                   1188: 
                   1189:                                if (r->root_hooks.hook_exec.exception && evt->events & (EPOLLERR | EPOLLHUP)) {
                   1190:                                        if (r->root_hooks.hook_exec.exception(r, (void*) (intptr_t)
                   1191:                                                                (evt->events & EPOLLERR ? EV_ERROR | EV_EOF : EV_EOF))) {
                   1192:                                                task->task_type = taskUNUSE;
                   1193:                                                insert_task_to(task, &r->root_unuse);
                   1194:                                        } else {
                   1195:                                                task->task_type = taskREADY;
                   1196:                                                insert_task_to(task, &r->root_ready);
                   1197:                                        }
                   1198:                                } else {
                   1199:                                        task->task_type = taskREADY;
                   1200:                                        insert_task_to(task, &r->root_ready);
                   1201:                                }
1.32      misho    1202: 
1.38      misho    1203:                                if (!(res[i].events & EPOLLIN) && FD_ISSET(evt->data.fd, &r->root_fds[0])) {
                   1204:                                        evt->events |= EPOLLIN;
                   1205:                                        rflg = 42;
                   1206:                                }
                   1207:                                if (!(res[i].events & EPOLLPRI) && FD_ISSET(evt->data.fd, &r->root_fds[2])) {
                   1208:                                        evt->events |= EPOLLPRI;
1.37      misho    1209:                                        rflg = 42;
1.32      misho    1210:                                }
1.37      misho    1211:                                if (wflg > 1)
1.32      misho    1212:                                        evt->events |= EPOLLOUT;
1.37      misho    1213:                                else
1.32      misho    1214:                                        FD_CLR(evt->data.fd, &r->root_fds[1]);
1.28      misho    1215:                        }
                   1216:                }
                   1217: 
1.39      misho    1218:                ops = EPOLL_CTL_DEL;
1.37      misho    1219:                if (rflg > 1 || wflg > 1)
                   1220:                        ops = EPOLL_CTL_MOD;
                   1221: 
1.28      misho    1222:                if (epoll_ctl(r->root_kq, ops, evt->data.fd, evt) == -1) {
1.3       misho    1223:                        if (r->root_hooks.hook_exec.exception) {
1.28      misho    1224:                                r->root_hooks.hook_exec.exception(r, NULL);
1.3       misho    1225:                        } else
                   1226:                                LOGERR;
                   1227:                }
1.25      misho    1228:        }
1.28      misho    1229: }
                   1230: #endif
                   1231: 
                   1232: #if SUP_ENABLE == NO_SUPPORT
                   1233: static inline void 
                   1234: fetch_hook_select_proceed(int en, fd_set rfd, fd_set wfd, fd_set xfd, sched_root_task_t *r)
                   1235: {
1.37      misho    1236:        register int i, rflg, wflg;
                   1237:        sched_task_t *t, *tmp, *task;
1.28      misho    1238: 
                   1239:        /* skip select check if return value from select is zero */
                   1240:        if (!en)
                   1241:                return;
                   1242: 
1.25      misho    1243:        for (i = 0; i < r->root_kq; i++) {
1.38      misho    1244:                if (!FD_ISSET(i, &r->root_fds[0]) && 
                   1245:                                !FD_ISSET(i, &r->root_fds[1]) && 
                   1246:                                !FD_ISSET(i, &r->root_fds[2]))
1.37      misho    1247:                        continue;
                   1248: 
                   1249:                rflg = wflg = 0;
                   1250: 
1.25      misho    1251:                if (FD_ISSET(i, &rfd) || FD_ISSET(i, &xfd)) {
1.37      misho    1252:                        task = NULL;
1.32      misho    1253:                        TAILQ_FOREACH_SAFE(t, &r->root_read, task_node, tmp) {
                   1254:                                if (TASK_FD(t) == i) {
1.37      misho    1255:                                        if (!task)
1.32      misho    1256:                                                task = t;
1.37      misho    1257:                                        rflg++;
1.25      misho    1258:                                }
1.32      misho    1259:                        }
                   1260: 
1.37      misho    1261:                        if (task) {
1.32      misho    1262:                                TASK_FLAG(task) = ioctl(TASK_FD(task), FIONREAD, &TASK_RET(task));
                   1263: 
1.25      misho    1264:                                /* remove read handle */
1.28      misho    1265:                                remove_task_from(task, &r->root_read);
                   1266: 
1.25      misho    1267:                                if (r->root_hooks.hook_exec.exception) {
                   1268:                                        if (r->root_hooks.hook_exec.exception(r, NULL)) {
                   1269:                                                task->task_type = taskUNUSE;
1.28      misho    1270:                                                insert_task_to(task, &r->root_unuse);
1.25      misho    1271:                                        } else {
                   1272:                                                task->task_type = taskREADY;
1.28      misho    1273:                                                insert_task_to(task, &r->root_ready);
1.25      misho    1274:                                        }
                   1275:                                } else {
                   1276:                                        task->task_type = taskREADY;
1.28      misho    1277:                                        insert_task_to(task, &r->root_ready);
1.25      misho    1278:                                }
1.32      misho    1279: 
                   1280:                                /* remove resouce */
1.38      misho    1281:                                if (rflg == 1) {
1.32      misho    1282:                                        FD_CLR(i, &r->root_fds[0]);
1.38      misho    1283:                                        FD_CLR(i, &r->root_fds[2]);
                   1284:                                }
1.25      misho    1285:                        }
1.37      misho    1286:                }
                   1287:                if (FD_ISSET(i, &wfd)) {
                   1288:                        task = NULL;
1.32      misho    1289:                        TAILQ_FOREACH_SAFE(t, &r->root_write, task_node, tmp) {
                   1290:                                if (TASK_FD(t) == i) {
1.37      misho    1291:                                        if (!task)
1.32      misho    1292:                                                task = t;
1.37      misho    1293:                                        wflg++;
1.25      misho    1294:                                }
1.32      misho    1295:                        }
                   1296: 
1.37      misho    1297:                        if (task) {
1.32      misho    1298:                                TASK_FLAG(task) = ioctl(TASK_FD(task), FIONWRITE, &TASK_RET(task));
                   1299: 
1.25      misho    1300:                                /* remove write handle */
1.28      misho    1301:                                remove_task_from(task, &r->root_write);
                   1302: 
1.25      misho    1303:                                if (r->root_hooks.hook_exec.exception) {
                   1304:                                        if (r->root_hooks.hook_exec.exception(r, NULL)) {
                   1305:                                                task->task_type = taskUNUSE;
1.28      misho    1306:                                                insert_task_to(task, &r->root_unuse);
1.25      misho    1307:                                        } else {
                   1308:                                                task->task_type = taskREADY;
1.28      misho    1309:                                                insert_task_to(task, &r->root_ready);
1.25      misho    1310:                                        }
                   1311:                                } else {
                   1312:                                        task->task_type = taskREADY;
1.28      misho    1313:                                        insert_task_to(task, &r->root_ready);
1.25      misho    1314:                                }
1.32      misho    1315: 
                   1316:                                /* remove resouce */
1.37      misho    1317:                                if (wflg == 1)
1.32      misho    1318:                                        FD_CLR(i, &r->root_fds[1]);
1.25      misho    1319:                        }
                   1320:                }
                   1321:        }
                   1322: 
                   1323:        /* optimize select */
1.37      misho    1324:        for (i = r->root_kq - 1; i >= 0; i--)
1.38      misho    1325:                if (FD_ISSET(i, &r->root_fds[0]) || 
                   1326:                                FD_ISSET(i, &r->root_fds[1]) || 
                   1327:                                FD_ISSET(i, &r->root_fds[2]))
1.25      misho    1328:                        break;
1.37      misho    1329:        r->root_kq = i + 1;
1.28      misho    1330: }
                   1331: #endif
                   1332: 
                   1333: /*
                   1334:  * sched_hook_fetch() - Default FETCH hook
                   1335:  *
                   1336:  * @root = root task
                   1337:  * @arg = unused
                   1338:  * return: NULL error or !=NULL fetched task
                   1339:  */
                   1340: void *
                   1341: sched_hook_fetch(void *root, void *arg __unused)
                   1342: {
                   1343:        sched_root_task_t *r = root;
                   1344:        sched_task_t *task, *tmp;
1.40      misho    1345:        struct timespec now, m, mtmp, *tsmin;
1.28      misho    1346: #if SUP_ENABLE == KQ_SUPPORT
                   1347:        struct kevent res[KQ_EVENTS];
                   1348:        struct timespec *timeout;
                   1349: #elif SUP_ENABLE == EP_SUPPORT
                   1350:        struct epoll_event res[KQ_EVENTS];
                   1351:        u_long timeout = 0;
                   1352: #else
                   1353:        struct timeval *timeout, tv;
                   1354:        fd_set rfd, wfd, xfd;
                   1355: #endif
                   1356:        int en;
                   1357: 
                   1358:        if (!r)
                   1359:                return NULL;
                   1360: 
                   1361:        /* get new task by queue priority */
                   1362:        while ((task = TAILQ_FIRST(&r->root_event))) {
                   1363:                transit_task2unuse(task, &r->root_event);
                   1364:                return task;
                   1365:        }
                   1366:        while ((task = TAILQ_FIRST(&r->root_ready))) {
                   1367:                transit_task2unuse(task, &r->root_ready);
                   1368:                return task;
                   1369:        }
                   1370: 
1.33      misho    1371:        /* if present member of task, set NOWAIT */
                   1372:        if (!TAILQ_FIRST(&r->root_task)) {
                   1373:                /* timer tasks */
1.28      misho    1374: #ifdef TIMER_WITHOUT_SORT
1.33      misho    1375:                clock_gettime(CLOCK_MONOTONIC, &now);
1.28      misho    1376: 
1.33      misho    1377:                sched_timespecclear(&r->root_wait);
                   1378:                TAILQ_FOREACH(task, &r->root_timer, task_node) {
                   1379:                        if (!sched_timespecisset(&r->root_wait))
                   1380:                                r->root_wait = TASK_TS(task);
                   1381:                        else if (sched_timespeccmp(&TASK_TS(task), &r->root_wait, -) < 0)
                   1382:                                r->root_wait = TASK_TS(task);
                   1383:                }
                   1384: 
                   1385:                if (TAILQ_FIRST(&r->root_timer)) {
                   1386:                        m = r->root_wait;
                   1387:                        sched_timespecsub(&m, &now, &mtmp);
1.42    ! misho    1388:                        if (mtmp.tv_sec < 0 || mtmp.tv_nsec < 0)
        !          1389:                                /* don't wait for events. we have ready timer */
        !          1390:                                sched_timespecclear(&r->root_wait);
        !          1391:                        else
        !          1392:                                r->root_wait = mtmp;
1.33      misho    1393:                } else {
                   1394:                        /* set wait INFTIM */
                   1395:                        sched_timespecinf(&r->root_wait);
                   1396:                }
1.28      misho    1397: #else  /* ! TIMER_WITHOUT_SORT */
1.33      misho    1398:                if ((task = TAILQ_FIRST(&r->root_timer))) {
                   1399:                        clock_gettime(CLOCK_MONOTONIC, &now);
1.28      misho    1400: 
1.33      misho    1401:                        m = TASK_TS(task);
                   1402:                        sched_timespecsub(&m, &now, &mtmp);
1.42    ! misho    1403:                        if (mtmp.tv_sec < 0 || mtmp.tv_nsec < 0)
        !          1404:                                /* don't wait for events. we have ready timer */
        !          1405:                                sched_timespecclear(&r->root_wait);
        !          1406:                        else
        !          1407:                                r->root_wait = mtmp;
1.33      misho    1408:                } else {
                   1409:                        /* set wait INFTIM */
                   1410:                        sched_timespecinf(&r->root_wait);
                   1411:                }
1.28      misho    1412: #endif /* TIMER_WITHOUT_SORT */
1.33      misho    1413:        } else  /* no waiting for event, because we have ready task */
1.28      misho    1414:                sched_timespecclear(&r->root_wait);
                   1415: 
1.40      misho    1416:        if (!sched_timespecisinf(&r->root_wait)) {
                   1417:                tsmin = sched_timespecmin(&r->root_wait, &r->root_poll);
1.28      misho    1418: #if SUP_ENABLE == KQ_SUPPORT
1.40      misho    1419:                timeout = tsmin;
1.28      misho    1420: #elif SUP_ENABLE == EP_SUPPORT
1.40      misho    1421:                timeout = tsmin->tv_sec * 1000 + tsmin->tv_nsec / 1000000;
1.28      misho    1422: #else
1.40      misho    1423:                sched_timespec2val(tsmin, &tv);
1.28      misho    1424:                timeout = &tv;
                   1425: #endif /* KQ_SUPPORT */
                   1426:        } else if (sched_timespecisinf(&r->root_poll))
                   1427: #if SUP_ENABLE == EP_SUPPORT
                   1428:                timeout = -1;
                   1429: #else
                   1430:                timeout = NULL;
                   1431: #endif
                   1432:        else {
                   1433: #if SUP_ENABLE == KQ_SUPPORT
                   1434:                timeout = &r->root_poll;
                   1435: #elif SUP_ENABLE == EP_SUPPORT
                   1436:                timeout = r->root_poll.tv_sec * 1000 + r->root_poll.tv_nsec / 1000000;
                   1437: #else
                   1438:                sched_timespec2val(&r->root_poll, &tv);
                   1439:                timeout = &tv;
                   1440: #endif /* KQ_SUPPORT */
                   1441:        }
                   1442: 
                   1443: #if SUP_ENABLE == KQ_SUPPORT
                   1444:        if ((en = kevent(r->root_kq, NULL, 0, res, KQ_EVENTS, timeout)) == -1) {
                   1445: #elif SUP_ENABLE == EP_SUPPORT
                   1446:        if ((en = epoll_wait(r->root_kq, res, KQ_EVENTS, timeout)) == -1) {
                   1447: #else
1.38      misho    1448:        xfd = r->root_fds[2];
                   1449:        rfd = r->root_fds[0];
1.28      misho    1450:        wfd = r->root_fds[1];
                   1451:        if ((en = select(r->root_kq, &rfd, &wfd, &xfd, timeout)) == -1) {
                   1452: #endif /* KQ_SUPPORT */
                   1453:                if (r->root_hooks.hook_exec.exception) {
                   1454:                        if (r->root_hooks.hook_exec.exception(r, NULL))
                   1455:                                return NULL;
                   1456:                } else if (errno != EINTR)
                   1457:                        LOGERR;
                   1458:                goto skip_event;
                   1459:        }
                   1460: 
                   1461:        /* Go and catch the cat into pipes ... */
                   1462: #if SUP_ENABLE == KQ_SUPPORT
                   1463:        /* kevent dispatcher */
                   1464:        fetch_hook_kevent_proceed(en, res, r);
                   1465: #elif SUP_ENABLE == EP_SUPPORT
                   1466:        /* epoll dispatcher */
                   1467:        fetch_hook_epoll_proceed(en, res, r);
                   1468: #else
                   1469:        /* select dispatcher */
                   1470:        fetch_hook_select_proceed(en, rfd, wfd, xfd, r);
                   1471: #endif /* KQ_SUPPORT */
1.1       misho    1472: 
1.24      misho    1473: skip_event:
1.2       misho    1474:        /* timer update & put in ready queue */
1.4       misho    1475:        clock_gettime(CLOCK_MONOTONIC, &now);
1.1       misho    1476: 
1.6       misho    1477:        TAILQ_FOREACH_SAFE(task, &r->root_timer, task_node, tmp)
1.28      misho    1478:                if (sched_timespeccmp(&now, &TASK_TS(task), -) >= 0)
                   1479:                        transit_task2ready(task, &r->root_timer);
1.1       misho    1480: 
1.12      misho    1481:        /* put regular task priority task to ready queue, 
1.13      misho    1482:                if there is no ready task or reach max missing hit for regular task */
1.12      misho    1483:        if ((task = TAILQ_FIRST(&r->root_task))) {
1.13      misho    1484:                if (!TAILQ_FIRST(&r->root_ready) || r->root_miss >= TASK_VAL(task)) {
                   1485:                        r->root_miss ^= r->root_miss;
1.1       misho    1486: 
1.28      misho    1487:                        transit_task2ready(task, &r->root_task);
1.1       misho    1488:                } else
1.13      misho    1489:                        r->root_miss++;
1.1       misho    1490:        } else
1.13      misho    1491:                r->root_miss ^= r->root_miss;
1.1       misho    1492: 
                   1493:        /* OK, lets get ready task !!! */
1.6       misho    1494:        task = TAILQ_FIRST(&r->root_ready);
1.28      misho    1495:        if (task)
                   1496:                transit_task2unuse(task, &r->root_ready);
1.1       misho    1497:        return task;
                   1498: }
1.3       misho    1499: 
                   1500: /*
                   1501:  * sched_hook_exception() - Default EXCEPTION hook
1.5       misho    1502:  *
1.3       misho    1503:  * @root = root task
                   1504:  * @arg = custom handling: if arg == EV_EOF or other value; default: arg == NULL log errno
                   1505:  * return: <0 errors and 0 ok
                   1506:  */
                   1507: void *
                   1508: sched_hook_exception(void *root, void *arg)
                   1509: {
                   1510:        sched_root_task_t *r = root;
                   1511: 
1.6       misho    1512:        if (!r)
1.3       misho    1513:                return NULL;
                   1514: 
                   1515:        /* custom exception handling ... */
                   1516:        if (arg) {
                   1517:                if (arg == (void*) EV_EOF)
                   1518:                        return NULL;
                   1519:                return (void*) -1;      /* raise scheduler error!!! */
                   1520:        }
                   1521: 
                   1522:        /* if error hook exists */
                   1523:        if (r->root_hooks.hook_root.error)
                   1524:                return (r->root_hooks.hook_root.error(root, (void*) ((intptr_t) errno)));
                   1525: 
                   1526:        /* default case! */
                   1527:        LOGERR;
                   1528:        return NULL;
                   1529: }
1.5       misho    1530: 
                   1531: /*
                   1532:  * sched_hook_condition() - Default CONDITION hook
                   1533:  *
                   1534:  * @root = root task
                   1535:  * @arg = killState from schedRun()
                   1536:  * return: NULL kill scheduler loop or !=NULL ok
                   1537:  */
                   1538: void *
                   1539: sched_hook_condition(void *root, void *arg)
                   1540: {
                   1541:        sched_root_task_t *r = root;
                   1542: 
1.6       misho    1543:        if (!r)
1.5       misho    1544:                return NULL;
                   1545: 
1.28      misho    1546:        return (void*) (*r->root_cond - *(intptr_t*) arg);
1.5       misho    1547: }
1.19      misho    1548: 
                   1549: /*
                   1550:  * sched_hook_rtc() - Default RTC hook
                   1551:  *
                   1552:  * @task = current task
                   1553:  * @arg = unused
                   1554:  * return: <0 errors and 0 ok
                   1555:  */
                   1556: void *
                   1557: sched_hook_rtc(void *task, void *arg __unused)
                   1558: {
1.30      misho    1559: #if defined(HAVE_LIBRT) && defined(HAVE_TIMER_CREATE) && \
                   1560:        defined(HAVE_TIMER_SETTIME) && defined(HAVE_TIMER_DELETE)
1.19      misho    1561:        sched_task_t *sigt = NULL, *t = task;
                   1562:        struct itimerspec its;
                   1563:        struct sigevent evt;
                   1564:        timer_t tmr;
1.28      misho    1565: #if SUP_ENABLE != KQ_SUPPORT
                   1566:        struct sigaction sa;
                   1567: #endif
1.19      misho    1568: 
                   1569:        if (!t || !TASK_ROOT(t))
                   1570:                return (void*) -1;
                   1571: 
                   1572:        memset(&evt, 0, sizeof evt);
                   1573:        evt.sigev_notify = SIGEV_SIGNAL;
1.20      misho    1574:        evt.sigev_signo = (intptr_t) TASK_DATA(t) + SIGRTMIN;
1.28      misho    1575:        evt.sigev_value.sival_ptr = t;
1.19      misho    1576: 
                   1577:        if (timer_create(CLOCK_MONOTONIC, &evt, &tmr) == -1) {
                   1578:                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                   1579:                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
                   1580:                else
                   1581:                        LOGERR;
                   1582:                return (void*) -1;
                   1583:        } else
                   1584:                TASK_FLAG(t) = (u_long) tmr;
                   1585: 
1.28      misho    1586: #if SUP_ENABLE == KQ_SUPPORT
1.21      misho    1587:        if (!(sigt = schedSignal(TASK_ROOT(t), _sched_rtcWrapper, TASK_ARG(t), evt.sigev_signo, 
                   1588:                                t, (size_t) tmr))) {
1.19      misho    1589:                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                   1590:                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
                   1591:                else
                   1592:                        LOGERR;
                   1593:                timer_delete(tmr);
                   1594:                return (void*) -1;
                   1595:        } else
                   1596:                TASK_RET(t) = (uintptr_t) sigt;
1.28      misho    1597: #else
                   1598:        memset(&sa, 0, sizeof sa);
                   1599:        sigemptyset(&sa.sa_mask);
                   1600:        sa.sa_sigaction = _sched_rtcSigWrapper;
                   1601:        sa.sa_flags = SA_SIGINFO | SA_RESTART;
                   1602: 
                   1603:        if (sigaction(evt.sigev_signo, &sa, NULL) == -1) {
                   1604:                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                   1605:                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
                   1606:                else
                   1607:                        LOGERR;
                   1608:                timer_delete(tmr);
                   1609:                return (void*) -1;
                   1610:        }
                   1611: #endif
1.19      misho    1612: 
                   1613:        memset(&its, 0, sizeof its);
                   1614:        its.it_value.tv_sec = t->task_val.ts.tv_sec;
                   1615:        its.it_value.tv_nsec = t->task_val.ts.tv_nsec;
                   1616: 
                   1617:        if (timer_settime(tmr, TIMER_RELTIME, &its, NULL) == -1) {
                   1618:                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                   1619:                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
                   1620:                else
                   1621:                        LOGERR;
                   1622:                schedCancel(sigt);
                   1623:                timer_delete(tmr);
                   1624:                return (void*) -1;
                   1625:        }
1.30      misho    1626: #endif /* HAVE_TIMER_CREATE */
1.19      misho    1627:        return NULL;
                   1628: }

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