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

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.6.4.1 ! misho       6: * $Id: hooks.c,v 1.6 2012/05/14 12:09:13 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.6.4.1 ! misho     110:        uintptr_t ident;
1.1       misho     111: 
1.6       misho     112:        if (!t || !TASK_ROOT(t))
1.1       misho     113:                return (void*) -1;
                    114: 
1.4       misho     115:        switch (TASK_TYPE(t)) {
1.1       misho     116:                case taskREAD:
1.2       misho     117: #ifdef __NetBSD__
                    118:                        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_DELETE, 0, 0, (intptr_t) TASK_FD(t));
                    119: #else
                    120:                        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_DELETE, 0, 0, (void*) TASK_FD(t));
                    121: #endif
1.4       misho     122:                        kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout);
1.1       misho     123:                        break;
                    124:                case taskWRITE:
1.2       misho     125: #ifdef __NetBSD__
                    126:                        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_DELETE, 0, 0, (intptr_t) TASK_FD(t));
                    127: #else
                    128:                        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_DELETE, 0, 0, (void*) TASK_FD(t));
                    129: #endif
1.4       misho     130:                        kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout);
1.1       misho     131:                        break;
1.6.4.1 ! misho     132:                case taskALARM:
        !           133:                        if (TASK_DATA(t))
        !           134:                                ident = (uintptr_t) TASK_DATA(t);
        !           135:                        else
        !           136:                                ident = (uintptr_t) TASK_FUNC(t);
        !           137: #ifdef __NetBSD__
        !           138:                        EV_SET(&chg[0], ident, EVFILT_TIMER, EV_DELETE, 0, 0, (intptr_t) ident);
        !           139: #else
        !           140:                        EV_SET(&chg[0], ident, EVFILT_TIMER, EV_DELETE, 0, 0, (void*) ident);
        !           141: #endif
        !           142:                        kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout);
        !           143:                        break;
1.1       misho     144:                default:
                    145:                        break;
                    146:        }
                    147: 
                    148:        return NULL;
                    149: }
                    150: 
                    151: /*
                    152:  * sched_hook_read() - Default READ hook
1.5       misho     153:  *
1.1       misho     154:  * @task = current task
                    155:  * @arg = unused
                    156:  * return: <0 errors and 0 ok
                    157:  */
                    158: void *
                    159: sched_hook_read(void *task, void *arg __unused)
                    160: {
                    161:        sched_task_t *t = task;
                    162:        struct kevent chg[1];
1.2       misho     163:        struct timespec timeout = { 0, 0 };
1.1       misho     164: 
1.6       misho     165:        if (!t || !TASK_ROOT(t))
1.1       misho     166:                return (void*) -1;
                    167: 
1.2       misho     168: #ifdef __NetBSD__
                    169:        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD, 0, 0, (intptr_t) TASK_FD(t));
                    170: #else
                    171:        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD, 0, 0, (void*) TASK_FD(t));
                    172: #endif
1.4       misho     173:        if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                    174:                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                    175:                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
1.3       misho     176:                else
                    177:                        LOGERR;
1.1       misho     178:                return (void*) -1;
                    179:        }
                    180: 
                    181:        return NULL;
                    182: }
                    183: 
                    184: /*
                    185:  * sched_hook_write() - Default WRITE hook
1.5       misho     186:  *
1.1       misho     187:  * @task = current task
                    188:  * @arg = unused
                    189:  * return: <0 errors and 0 ok
                    190:  */
                    191: void *
                    192: sched_hook_write(void *task, void *arg __unused)
                    193: {
                    194:        sched_task_t *t = task;
                    195:        struct kevent chg[1];
1.2       misho     196:        struct timespec timeout = { 0, 0 };
1.1       misho     197: 
1.6       misho     198:        if (!t || !TASK_ROOT(t))
1.1       misho     199:                return (void*) -1;
                    200: 
1.2       misho     201: #ifdef __NetBSD__
                    202:        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD, 0, 0, (intptr_t) TASK_FD(t));
                    203: #else
                    204:        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD, 0, 0, (void*) TASK_FD(t));
                    205: #endif
1.4       misho     206:        if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                    207:                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                    208:                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
1.3       misho     209:                else
                    210:                        LOGERR;
