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

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

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