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

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.10.2.4! misho       6: * $Id: hooks.c,v 1.10.2.3 2012/08/01 14:27:52 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.5       misho      15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
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: 
                     50: /*
                     51:  * sched_hook_init() - Default INIT hook
1.5       misho      52:  *
1.1       misho      53:  * @root = root task
1.6       misho      54:  * @arg = unused
1.1       misho      55:  * return: <0 errors and 0 ok
                     56:  */
                     57: void *
1.6       misho      58: sched_hook_init(void *root, void *arg __unused)
1.1       misho      59: {
                     60:        sched_root_task_t *r = root;
                     61: 
1.6       misho      62:        if (!r)
1.1       misho      63:                return (void*) -1;
                     64: 
                     65:        r->root_kq = kqueue();
                     66:        if (r->root_kq == -1) {
                     67:                LOGERR;
                     68:                return (void*) -1;
                     69:        }
                     70: 
                     71:        return NULL;
                     72: }
                     73: 
                     74: /*
                     75:  * sched_hook_fini() - Default FINI hook
1.5       misho      76:  *
1.1       misho      77:  * @root = root task
                     78:  * @arg = unused
                     79:  * return: <0 errors and 0 ok
                     80:  */
                     81: void *
                     82: sched_hook_fini(void *root, void *arg __unused)
                     83: {
                     84:        sched_root_task_t *r = root;
                     85: 
                     86:        if (!r)
                     87:                return (void*) -1;
                     88: 
                     89:        if (r->root_kq > 2) {
                     90:                close(r->root_kq);
                     91:                r->root_kq = 0;
                     92:        }
                     93: 
                     94:        return NULL;
                     95: }
                     96: 
                     97: /*
                     98:  * sched_hook_cancel() - Default CANCEL hook
1.5       misho      99:  *
1.1       misho     100:  * @task = current task
                    101:  * @arg = unused
                    102:  * return: <0 errors and 0 ok
                    103:  */
                    104: void *
                    105: sched_hook_cancel(void *task, void *arg __unused)
                    106: {
                    107:        sched_task_t *t = task;
                    108:        struct kevent chg[1];
1.2       misho     109:        struct timespec timeout = { 0, 0 };
1.10.2.3  misho     110: #ifdef EVFILT_AIO
                    111:        struct aiocb *acb;
                    112: #endif
1.1       misho     113: 
1.6       misho     114:        if (!t || !TASK_ROOT(t))
1.1       misho     115:                return (void*) -1;
                    116: 
1.4       misho     117:        switch (TASK_TYPE(t)) {
1.1       misho     118:                case taskREAD:
1.2       misho     119: #ifdef __NetBSD__
                    120:                        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_DELETE, 0, 0, (intptr_t) TASK_FD(t));
                    121: #else
                    122:                        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_DELETE, 0, 0, (void*) TASK_FD(t));
                    123: #endif
1.1       misho     124:                        break;
                    125:                case taskWRITE:
1.2       misho     126: #ifdef __NetBSD__
                    127:                        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_DELETE, 0, 0, (intptr_t) TASK_FD(t));
                    128: #else
                    129:                        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_DELETE, 0, 0, (void*) TASK_FD(t));
                    130: #endif
1.1       misho     131:                        break;
1.7       misho     132:                case taskALARM:
                    133: #ifdef __NetBSD__
                    134:                        EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_DELETE, 
                    135:                                        0, 0, (intptr_t) TASK_DATA(t));
                    136: #else
                    137:                        EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_DELETE, 
                    138:                                        0, 0, (void*) TASK_DATA(t));
                    139: #endif
1.8       misho     140:                        break;
                    141:                case taskNODE:
                    142: #ifdef __NetBSD__
                    143:                        EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_DELETE, 0, 0, (intptr_t) TASK_FD(t));
                    144: #else
                    145:                        EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_DELETE, 0, 0, (void*) TASK_FD(t));
                    146: #endif
                    147:                        break;
                    148:                case taskPROC:
                    149: #ifdef __NetBSD__
                    150:                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));
                    151: #else
                    152:                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_DELETE, 0, 0, (void*) TASK_VAL(t));
                    153: #endif
                    154:                        break;
                    155:                case taskSIGNAL:
                    156: #ifdef __NetBSD__
                    157:                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));
                    158: #else
                    159:                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_DELETE, 0, 0, (void*) TASK_VAL(t));
                    160: #endif
                    161:                        break;
1.10.2.1  misho     162: #ifdef EVFILT_AIO
                    163:                case taskAIO:
                    164: #ifdef __NetBSD__
                    165:                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_AIO, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));
                    166: #else
                    167:                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_AIO, EV_DELETE, 0, 0, (void*) TASK_VAL(t));
                    168: #endif
1.10.2.3  misho     169:                        acb = (struct aiocb*) TASK_VAL(t);
                    170:                        if (acb) {
                    171:                                aio_cancel(acb->aio_fildes, acb);
                    172:                                free(acb);
1.10.2.2  misho     173:                                TASK_VAL(t) = 0;
                    174:                        }