1.1       misho     211:                return (void*) -1;
                    212:        }
                    213: 
                    214:        return NULL;
                    215: }
                    216: 
                    217: /*
1.6.4.1 ! misho     218:  * sched_hook_alarm() - Default ALARM hook
        !           219:  *
        !           220:  * @task = current task
        !           221:  * @arg = unused
        !           222:  * return: <0 errors and 0 ok
        !           223:  */
        !           224: void *
        !           225: sched_hook_alarm(void *task, void *arg __unused)
        !           226: {
        !           227:        sched_task_t *t = task;
        !           228:        struct kevent chg[1];
        !           229:        struct timespec timeout = { 0, 0 };
        !           230:        uintptr_t ident;
        !           231: 
        !           232:        if (!t || !TASK_ROOT(t))
        !           233:                return (void*) -1;
        !           234: 
        !           235:        if (TASK_DATA(t))
        !           236:                ident = (uintptr_t) TASK_DATA(t);
        !           237:        else
        !           238:                ident = (uintptr_t) TASK_FUNC(t);
        !           239: 
        !           240: #ifdef __NetBSD__
        !           241:        EV_SET(&chg[0], ident, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 0, (intptr_t) ident);
        !           242: #else
        !           243:        EV_SET(&chg[0], ident, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 0, (void*) ident);
        !           244: #endif
        !           245:        if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
        !           246:                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
        !           247:                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
        !           248:                else
        !           249:                        LOGERR;
        !           250:                return (void*) -1;
        !           251:        }
        !           252: 
        !           253:        return NULL;
        !           254: }
        !           255: 
        !           256: /*
1.1       misho     257:  * sched_hook_fetch() - Default FETCH hook
1.5       misho     258:  *
1.1       misho     259:  * @root = root task
                    260:  * @arg = unused
                    261:  * return: NULL error or !=NULL fetched task
                    262:  */
                    263: void *
                    264: sched_hook_fetch(void *root, void *arg __unused)
                    265: {
                    266:        sched_root_task_t *r = root;
1.6       misho     267:        sched_task_t *task, *tmp;
1.4       misho     268:        struct timespec now, m, mtmp;
                    269:        struct timespec *timeout;
1.1       misho     270:        struct kevent evt[1], res[KQ_EVENTS];
                    271:        register int i;
                    272:        int en;
1.6.4.1 ! misho     273:        uintptr_t ident;
1.1       misho     274: 
1.6       misho     275:        if (!r)
1.1       misho     276:                return NULL;
                    277: 
                    278:        /* get new task by queue priority */
                    279:        while ((task = TAILQ_FIRST(&r->root_event))) {
1.4       misho     280: #ifdef HAVE_LIBPTHREAD
                    281:                pthread_mutex_lock(&r->root_mtx[taskEVENT]);
                    282: #endif
1.1       misho     283:                TAILQ_REMOVE(&r->root_event, task, task_node);
1.4       misho     284: #ifdef HAVE_LIBPTHREAD
                    285:                pthread_mutex_unlock(&r->root_mtx[taskEVENT]);
                    286: #endif
1.1       misho     287:                task->task_type = taskUNUSE;
1.4       misho     288: #ifdef HAVE_LIBPTHREAD
                    289:                pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
                    290: #endif
1.1       misho     291:                TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4       misho     292: #ifdef HAVE_LIBPTHREAD
                    293:                pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
                    294: #endif
1.1       misho     295:                return task;
                    296:        }
                    297:        while ((task = TAILQ_FIRST(&r->root_ready))) {
1.4       misho     298: #ifdef HAVE_LIBPTHREAD
                    299:                pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    300: #endif
1.1       misho     301:                TAILQ_REMOVE(&r->root_ready, task, task_node);
1.4       misho     302: #ifdef HAVE_LIBPTHREAD
                    303:                pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    304: #endif
1.1       misho     305:                task->task_type = taskUNUSE;
1.4       misho     306: #ifdef HAVE_LIBPTHREAD
                    307:                pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
                    308: #endif
1.1       misho     309:                TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4       misho     310: #ifdef HAVE_LIBPTHREAD
                    311:                pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
                    312: #endif
1.1       misho     313:                return task;
                    314:        }
                    315: 
                    316: #ifdef TIMER_WITHOUT_SORT
1.4       misho     317:        clock_gettime(CLOCK_MONOTONIC, &now);
1.1       misho     318: 
1.4       misho     319:        sched_timespecclear(&r->root_wait);
1.1       misho     320:        TAILQ_FOREACH(task, &r->root_timer, task_node) {
1.4       misho     321:                if (!sched_timespecisset(&r->root_wait))
                    322:                        r->root_wait = TASK_TS(task);
                    323:                else if (sched_timespeccmp(&TASK_TS(task), &r->root_wait, -) < 0)
                    324:                        r->root_wait = TASK_TS(task);
1.1       misho     325:        }
                    326: 
                    327:        if (TAILQ_FIRST(&r->root_timer)) {
                    328:                m = r->root_wait;
1.4       misho     329:                sched_timespecsub(&m, &now, &mtmp);
1.1       misho     330:                r->root_wait = mtmp;
                    331:        } else {
                    332:                /* set wait INFTIM */
1.4       misho     333:                sched_timespecinf(&r->root_wait);
1.1       misho     334:        }
                    335: #else
                    336:        if (!TAILQ_FIRST(&r->root_eventlo) && (task = TAILQ_FIRST(&r->root_timer))) {
1.4       misho     337:                clock_gettime(CLOCK_MONOTONIC, &now);
1.1       misho     338: 
1.4       misho     339:                m = TASK_TS(task);
                    340:                sched_timespecsub(&m, &now, &mtmp);
1.1       misho     341:                r->root_wait = mtmp;
                    342:        } else {
                    343:                /* set wait INFTIM */
1.4       misho     344:                sched_timespecinf(&r->root_wait);
1.1       misho     345:        }
                    346: #endif
                    347:        /* if present member of eventLo, set NOWAIT */
                    348:        if (TAILQ_FIRST(&r->root_eventlo))
1.4       misho     349:                sched_timespecclear(&r->root_wait);
1.1       misho     350: 
1.4       misho     351:        if (r->root_wait.tv_sec != -1 && r->root_wait.tv_nsec != -1)
                    352:                timeout = &r->root_wait;
                    353:        else if (sched_timespecisinf(&r->root_poll))
1.1       misho     354:                timeout = NULL;
1.4       misho     355:        else
                    356:                timeout = &r->root_poll;
1.1       misho     357:        if ((en = kevent(r->root_kq, NULL, 0, res, KQ_EVENTS, timeout)) == -1) {
1.3       misho     358:                if (r->root_hooks.hook_exec.exception) {
                    359:                        if (r->root_hooks.hook_exec.exception(r, NULL))
                    360:                                return NULL;
1.6       misho     361:                } else if (errno != EINTR)
1.3       misho     362:                        LOGERR;
1.2       misho     363:                return NULL;
1.1       misho     364:        }
                    365: 
1.4       misho     366:        now.tv_sec = now.tv_nsec = 0;
1.1       misho     367:        /* Go and catch the cat into pipes ... */
                    368:        for (i = 0; i < en; i++) {
                    369:                memcpy(evt, &res[i], sizeof evt);
                    370:                evt->flags = EV_DELETE;
                    371:                /* Put read/write task to ready queue */
                    372:                switch (res[i].filter) {
                    373:                        case EVFILT_READ:
1.6       misho     374:                                TAILQ_FOREACH_SAFE(task, &r->root_read, task_node, tmp) {
1.3       misho     375:                                        if (TASK_FD(task) != ((intptr_t) res[i].udata))
1.1       misho     376:                                                continue;
                    377:                                        /* remove read handle */
1.4       misho     378: #ifdef HAVE_LIBPTHREAD
                    379:                                        pthread_mutex_lock(&r->root_mtx[taskREAD]);
                    380: #endif
1.1       misho     381:                                        TAILQ_REMOVE(&r->root_read, task, task_node);
1.4       misho     382: #ifdef HAVE_LIBPTHREAD
                    383:                                        pthread_mutex_unlock(&r->root_mtx[taskREAD]);
                    384: #endif
1.3       misho     385:                                        if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
                    386:                                                if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
                    387:                                                        task->task_type = taskUNUSE;
1.4       misho     388: #ifdef HAVE_LIBPTHREAD
                    389:                                                        pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
                    390: #endif
1.3       misho     391:                                                        TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4       misho     392: #ifdef HAVE_LIBPTHREAD
                    393:                                                        pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
                    394: #endif
1.3       misho     395:                                                } else {
                    396:                                                        task->task_type = taskREADY;
1.4       misho     397: #ifdef HAVE_LIBPTHREAD
                    398:                                                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    399: #endif
1.3       misho     400:                                                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4       misho     401: #ifdef HAVE_LIBPTHREAD
                    402:                                                        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    403: #endif
1.3       misho     404:                                                }
                    405:                                        } else {
1.2       misho     406:                                                task->task_type = taskREADY;
1.4       misho     407: #ifdef HAVE_LIBPTHREAD
                    408:                                                pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    409: #endif
1.2       misho     410:                                                TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4       misho     411: #ifdef HAVE_LIBPTHREAD
                    412:                                                pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    413: #endif
1.3       misho     414:                                        }
1.1       misho     415:                                        break;
                    416:                                }
                    417:                                break;
                    418:                        case EVFILT_WRITE:
1.6       misho     419:                                TAILQ_FOREACH_SAFE(task, &r->root_write, task_node, tmp) {
1.3       misho     420:                                        if (TASK_FD(task) != ((intptr_t) res[i].udata))
1.1       misho     421:                                                continue;
                    422:                                        /* remove write handle */
1.4       misho     423: #ifdef HAVE_LIBPTHREAD
                    424:                                        pthread_mutex_lock(&r->root_mtx[taskWRITE]);
                    425: #endif
1.1       misho     426:                                        TAILQ_REMOVE(&r->root_write, task, task_node);
1.4       misho     427: #ifdef HAVE_LIBPTHREAD
                    428:                                        pthread_mutex_unlock(&r->root_mtx[taskWRITE]);
                    429: #endif
1.3       misho     430:                                        if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
                    431:                                                if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
                    432:                                                        task->task_type = taskUNUSE;
1.4       misho     433: #ifdef HAVE_LIBPTHREAD
                    434:                                                        pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
                    435: #endif
1.3       misho     436:                                                        TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4       misho     437: #ifdef HAVE_LIBPTHREAD
                    438:                                                        pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
                    439: #endif
1.3       misho     440:                                                } else {
                    441:                                                        task->task_type = taskREADY;
1.4       misho     442: #ifdef HAVE_LIBPTHREAD
                    443:                                                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    444: #endif
1.3       misho     445:                                                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4       misho     446: #ifdef HAVE_LIBPTHREAD
                    447:                                                        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    448: #endif
1.3       misho     449:                                                }
                    450:                                        } else {
1.2       misho     451:                                                task->task_type = taskREADY;
1.4       misho     452: #ifdef HAVE_LIBPTHREAD
                    453:                                                pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    454: #endif
1.2       misho     455:                                                TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4       misho     456: #ifdef HAVE_LIBPTHREAD
                    457:                                                pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    458: #endif
1.3       misho     459:                                        }
1.1       misho     460:                                        break;
                    461:                                }
                    462:                                break;
