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

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

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