1.10.2.1  misho     175:                        break;
                    176: #endif
1.8       misho     177: #ifdef EVFILT_USER
                    178:                case taskUSER:
                    179: #ifdef __NetBSD__
                    180:                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));
                    181: #else
                    182:                        EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_DELETE, 0, 0, (void*) TASK_VAL(t));
                    183: #endif
1.10      misho     184:                        break;
1.8       misho     185: #endif
1.1       misho     186:                default:
1.8       misho     187:                        return NULL;
1.1       misho     188:        }
                    189: 
1.8       misho     190:        kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout);
1.1       misho     191:        return NULL;
                    192: }
                    193: 
                    194: /*
                    195:  * sched_hook_read() - Default READ hook
1.5       misho     196:  *
1.1       misho     197:  * @task = current task
                    198:  * @arg = unused
                    199:  * return: <0 errors and 0 ok
                    200:  */
                    201: void *
                    202: sched_hook_read(void *task, void *arg __unused)
                    203: {
                    204:        sched_task_t *t = task;
                    205:        struct kevent chg[1];
1.2       misho     206:        struct timespec timeout = { 0, 0 };
1.1       misho     207: 
1.6       misho     208:        if (!t || !TASK_ROOT(t))
1.1       misho     209:                return (void*) -1;
                    210: 
1.2       misho     211: #ifdef __NetBSD__
1.8       misho     212:        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, (intptr_t) TASK_FD(t));
1.2       misho     213: #else
1.8       misho     214:        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, (void*) TASK_FD(t));
1.2       misho     215: #endif
1.4       misho     216:        if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                    217:                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                    218:                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
1.3       misho     219:                else
                    220:                        LOGERR;
1.1       misho     221:                return (void*) -1;
                    222:        }
                    223: 
                    224:        return NULL;
                    225: }
                    226: 
                    227: /*
                    228:  * sched_hook_write() - Default WRITE hook
1.5       misho     229:  *
1.1       misho     230:  * @task = current task
                    231:  * @arg = unused
                    232:  * return: <0 errors and 0 ok
                    233:  */
                    234: void *
                    235: sched_hook_write(void *task, void *arg __unused)
                    236: {
                    237:        sched_task_t *t = task;
                    238:        struct kevent chg[1];
1.2       misho     239:        struct timespec timeout = { 0, 0 };
1.1       misho     240: 
1.6       misho     241:        if (!t || !TASK_ROOT(t))
1.1       misho     242:                return (void*) -1;
                    243: 
1.2       misho     244: #ifdef __NetBSD__
1.8       misho     245:        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, (intptr_t) TASK_FD(t));
1.2       misho     246: #else
1.8       misho     247:        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, (void*) TASK_FD(t));
1.2       misho     248: #endif
1.4       misho     249:        if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                    250:                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                    251:                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
1.3       misho     252:                else
                    253:                        LOGERR;