1.6.4.1 ! misho     463:                        case EVFILT_TIMER:
        !           464:                                if (TASK_DATA(task))
        !           465:                                        ident = (uintptr_t) TASK_DATA(task);
        !           466:                                else
        !           467:                                        ident = (uintptr_t) TASK_FUNC(task);
        !           468:                                TAILQ_FOREACH_SAFE(task, &r->root_alarm, task_node, tmp) {
        !           469:                                        if (ident != ((uintptr_t) res[i].udata))
        !           470:                                                continue;
        !           471:                                        /* remove alarm handle */
        !           472: #ifdef HAVE_LIBPTHREAD
        !           473:                                        pthread_mutex_lock(&r->root_mtx[taskALARM]);
        !           474: #endif
        !           475:                                        TAILQ_REMOVE(&r->root_alarm, task, task_node);
        !           476: #ifdef HAVE_LIBPTHREAD
        !           477:                                        pthread_mutex_unlock(&r->root_mtx[taskALARM]);
        !           478: #endif
        !           479:                                        task->task_type = taskREADY;
        !           480: #ifdef HAVE_LIBPTHREAD
        !           481:                                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
        !           482: #endif
        !           483:                                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
        !           484: #ifdef HAVE_LIBPTHREAD
        !           485:                                        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
        !           486: #endif
        !           487:                                        break;
        !           488:                                }
        !           489:                                break;
