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

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

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