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

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

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