1.1       misho     490:                }
1.4       misho     491:                if (kevent(r->root_kq, evt, 1, NULL, 0, &now) == -1) {
1.3       misho     492:                        if (r->root_hooks.hook_exec.exception) {
                    493:                                if (r->root_hooks.hook_exec.exception(r, NULL))
                    494:                                        return NULL;
                    495:                        } else
                    496:                                LOGERR;
                    497:                }
1.1       misho     498:        }
                    499: 
1.2       misho     500:        /* timer update & put in ready queue */
1.4       misho     501:        clock_gettime(CLOCK_MONOTONIC, &now);
1.1       misho     502: 
1.6       misho     503:        TAILQ_FOREACH_SAFE(task, &r->root_timer, task_node, tmp)
1.4       misho     504:                if (sched_timespeccmp(&now, &TASK_TS(task), -) >= 0) {
                    505: #ifdef HAVE_LIBPTHREAD
                    506:                        pthread_mutex_lock(&r->root_mtx[taskTIMER]);
                    507: #endif
1.1       misho     508:                        TAILQ_REMOVE(&r->root_timer, task, task_node);
1.4       misho     509: #ifdef HAVE_LIBPTHREAD
                    510:                        pthread_mutex_unlock(&r->root_mtx[taskTIMER]);
                    511: #endif
1.1       misho     512:                        task->task_type = taskREADY;
1.4       misho     513: #ifdef HAVE_LIBPTHREAD
                    514:                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    515: #endif
1.1       misho     516:                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4       misho     517: #ifdef HAVE_LIBPTHREAD
                    518:                        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    519: #endif
1.1       misho     520:                }
                    521: 
                    522:        /* put eventlo priority task to ready queue, if there is no ready task or 
                    523:                reach max missed fetch-rotate */
                    524:        if ((task = TAILQ_FIRST(&r->root_eventlo))) {
                    525:                if (!TAILQ_FIRST(&r->root_ready) || r->root_eventlo_miss > MAX_EVENTLO_MISS) {
                    526:                        r->root_eventlo_miss = 0;
                    527: 
1.4       misho     528: #ifdef HAVE_LIBPTHREAD
                    529:                        pthread_mutex_lock(&r->root_mtx[taskEVENTLO]);
                    530: #endif
1.1       misho     531:                        TAILQ_REMOVE(&r->root_eventlo, task, task_node);
1.4       misho     532: #ifdef HAVE_LIBPTHREAD
                    533:                        pthread_mutex_unlock(&r->root_mtx[taskEVENTLO]);
                    534: #endif
1.1       misho     535:                        task->task_type = taskREADY;
1.4       misho     536: #ifdef HAVE_LIBPTHREAD
                    537:                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    538: #endif
1.1       misho     539:                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4       misho     540: #ifdef HAVE_LIBPTHREAD
                    541:                        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    542: #endif
1.1       misho     543:                } else
                    544:                        r->root_eventlo_miss++;
                    545:        } else
                    546:                r->root_eventlo_miss = 0;
                    547: 
                    548:        /* OK, lets get ready task !!! */