1.1       misho     254:                return (void*) -1;
                    255:        }
                    256: 
                    257:        return NULL;
                    258: }
                    259: 
                    260: /*
1.7       misho     261:  * sched_hook_alarm() - Default ALARM hook
                    262:  *
                    263:  * @task = current task
                    264:  * @arg = unused
                    265:  * return: <0 errors and 0 ok
                    266:  */
                    267: void *
                    268: sched_hook_alarm(void *task, void *arg __unused)
                    269: {
                    270:        sched_task_t *t = task;
                    271:        struct kevent chg[1];
                    272:        struct timespec timeout = { 0, 0 };
                    273: 
                    274:        if (!t || !TASK_ROOT(t))
                    275:                return (void*) -1;
                    276: 
                    277: #ifdef __NetBSD__
                    278:        EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 
                    279:                        t->task_val.ts.tv_sec * 1000 + t->task_val.ts.tv_nsec / 1000000, 
                    280:                        (intptr_t) TASK_DATA(t));
                    281: #else
                    282:        EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 
                    283:                        t->task_val.ts.tv_sec * 1000 + t->task_val.ts.tv_nsec / 1000000, 
                    284:                        (void*) TASK_DATA(t));
                    285: #endif
                    286:        if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                    287:                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                    288:                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
                    289:                else
                    290:                        LOGERR;
                    291:                return (void*) -1;
                    292:        }
                    293: 
                    294:        return NULL;
                    295: }
                    296: 
                    297: /*
1.8       misho     298:  * sched_hook_node() - Default NODE hook
                    299:  *
                    300:  * @task = current task
                    301:  * @arg = unused
                    302:  * return: <0 errors and 0 ok
                    303:  */
                    304: void *
                    305: sched_hook_node(void *task, void *arg __unused)
                    306: {
                    307:        sched_task_t *t = task;
                    308:        struct kevent chg[1];
                    309:        struct timespec timeout = { 0, 0 };
                    310: 
                    311:        if (!t || !TASK_ROOT(t))
                    312:                return (void*) -1;
                    313: 
                    314: #ifdef __NetBSD__
                    315:        EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_ADD | EV_CLEAR, 
                    316:                        NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | 
                    317:                        NOTE_LINK | NOTE_RENAME | NOTE_REVOKE, 0, (intptr_t) TASK_FD(t));
                    318: #else
                    319:        EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_ADD | EV_CLEAR, 
                    320:                        NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | 
                    321:                        NOTE_LINK | NOTE_RENAME | NOTE_REVOKE, 0, (void*) TASK_FD(t));
                    322: #endif
                    323:        if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                    324:                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                    325:                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
                    326:                else
                    327:                        LOGERR;
                    328:                return (void*) -1;
                    329:        }
                    330: 
                    331:        return NULL;
                    332: }
                    333: 
                    334: /*
                    335:  * sched_hook_proc() - Default PROC hook
                    336:  *
                    337:  * @task = current task
                    338:  * @arg = unused
                    339:  * return: <0 errors and 0 ok
                    340:  */
                    341: void *
                    342: sched_hook_proc(void *task, void *arg __unused)
                    343: {
                    344:        sched_task_t *t = task;
                    345:        struct kevent chg[1];
                    346:        struct timespec timeout = { 0, 0 };
                    347: 
                    348:        if (!t || !TASK_ROOT(t))
                    349:                return (void*) -1;
                    350: 
                    351: #ifdef __NetBSD__
                    352:        EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_ADD | EV_CLEAR, 
                    353:                        NOTE_EXIT | NOTE_FORK | NOTE_EXEC | NOTE_TRACK, 0, (intptr_t) TASK_VAL(t));
                    354: #else
                    355:        EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_ADD | EV_CLEAR, 
                    356:                        NOTE_EXIT | NOTE_FORK | NOTE_EXEC | NOTE_TRACK, 0, (void*) TASK_VAL(t));
                    357: #endif
                    358:        if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                    359:                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                    360:                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
                    361:                else
                    362:                        LOGERR;
                    363:                return (void*) -1;
                    364:        }
                    365: 
                    366:        return NULL;
                    367: }
                    368: 
                    369: /*
                    370:  * sched_hook_signal() - Default SIGNAL hook
                    371:  *
                    372:  * @task = current task
                    373:  * @arg = unused
                    374:  * return: <0 errors and 0 ok
                    375:  */
                    376: void *
                    377: sched_hook_signal(void *task, void *arg __unused)
                    378: {
                    379:        sched_task_t *t = task;
                    380:        struct kevent chg[1];
                    381:        struct timespec timeout = { 0, 0 };
                    382: 
                    383:        if (!t || !TASK_ROOT(t))
                    384:                return (void*) -1;
                    385: 
                    386: #ifdef __NetBSD__
                    387:        EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_ADD, 0, 0, (intptr_t) TASK_VAL(t));
                    388: #else
                    389:        EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_ADD, 0, 0, (void*) TASK_VAL(t));
                    390: #endif
                    391:        if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                    392:                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                    393:                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
                    394:                else
                    395:                        LOGERR;
                    396:                return (void*) -1;
                    397:        }
                    398: 
                    399:        return NULL;
                    400: }
                    401: 
                    402: /*
                    403:  * sched_hook_user() - Default USER hook
                    404:  *
                    405:  * @task = current task
                    406:  * @arg = unused
                    407:  * return: <0 errors and 0 ok
                    408:  */
                    409: #ifdef EVFILT_USER
                    410: void *
                    411: sched_hook_user(void *task, void *arg __unused)
                    412: {
                    413:        sched_task_t *t = task;
                    414:        struct kevent chg[1];
                    415:        struct timespec timeout = { 0, 0 };
                    416: 
                    417:        if (!t || !TASK_ROOT(t))
                    418:                return (void*) -1;
                    419: 
                    420: #ifdef __NetBSD__
                    421:        EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_ADD | EV_CLEAR, TASK_DATLEN(t), 
                    422:                        0, (intptr_t) TASK_VAL(t));
                    423: #else
                    424:        EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_ADD | EV_CLEAR, TASK_DATLEN(t), 
                    425:                        0, (void*) TASK_VAL(t));
                    426: #endif
                    427:        if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                    428:                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                    429:                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
                    430:                else
                    431:                        LOGERR;
                    432:                return (void*) -1;
                    433:        }
                    434: 
                    435:        return NULL;
                    436: }
                    437: #endif
                    438: 
                    439: /*
1.1       misho     440:  * sched_hook_fetch() - Default FETCH hook
1.5       misho     441:  *
1.1       misho     442:  * @root = root task
                    443:  * @arg = unused
                    444:  * return: NULL error or !=NULL fetched task
                    445:  */
                    446: void *
                    447: sched_hook_fetch(void *root, void *arg __unused)
                    448: {
                    449:        sched_root_task_t *r = root;
1.6       misho     450:        sched_task_t *task, *tmp;
1.4       misho     451:        struct timespec now, m, mtmp;
                    452:        struct timespec *timeout;
1.1       misho     453:        struct kevent evt[1], res[KQ_EVENTS];
1.9       misho     454:        register int i, flg;
1.1       misho     455:        int en;
1.10.2.2  misho     456: #ifdef EVFILT_AIO
1.10.2.4! misho     457:        int len;
1.10.2.2  misho     458:        struct aiocb *acb;
                    459: #endif
1.1       misho     460: 
1.6       misho     461:        if (!r)
1.1       misho     462:                return NULL;
                    463: 
                    464:        /* get new task by queue priority */
                    465:        while ((task = TAILQ_FIRST(&r->root_event))) {
1.4       misho     466: #ifdef HAVE_LIBPTHREAD
                    467:                pthread_mutex_lock(&r->root_mtx[taskEVENT]);
                    468: #endif
1.1       misho     469:                TAILQ_REMOVE(&r->root_event, task, task_node);
1.4       misho     470: #ifdef HAVE_LIBPTHREAD
                    471:                pthread_mutex_unlock(&r->root_mtx[taskEVENT]);
                    472: #endif
1.1       misho     473:                task->task_type = taskUNUSE;
1.4       misho     474: #ifdef HAVE_LIBPTHREAD
                    475:                pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
                    476: #endif
1.1       misho     477:                TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4       misho     478: #ifdef HAVE_LIBPTHREAD
                    479:                pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
                    480: #endif
1.1       misho     481:                return task;
                    482:        }
                    483:        while ((task = TAILQ_FIRST(&r->root_ready))) {
1.4       misho     484: #ifdef HAVE_LIBPTHREAD
                    485:                pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    486: #endif
1.1       misho     487:                TAILQ_REMOVE(&r->root_ready, task, task_node);
1.4       misho     488: #ifdef HAVE_LIBPTHREAD
                    489:                pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    490: #endif
1.1       misho     491:                task->task_type = taskUNUSE;
1.4       misho     492: #ifdef HAVE_LIBPTHREAD
                    493:                pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
                    494: #endif
1.1       misho     495:                TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4       misho     496: #ifdef HAVE_LIBPTHREAD
                    497:                pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
                    498: #endif
1.1       misho     499:                return task;
                    500:        }
                    501: 
                    502: #ifdef TIMER_WITHOUT_SORT
1.4       misho     503:        clock_gettime(CLOCK_MONOTONIC, &now);
1.1       misho     504: 
1.4       misho     505:        sched_timespecclear(&r->root_wait);
1.1       misho     506:        TAILQ_FOREACH(task, &r->root_timer, task_node) {
1.4       misho     507:                if (!sched_timespecisset(&r->root_wait))
                    508:                        r->root_wait = TASK_TS(task);
                    509:                else if (sched_timespeccmp(&TASK_TS(task), &r->root_wait, -) < 0)
                    510:                        r->root_wait = TASK_TS(task);
1.1       misho     511:        }
                    512: 
                    513:        if (TAILQ_FIRST(&r->root_timer)) {
                    514:                m = r->root_wait;
1.4       misho     515:                sched_timespecsub(&m, &now, &mtmp);
1.1       misho     516:                r->root_wait = mtmp;
                    517:        } else {
                    518:                /* set wait INFTIM */
1.4       misho     519:                sched_timespecinf(&r->root_wait);
1.1       misho     520:        }
                    521: #else
                    522:        if (!TAILQ_FIRST(&r->root_eventlo) && (task = TAILQ_FIRST(&r->root_timer))) {
1.4       misho     523:                clock_gettime(CLOCK_MONOTONIC, &now);
1.1       misho     524: 
1.4       misho     525:                m = TASK_TS(task);
                    526:                sched_timespecsub(&m, &now, &mtmp);
1.1       misho     527:                r->root_wait = mtmp;
                    528:        } else {
                    529:                /* set wait INFTIM */
1.4       misho     530:                sched_timespecinf(&r->root_wait);
1.1       misho     531:        }
                    532: #endif
                    533:        /* if present member of eventLo, set NOWAIT */
                    534:        if (TAILQ_FIRST(&r->root_eventlo))
1.4       misho     535:                sched_timespecclear(&r->root_wait);
1.1       misho     536: 
1.4       misho     537:        if (r->root_wait.tv_sec != -1 && r->root_wait.tv_nsec != -1)
                    538:                timeout = &r->root_wait;
                    539:        else if (sched_timespecisinf(&r->root_poll))
1.1       misho     540:                timeout = NULL;
1.4       misho     541:        else
                    542:                timeout = &r->root_poll;
1.1       misho     543:        if ((en = kevent(r->root_kq, NULL, 0, res, KQ_EVENTS, timeout)) == -1) {
1.3       misho     544:                if (r->root_hooks.hook_exec.exception) {
                    545:                        if (r->root_hooks.hook_exec.exception(r, NULL))
                    546:                                return NULL;
1.6       misho     547:                } else if (errno != EINTR)
1.3       misho     548:                        LOGERR;
1.2       misho     549:                return NULL;
1.1       misho     550:        }
                    551: 
1.4       misho     552:        now.tv_sec = now.tv_nsec = 0;
1.1       misho     553:        /* Go and catch the cat into pipes ... */
                    554:        for (i = 0; i < en; i++) {
                    555:                memcpy(evt, &res[i], sizeof evt);
                    556:                evt->flags = EV_DELETE;
                    557:                /* Put read/write task to ready queue */
                    558:                switch (res[i].filter) {
                    559:                        case EVFILT_READ:
1.9       misho     560:                                flg = 0;
1.6       misho     561:                                TAILQ_FOREACH_SAFE(task, &r->root_read, task_node, tmp) {
1.3       misho     562:                                        if (TASK_FD(task) != ((intptr_t) res[i].udata))
1.1       misho     563:                                                continue;
1.9       misho     564:                                        else
                    565:                                                flg++;
1.1       misho     566:                                        /* remove read handle */
1.4       misho     567: #ifdef HAVE_LIBPTHREAD
                    568:                                        pthread_mutex_lock(&r->root_mtx[taskREAD]);
                    569: #endif
1.1       misho     570:                                        TAILQ_REMOVE(&r->root_read, task, task_node);
1.4       misho     571: #ifdef HAVE_LIBPTHREAD
                    572:                                        pthread_mutex_unlock(&r->root_mtx[taskREAD]);
                    573: #endif
1.3       misho     574:                                        if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
                    575:                                                if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
                    576:                                                        task->task_type = taskUNUSE;
1.4       misho     577: #ifdef HAVE_LIBPTHREAD
                    578:                                                        pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
                    579: #endif
1.3       misho     580:                                                        TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4       misho     581: #ifdef HAVE_LIBPTHREAD
                    582:                                                        pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
                    583: #endif
1.3       misho     584:                                                } else {
                    585:                                                        task->task_type = taskREADY;
1.4       misho     586: #ifdef HAVE_LIBPTHREAD
                    587:                                                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    588: #endif
1.3       misho     589:                                                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4       misho     590: #ifdef HAVE_LIBPTHREAD
                    591:                                                        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    592: #endif
1.3       misho     593:                                                }
                    594:                                        } else {
1.2       misho     595:                                                task->task_type = taskREADY;
1.4       misho     596: #ifdef HAVE_LIBPTHREAD
                    597:                                                pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    598: #endif
1.2       misho     599:                                                TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4       misho     600: #ifdef HAVE_LIBPTHREAD
                    601:                                                pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    602: #endif
1.3       misho     603:                                        }
1.1       misho     604:                                }
1.9       misho     605:                                /* if match at least 2, don't remove resouce of event */
                    606:                                if (flg > 1)
                    607:                                        evt->flags ^= evt->flags;
1.1       misho     608:                                break;
                    609:                        case EVFILT_WRITE:
1.9       misho     610:                                flg = 0;
1.6       misho     611:                                TAILQ_FOREACH_SAFE(task, &r->root_write, task_node, tmp) {
1.3       misho     612:                                        if (TASK_FD(task) != ((intptr_t) res[i].udata))
1.1       misho     613:                                                continue;
1.9       misho     614:                                        else
                    615:                                                flg++;
1.1       misho     616:                                        /* remove write handle */
1.4       misho     617: #ifdef HAVE_LIBPTHREAD
                    618:                                        pthread_mutex_lock(&r->root_mtx[taskWRITE]);
                    619: #endif
1.1       misho     620:                                        TAILQ_REMOVE(&r->root_write, task, task_node);
1.4       misho     621: #ifdef HAVE_LIBPTHREAD
                    622:                                        pthread_mutex_unlock(&r->root_mtx[taskWRITE]);
                    623: #endif
1.3       misho     624:                                        if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
                    625:                                                if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
                    626:                                                        task->task_type = taskUNUSE;
1.4       misho     627: #ifdef HAVE_LIBPTHREAD
                    628:                                                        pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
                    629: #endif
1.3       misho     630:                                                        TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4       misho     631: #ifdef HAVE_LIBPTHREAD
                    632:                                                        pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
                    633: #endif
1.3       misho     634:                                                } else {
                    635:                                                        task->task_type = taskREADY;
1.4       misho     636: #ifdef HAVE_LIBPTHREAD
                    637:                                                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    638: #endif
1.3       misho     639:                                                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4       misho     640: #ifdef HAVE_LIBPTHREAD
                    641:                                                        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    642: #endif
1.3       misho     643:                                                }
                    644:                                        } else {
1.2       misho     645:                                                task->task_type = taskREADY;
1.4       misho     646: #ifdef HAVE_LIBPTHREAD
                    647:                                                pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    648: #endif
1.2       misho     649:                                                TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4       misho     650: #ifdef HAVE_LIBPTHREAD
                    651:                                                pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    652: #endif
1.3       misho     653:                                        }
1.1       misho     654:                                }
1.9       misho     655:                                /* if match at least 2, don't remove resouce of event */
                    656:                                if (flg > 1)
                    657:                                        evt->flags ^= evt->flags;
