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

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

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