1.6       misho     549:        task = TAILQ_FIRST(&r->root_ready);
                    550:        if (!(task))
                    551:                return NULL;
                    552: 
1.4       misho     553: #ifdef HAVE_LIBPTHREAD
                    554:        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    555: #endif
1.1       misho     556:        TAILQ_REMOVE(&r->root_ready, task, task_node);
1.4       misho     557: #ifdef HAVE_LIBPTHREAD
                    558:        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    559: #endif
1.1       misho     560:        task->task_type = taskUNUSE;
1.4       misho     561: #ifdef HAVE_LIBPTHREAD
                    562:        pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
                    563: #endif
1.1       misho     564:        TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4       misho     565: #ifdef HAVE_LIBPTHREAD
                    566:        pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
                    567: #endif
1.1       misho     568:        return task;
                    569: }
1.3       misho     570: 
                    571: /*
                    572:  * sched_hook_exception() - Default EXCEPTION hook
1.5       misho     573:  *
1.3       misho     574:  * @root = root task
                    575:  * @arg = custom handling: if arg == EV_EOF or other value; default: arg == NULL log errno
                    576:  * return: <0 errors and 0 ok
                    577:  */
                    578: void *
                    579: sched_hook_exception(void *root, void *arg)
                    580: {
                    581:        sched_root_task_t *r = root;
                    582: 
1.6       misho     583:        if (!r)
1.3       misho     584:                return NULL;
                    585: 
                    586:        /* custom exception handling ... */
                    587:        if (arg) {
                    588:                if (arg == (void*) EV_EOF)
                    589:                        return NULL;
                    590:                return (void*) -1;      /* raise scheduler error!!! */
                    591:        }
                    592: 
                    593:        /* if error hook exists */
                    594:        if (r->root_hooks.hook_root.error)
                    595:                return (r->root_hooks.hook_root.error(root, (void*) ((intptr_t) errno)));
                    596: 
                    597:        /* default case! */
                    598:        LOGERR;
                    599:        return NULL;
                    600: }
1.5       misho     601: 
                    602: /*
                    603:  * sched_hook_condition() - Default CONDITION hook
                    604:  *
                    605:  * @root = root task
                    606:  * @arg = killState from schedRun()
                    607:  * return: NULL kill scheduler loop or !=NULL ok
                    608:  */
                    609: void *
                    610: sched_hook_condition(void *root, void *arg)
                    611: {
                    612:        sched_root_task_t *r = root;
                    613: 
1.6       misho     614:        if (!r)
1.5       misho     615:                return NULL;
                    616: 
                    617:        return (void*) (r->root_cond - *(intptr_t*) arg);
                    618: }

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