1.1       misho     658:                                break;
1.7       misho     659:                        case EVFILT_TIMER:
1.9       misho     660:                                flg = 0;
1.7       misho     661:                                TAILQ_FOREACH_SAFE(task, &r->root_alarm, task_node, tmp) {
                    662:                                        if ((uintptr_t) TASK_DATA(task) != ((uintptr_t) res[i].udata))
                    663:                                                continue;
1.9       misho     664:                                        else
                    665:                                                flg++;
1.7       misho     666:                                        /* remove alarm handle */
                    667: #ifdef HAVE_LIBPTHREAD
                    668:                                        pthread_mutex_lock(&r->root_mtx[taskALARM]);
                    669: #endif
                    670:                                        TAILQ_REMOVE(&r->root_alarm, task, task_node);
                    671: #ifdef HAVE_LIBPTHREAD
                    672:                                        pthread_mutex_unlock(&r->root_mtx[taskALARM]);
                    673: #endif
                    674:                                        task->task_type = taskREADY;
                    675: #ifdef HAVE_LIBPTHREAD
                    676:                                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    677: #endif
                    678:                                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
                    679: #ifdef HAVE_LIBPTHREAD
                    680:                                        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    681: #endif
                    682:                                }
1.9       misho     683:                                /* if match at least 2, don't remove resouce of event */
                    684:                                if (flg > 1)
                    685:                                        evt->flags ^= evt->flags;
