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

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

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