1.7       misho     686:                                break;
1.8       misho     687:                        case EVFILT_VNODE:
1.9       misho     688:                                flg = 0;
1.8       misho     689:                                TAILQ_FOREACH_SAFE(task, &r->root_node, task_node, tmp) {
                    690:                                        if (TASK_FD(task) != ((intptr_t) res[i].udata))
                    691:                                                continue;
                    692:                                        else {
1.9       misho     693:                                                flg++;
1.8       misho     694:                                                TASK_DATA(task) = (void*) (uintptr_t) res[i].data;
                    695:                                                TASK_DATLEN(task) = res[i].fflags;
                    696:                                        }
                    697:                                        /* remove node handle */
                    698: #ifdef HAVE_LIBPTHREAD
                    699:                                        pthread_mutex_lock(&r->root_mtx[taskNODE]);
                    700: #endif
                    701:                                        TAILQ_REMOVE(&r->root_node, task, task_node);
                    702: #ifdef HAVE_LIBPTHREAD
                    703:                                        pthread_mutex_unlock(&r->root_mtx[taskNODE]);
                    704: #endif
                    705:                                        task->task_type = taskREADY;
                    706: #ifdef HAVE_LIBPTHREAD
                    707:                                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    708: #endif
                    709:                                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
                    710: #ifdef HAVE_LIBPTHREAD
                    711:                                        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    712: #endif
                    713:                                }
1.9       misho     714:                                /* if match at least 2, don't remove resouce of event */
                    715:                                if (flg > 1)
                    716:                                        evt->flags ^= evt->flags;
1.8       misho     717:                                break;
                    718:                        case EVFILT_PROC:
1.9       misho     719:                                flg = 0;
1.8       misho     720:                                TAILQ_FOREACH_SAFE(task, &r->root_proc, task_node, tmp) {
                    721:                                        if (TASK_VAL(task) != ((uintptr_t) res[i].udata))
                    722:                                                continue;
                    723:                                        else {
1.9       misho     724:                                                flg++;
1.8       misho     725:                                                TASK_DATA(task) = (void*) (uintptr_t) res[i].data;
                    726:                                                TASK_DATLEN(task) = res[i].fflags;
                    727:                                        }
                    728:                                        /* remove proc handle */
                    729: #ifdef HAVE_LIBPTHREAD
                    730:                                        pthread_mutex_lock(&r->root_mtx[taskPROC]);
                    731: #endif
                    732:                                        TAILQ_REMOVE(&r->root_proc, task, task_node);
                    733: #ifdef HAVE_LIBPTHREAD
                    734:                                        pthread_mutex_unlock(&r->root_mtx[taskPROC]);
                    735: #endif
                    736:                                        task->task_type = taskREADY;
                    737: #ifdef HAVE_LIBPTHREAD
                    738:                                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    739: #endif
                    740:                                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
                    741: #ifdef HAVE_LIBPTHREAD
                    742:                                        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    743: #endif
                    744:                                }
1.9       misho     745:                                /* if match at least 2, don't remove resouce of event */
                    746:                                if (flg > 1)
                    747:                                        evt->flags ^= evt->flags;
1.8       misho     748:                                break;
                    749:                        case EVFILT_SIGNAL:
1.9       misho     750:                                flg = 0;
1.8       misho     751:                                TAILQ_FOREACH_SAFE(task, &r->root_signal, task_node, tmp) {
                    752:                                        if (TASK_VAL(task) != ((uintptr_t) res[i].udata))
                    753:                                                continue;
1.9       misho     754:                                        else
                    755:                                                flg++;
1.8       misho     756:                                        /* remove signal handle */
                    757: #ifdef HAVE_LIBPTHREAD
                    758:                                        pthread_mutex_lock(&r->root_mtx[taskSIGNAL]);
                    759: #endif
                    760:                                        TAILQ_REMOVE(&r->root_signal, task, task_node);
                    761: #ifdef HAVE_LIBPTHREAD
                    762:                                        pthread_mutex_unlock(&r->root_mtx[taskSIGNAL]);
                    763: #endif
                    764:                                        task->task_type = taskREADY;
                    765: #ifdef HAVE_LIBPTHREAD
                    766:                                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    767: #endif
                    768:                                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
                    769: #ifdef HAVE_LIBPTHREAD
                    770:                                        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    771: #endif
                    772:                                }
1.9       misho     773:                                /* if match at least 2, don't remove resouce of event */
                    774:                                if (flg > 1)
                    775:                                        evt->flags ^= evt->flags;
1.8       misho     776:                                break;
1.10.2.2  misho     777: #ifdef EVFILT_AIO
                    778:                        case EVFILT_AIO:
                    779:                                flg = 0;
                    780:                                TAILQ_FOREACH_SAFE(task, &r->root_aio, task_node, tmp) {
1.10.2.4! misho     781:                                        acb = (struct aiocb*) TASK_VAL(task);
1.10.2.2  misho     782:                                        if (acb != ((struct aiocb*) res[i].ident) || 
                    783:                                                        acb->aio_sigevent.sigev_value.sival_ptr != res[i].udata)
                    784:                                                continue;
                    785:                                        else
                    786:                                                flg++;
                    787:                                        /* remove user handle */
                    788: #ifdef HAVE_LIBPTHREAD
                    789:                                        pthread_mutex_lock(&r->root_mtx[taskAIO]);
                    790: #endif
                    791:                                        TAILQ_REMOVE(&r->root_aio, task, task_node);
                    792: #ifdef HAVE_LIBPTHREAD
                    793:                                        pthread_mutex_unlock(&r->root_mtx[taskAIO]);
                    794: #endif
                    795:                                        task->task_type = taskREADY;
                    796: #ifdef HAVE_LIBPTHREAD
                    797:                                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    798: #endif
                    799:                                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
                    800: #ifdef HAVE_LIBPTHREAD
                    801:                                        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    802: #endif
1.10.2.4! misho     803:                                        if ((len = aio_return(acb)) != -1) {
        !           804:                                                if (lseek(acb->aio_fildes, acb->aio_offset + len, 
        !           805:                                                                        SEEK_CUR) == -1)
        !           806:                                                        LOGERR;
        !           807:                                        } else
        !           808:                                                LOGERR;
        !           809: 
        !           810:                                        free(acb);
        !           811:                                        TASK_VAL(task) = (u_long) len;
1.10.2.2  misho     812:                                }
                    813:                                /* if match at least 2, don't remove resouce of event */
                    814:                                if (flg > 1)
                    815:                                        evt->flags ^= evt->flags;
                    816:                                break;
                    817: #endif /* EVFILT_AIO */
1.8       misho     818: #ifdef EVFILT_USER
                    819:                        case EVFILT_USER:
1.9       misho     820:                                flg = 0;
1.8       misho     821:                                TAILQ_FOREACH_SAFE(task, &r->root_user, task_node, tmp) {
                    822:                                        if (TASK_VAL(task) != ((uintptr_t) res[i].udata))
                    823:                                                continue;
                    824:                                        else {
1.9       misho     825:                                                flg++;
1.8       misho     826:                                                TASK_DATA(task) = (void*) res[i].data;
                    827:                                                TASK_DATLEN(task) = res[i].fflags;
                    828:                                        }
                    829:                                        /* remove user handle */
                    830: #ifdef HAVE_LIBPTHREAD
                    831:                                        pthread_mutex_lock(&r->root_mtx[taskUSER]);
                    832: #endif
                    833:                                        TAILQ_REMOVE(&r->root_user, task, task_node);
                    834: #ifdef HAVE_LIBPTHREAD
                    835:                                        pthread_mutex_unlock(&r->root_mtx[taskUSER]);
                    836: #endif
                    837:                                        task->task_type = taskREADY;
                    838: #ifdef HAVE_LIBPTHREAD
                    839:                                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    840: #endif
                    841:                                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
                    842: #ifdef HAVE_LIBPTHREAD
                    843:                                        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    844: #endif
                    845:                                }
1.9       misho     846:                                /* if match at least 2, don't remove resouce of event */
                    847:                                if (flg > 1)
                    848:                                        evt->flags ^= evt->flags;
1.8       misho     849:                                break;
1.10.2.2  misho     850: #endif /* EVFILT_USER */
1.1       misho     851:                }
1.4       misho     852:                if (kevent(r->root_kq, evt, 1, NULL, 0, &now) == -1) {
1.3       misho     853:                        if (r->root_hooks.hook_exec.exception) {
                    854:                                if (r->root_hooks.hook_exec.exception(r, NULL))
                    855:                                        return NULL;
                    856:                        } else
                    857:                                LOGERR;
                    858:                }
1.1       misho     859:        }
                    860: 
1.2       misho     861:        /* timer update & put in ready queue */
1.4       misho     862:        clock_gettime(CLOCK_MONOTONIC, &now);
1.1       misho     863: 
1.6       misho     864:        TAILQ_FOREACH_SAFE(task, &r->root_timer, task_node, tmp)
1.4       misho     865:                if (sched_timespeccmp(&now, &TASK_TS(task), -) >= 0) {
                    866: #ifdef HAVE_LIBPTHREAD
                    867:                        pthread_mutex_lock(&r->root_mtx[taskTIMER]);
                    868: #endif
1.1       misho     869:                        TAILQ_REMOVE(&r->root_timer, task, task_node);
1.4       misho     870: #ifdef HAVE_LIBPTHREAD
                    871:                        pthread_mutex_unlock(&r->root_mtx[taskTIMER]);
                    872: #endif
1.1       misho     873:                        task->task_type = taskREADY;
1.4       misho     874: #ifdef HAVE_LIBPTHREAD
                    875:                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    876: #endif
1.1       misho     877:                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4       misho     878: #ifdef HAVE_LIBPTHREAD
                    879:                        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    880: #endif
1.1       misho     881:                }
                    882: 
                    883:        /* put eventlo priority task to ready queue, if there is no ready task or 
                    884:                reach max missed fetch-rotate */
                    885:        if ((task = TAILQ_FIRST(&r->root_eventlo))) {
                    886:                if (!TAILQ_FIRST(&r->root_ready) || r->root_eventlo_miss > MAX_EVENTLO_MISS) {
                    887:                        r->root_eventlo_miss = 0;
                    888: 
1.4       misho     889: #ifdef HAVE_LIBPTHREAD
                    890:                        pthread_mutex_lock(&r->root_mtx[taskEVENTLO]);
                    891: #endif
1.1       misho     892:                        TAILQ_REMOVE(&r->root_eventlo, task, task_node);
1.4       misho     893: #ifdef HAVE_LIBPTHREAD
                    894:                        pthread_mutex_unlock(&r->root_mtx[taskEVENTLO]);
                    895: #endif
1.1       misho     896:                        task->task_type = taskREADY;
1.4       misho     897: #ifdef HAVE_LIBPTHREAD
                    898:                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    899: #endif
1.1       misho     900:                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4       misho     901: #ifdef HAVE_LIBPTHREAD
                    902:                        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    903: #endif
1.1       misho     904:                } else
                    905:                        r->root_eventlo_miss++;
                    906:        } else
                    907:                r->root_eventlo_miss = 0;
                    908: 
                    909:        /* OK, lets get ready task !!! */
1.6       misho     910:        task = TAILQ_FIRST(&r->root_ready);
                    911:        if (!(task))
                    912:                return NULL;
                    913: 
1.4       misho     914: #ifdef HAVE_LIBPTHREAD
                    915:        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    916: #endif
1.1       misho     917:        TAILQ_REMOVE(&r->root_ready, task, task_node);
1.4       misho     918: #ifdef HAVE_LIBPTHREAD
                    919:        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    920: #endif
1.1       misho     921:        task->task_type = taskUNUSE;
1.4       misho     922: #ifdef HAVE_LIBPTHREAD
                    923:        pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
                    924: #endif
1.1       misho     925:        TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4       misho     926: #ifdef HAVE_LIBPTHREAD
                    927:        pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
                    928: #endif
1.1       misho     929:        return task;
                    930: }
1.3       misho     931: 
                    932: /*
                    933:  * sched_hook_exception() - Default EXCEPTION hook
1.5       misho     934:  *
1.3       misho     935:  * @root = root task
                    936:  * @arg = custom handling: if arg == EV_EOF or other value; default: arg == NULL log errno
                    937:  * return: <0 errors and 0 ok
                    938:  */
                    939: void *
                    940: sched_hook_exception(void *root, void *arg)
                    941: {
                    942:        sched_root_task_t *r = root;
                    943: 
1.6       misho     944:        if (!r)
1.3       misho     945:                return NULL;
                    946: 
                    947:        /* custom exception handling ... */
                    948:        if (arg) {
                    949:                if (arg == (void*) EV_EOF)
                    950:                        return NULL;
                    951:                return (void*) -1;      /* raise scheduler error!!! */
                    952:        }
                    953: 
                    954:        /* if error hook exists */
                    955:        if (r->root_hooks.hook_root.error)
                    956:                return (r->root_hooks.hook_root.error(root, (void*) ((intptr_t) errno)));
                    957: 
                    958:        /* default case! */
                    959:        LOGERR;
                    960:        return NULL;
                    961: }
1.5       misho     962: 
                    963: /*
                    964:  * sched_hook_condition() - Default CONDITION hook
                    965:  *
                    966:  * @root = root task
                    967:  * @arg = killState from schedRun()
                    968:  * return: NULL kill scheduler loop or !=NULL ok
                    969:  */
                    970: void *
                    971: sched_hook_condition(void *root, void *arg)
                    972: {
                    973:        sched_root_task_t *r = root;
                    974: 
1.6       misho     975:        if (!r)
1.5       misho     976:                return NULL;
                    977: 
                    978:        return (void*) (r->root_cond - *(intptr_t*) arg);
                    979: }

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