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

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.2 ! misho       6: * $Id: hooks.c,v 1.6.4.1 2012/05/30 08:07:45 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__
1.6.4.2 ! misho     241:        EV_SET(&chg[0], ident, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 
        !           242:                        t->task_val.ts.tv_sec * 1000 + t->task_val.ts.tv_nsec / 1000000, 
        !           243:                        (intptr_t) ident);
1.6.4.1   misho     244: #else
1.6.4.2 ! misho     245:        EV_SET(&chg[0], ident, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 
        !           246:                        t->task_val.ts.tv_sec * 1000 + t->task_val.ts.tv_nsec / 1000000, 
        !           247:                        (void*) ident);
1.6.4.1   misho     248: #endif
                    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);
                    252:                else
                    253:                        LOGERR;
                    254:                return (void*) -1;
                    255:        }
                    256: 
                    257:        return NULL;
                    258: }
                    259: 
                    260: /*
1.1       misho     261:  * sched_hook_fetch() - Default FETCH hook
1.5       misho     262:  *
1.1       misho     263:  * @root = root task
                    264:  * @arg = unused
                    265:  * return: NULL error or !=NULL fetched task
                    266:  */
                    267: void *
                    268: sched_hook_fetch(void *root, void *arg __unused)
                    269: {
                    270:        sched_root_task_t *r = root;
1.6       misho     271:        sched_task_t *task, *tmp;
1.4       misho     272:        struct timespec now, m, mtmp;
                    273:        struct timespec *timeout;
1.1       misho     274:        struct kevent evt[1], res[KQ_EVENTS];
                    275:        register int i;
                    276:        int en;
1.6.4.1   misho     277:        uintptr_t ident;
1.1       misho     278: 
1.6       misho     279:        if (!r)
1.1       misho     280:                return NULL;
                    281: 
                    282:        /* get new task by queue priority */
                    283:        while ((task = TAILQ_FIRST(&r->root_event))) {
1.4       misho     284: #ifdef HAVE_LIBPTHREAD
                    285:                pthread_mutex_lock(&r->root_mtx[taskEVENT]);
                    286: #endif
1.1       misho     287:                TAILQ_REMOVE(&r->root_event, task, task_node);
1.4       misho     288: #ifdef HAVE_LIBPTHREAD
                    289:                pthread_mutex_unlock(&r->root_mtx[taskEVENT]);
                    290: #endif
1.1       misho     291:                task->task_type = taskUNUSE;
1.4       misho     292: #ifdef HAVE_LIBPTHREAD
                    293:                pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
                    294: #endif
1.1       misho     295:                TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4       misho     296: #ifdef HAVE_LIBPTHREAD
                    297:                pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
                    298: #endif
1.1       misho     299:                return task;
                    300:        }
                    301:        while ((task = TAILQ_FIRST(&r->root_ready))) {
1.4       misho     302: #ifdef HAVE_LIBPTHREAD
                    303:                pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    304: #endif
1.1       misho     305:                TAILQ_REMOVE(&r->root_ready, task, task_node);
1.4       misho     306: #ifdef HAVE_LIBPTHREAD
                    307:                pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    308: #endif
1.1       misho     309:                task->task_type = taskUNUSE;
1.4       misho     310: #ifdef HAVE_LIBPTHREAD
                    311:                pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
                    312: #endif
1.1       misho     313:                TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4       misho     314: #ifdef HAVE_LIBPTHREAD
                    315:                pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
                    316: #endif
1.1       misho     317:                return task;
                    318:        }
                    319: 
                    320: #ifdef TIMER_WITHOUT_SORT
1.4       misho     321:        clock_gettime(CLOCK_MONOTONIC, &now);
1.1       misho     322: 
1.4       misho     323:        sched_timespecclear(&r->root_wait);
1.1       misho     324:        TAILQ_FOREACH(task, &r->root_timer, task_node) {
1.4       misho     325:                if (!sched_timespecisset(&r->root_wait))
                    326:                        r->root_wait = TASK_TS(task);
                    327:                else if (sched_timespeccmp(&TASK_TS(task), &r->root_wait, -) < 0)
                    328:                        r->root_wait = TASK_TS(task);
1.1       misho     329:        }
                    330: 
                    331:        if (TAILQ_FIRST(&r->root_timer)) {
                    332:                m = r->root_wait;
1.4       misho     333:                sched_timespecsub(&m, &now, &mtmp);
1.1       misho     334:                r->root_wait = mtmp;
                    335:        } else {
                    336:                /* set wait INFTIM */
1.4       misho     337:                sched_timespecinf(&r->root_wait);
1.1       misho     338:        }
                    339: #else
                    340:        if (!TAILQ_FIRST(&r->root_eventlo) && (task = TAILQ_FIRST(&r->root_timer))) {
1.4       misho     341:                clock_gettime(CLOCK_MONOTONIC, &now);
1.1       misho     342: 
1.4       misho     343:                m = TASK_TS(task);
                    344:                sched_timespecsub(&m, &now, &mtmp);
1.1       misho     345:                r->root_wait = mtmp;
                    346:        } else {
                    347:                /* set wait INFTIM */
1.4       misho     348:                sched_timespecinf(&r->root_wait);
1.1       misho     349:        }
                    350: #endif
                    351:        /* if present member of eventLo, set NOWAIT */
                    352:        if (TAILQ_FIRST(&r->root_eventlo))
1.4       misho     353:                sched_timespecclear(&r->root_wait);
1.1       misho     354: 
1.4       misho     355:        if (r->root_wait.tv_sec != -1 && r->root_wait.tv_nsec != -1)
                    356:                timeout = &r->root_wait;
                    357:        else if (sched_timespecisinf(&r->root_poll))
1.1       misho     358:                timeout = NULL;
1.4       misho     359:        else
                    360:                timeout = &r->root_poll;
1.1       misho     361:        if ((en = kevent(r->root_kq, NULL, 0, res, KQ_EVENTS, timeout)) == -1) {
1.3       misho     362:                if (r->root_hooks.hook_exec.exception) {
                    363:                        if (r->root_hooks.hook_exec.exception(r, NULL))
                    364:                                return NULL;
1.6       misho     365:                } else if (errno != EINTR)
1.3       misho     366:                        LOGERR;
1.2       misho     367:                return NULL;
1.1       misho     368:        }
                    369: 
1.4       misho     370:        now.tv_sec = now.tv_nsec = 0;
1.1       misho     371:        /* Go and catch the cat into pipes ... */
                    372:        for (i = 0; i < en; i++) {
                    373:                memcpy(evt, &res[i], sizeof evt);
                    374:                evt->flags = EV_DELETE;
                    375:                /* Put read/write task to ready queue */
                    376:                switch (res[i].filter) {
                    377:                        case EVFILT_READ:
1.6       misho     378:                                TAILQ_FOREACH_SAFE(task, &r->root_read, task_node, tmp) {
1.3       misho     379:                                        if (TASK_FD(task) != ((intptr_t) res[i].udata))
1.1       misho     380:                                                continue;
                    381:                                        /* remove read handle */
1.4       misho     382: #ifdef HAVE_LIBPTHREAD
                    383:                                        pthread_mutex_lock(&r->root_mtx[taskREAD]);
                    384: #endif
1.1       misho     385:                                        TAILQ_REMOVE(&r->root_read, task, task_node);
1.4       misho     386: #ifdef HAVE_LIBPTHREAD
                    387:                                        pthread_mutex_unlock(&r->root_mtx[taskREAD]);
                    388: #endif
1.3       misho     389:                                        if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
                    390:                                                if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
                    391:                                                        task->task_type = taskUNUSE;
1.4       misho     392: #ifdef HAVE_LIBPTHREAD
                    393:                                                        pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
                    394: #endif
1.3       misho     395:                                                        TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4       misho     396: #ifdef HAVE_LIBPTHREAD
                    397:                                                        pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
                    398: #endif
1.3       misho     399:                                                } else {
                    400:                                                        task->task_type = taskREADY;
1.4       misho     401: #ifdef HAVE_LIBPTHREAD
                    402:                                                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    403: #endif
1.3       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:                                                }
                    409:                                        } else {
1.2       misho     410:                                                task->task_type = taskREADY;
1.4       misho     411: #ifdef HAVE_LIBPTHREAD
                    412:                                                pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    413: #endif
1.2       misho     414:                                                TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4       misho     415: #ifdef HAVE_LIBPTHREAD
                    416:                                                pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    417: #endif
1.3       misho     418:                                        }
1.1       misho     419:                                        break;
                    420:                                }
                    421:                                break;
                    422:                        case EVFILT_WRITE:
1.6       misho     423:                                TAILQ_FOREACH_SAFE(task, &r->root_write, task_node, tmp) {
1.3       misho     424:                                        if (TASK_FD(task) != ((intptr_t) res[i].udata))
1.1       misho     425:                                                continue;
                    426:                                        /* remove write handle */
1.4       misho     427: #ifdef HAVE_LIBPTHREAD
                    428:                                        pthread_mutex_lock(&r->root_mtx[taskWRITE]);
                    429: #endif
1.1       misho     430:                                        TAILQ_REMOVE(&r->root_write, task, task_node);
1.4       misho     431: #ifdef HAVE_LIBPTHREAD
                    432:                                        pthread_mutex_unlock(&r->root_mtx[taskWRITE]);
                    433: #endif
1.3       misho     434:                                        if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
                    435:                                                if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
                    436:                                                        task->task_type = taskUNUSE;
1.4       misho     437: #ifdef HAVE_LIBPTHREAD
                    438:                                                        pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
                    439: #endif
1.3       misho     440:                                                        TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4       misho     441: #ifdef HAVE_LIBPTHREAD
                    442:                                                        pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
                    443: #endif
1.3       misho     444:                                                } else {
                    445:                                                        task->task_type = taskREADY;
1.4       misho     446: #ifdef HAVE_LIBPTHREAD
                    447:                                                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    448: #endif
1.3       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:                                                }
                    454:                                        } else {
1.2       misho     455:                                                task->task_type = taskREADY;
1.4       misho     456: #ifdef HAVE_LIBPTHREAD
                    457:                                                pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    458: #endif
1.2       misho     459:                                                TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4       misho     460: #ifdef HAVE_LIBPTHREAD
                    461:                                                pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    462: #endif
1.3       misho     463:                                        }
1.1       misho     464:                                        break;
                    465:                                }
                    466:                                break;
1.6.4.1   misho     467:                        case EVFILT_TIMER:
                    468:                                TAILQ_FOREACH_SAFE(task, &r->root_alarm, task_node, tmp) {
1.6.4.2 ! misho     469:                                        if (TASK_DATA(task))
        !           470:                                                ident = (uintptr_t) TASK_DATA(task);
        !           471:                                        else
        !           472:                                                ident = (uintptr_t) TASK_FUNC(task);
1.6.4.1   misho     473:                                        if (ident != ((uintptr_t) res[i].udata))
                    474:                                                continue;
                    475:                                        /* remove alarm handle */
                    476: #ifdef HAVE_LIBPTHREAD
                    477:                                        pthread_mutex_lock(&r->root_mtx[taskALARM]);
                    478: #endif
                    479:                                        TAILQ_REMOVE(&r->root_alarm, task, task_node);
                    480: #ifdef HAVE_LIBPTHREAD
                    481:                                        pthread_mutex_unlock(&r->root_mtx[taskALARM]);
                    482: #endif
                    483:                                        task->task_type = taskREADY;
                    484: #ifdef HAVE_LIBPTHREAD
                    485:                                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    486: #endif
                    487:                                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
                    488: #ifdef HAVE_LIBPTHREAD
                    489:                                        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    490: #endif
                    491:                                        break;
                    492:                                }
                    493:                                break;
1.1       misho     494:                }
1.4       misho     495:                if (kevent(r->root_kq, evt, 1, NULL, 0, &now) == -1) {
1.3       misho     496:                        if (r->root_hooks.hook_exec.exception) {
                    497:                                if (r->root_hooks.hook_exec.exception(r, NULL))
                    498:                                        return NULL;
                    499:                        } else
                    500:                                LOGERR;
                    501:                }
1.1       misho     502:        }
                    503: 
1.2       misho     504:        /* timer update & put in ready queue */
1.4       misho     505:        clock_gettime(CLOCK_MONOTONIC, &now);
1.1       misho     506: 
1.6       misho     507:        TAILQ_FOREACH_SAFE(task, &r->root_timer, task_node, tmp)
1.4       misho     508:                if (sched_timespeccmp(&now, &TASK_TS(task), -) >= 0) {
                    509: #ifdef HAVE_LIBPTHREAD
                    510:                        pthread_mutex_lock(&r->root_mtx[taskTIMER]);
                    511: #endif
1.1       misho     512:                        TAILQ_REMOVE(&r->root_timer, task, task_node);
1.4       misho     513: #ifdef HAVE_LIBPTHREAD
                    514:                        pthread_mutex_unlock(&r->root_mtx[taskTIMER]);
                    515: #endif
1.1       misho     516:                        task->task_type = taskREADY;
1.4       misho     517: #ifdef HAVE_LIBPTHREAD
                    518:                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    519: #endif
1.1       misho     520:                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4       misho     521: #ifdef HAVE_LIBPTHREAD
                    522:                        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    523: #endif
1.1       misho     524:                }
                    525: 
                    526:        /* put eventlo priority task to ready queue, if there is no ready task or 
                    527:                reach max missed fetch-rotate */
                    528:        if ((task = TAILQ_FIRST(&r->root_eventlo))) {
                    529:                if (!TAILQ_FIRST(&r->root_ready) || r->root_eventlo_miss > MAX_EVENTLO_MISS) {
                    530:                        r->root_eventlo_miss = 0;
                    531: 
1.4       misho     532: #ifdef HAVE_LIBPTHREAD
                    533:                        pthread_mutex_lock(&r->root_mtx[taskEVENTLO]);
                    534: #endif
1.1       misho     535:                        TAILQ_REMOVE(&r->root_eventlo, task, task_node);
1.4       misho     536: #ifdef HAVE_LIBPTHREAD
                    537:                        pthread_mutex_unlock(&r->root_mtx[taskEVENTLO]);
                    538: #endif
1.1       misho     539:                        task->task_type = taskREADY;
1.4       misho     540: #ifdef HAVE_LIBPTHREAD
                    541:                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    542: #endif
1.1       misho     543:                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4       misho     544: #ifdef HAVE_LIBPTHREAD
                    545:                        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    546: #endif
1.1       misho     547:                } else
                    548:                        r->root_eventlo_miss++;
                    549:        } else
                    550:                r->root_eventlo_miss = 0;
                    551: 
                    552:        /* OK, lets get ready task !!! */
1.6       misho     553:        task = TAILQ_FIRST(&r->root_ready);
                    554:        if (!(task))
                    555:                return NULL;
                    556: 
1.4       misho     557: #ifdef HAVE_LIBPTHREAD
                    558:        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    559: #endif
1.1       misho     560:        TAILQ_REMOVE(&r->root_ready, task, task_node);
1.4       misho     561: #ifdef HAVE_LIBPTHREAD
                    562:        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    563: #endif
1.1       misho     564:        task->task_type = taskUNUSE;
1.4       misho     565: #ifdef HAVE_LIBPTHREAD
                    566:        pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
                    567: #endif
1.1       misho     568:        TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4       misho     569: #ifdef HAVE_LIBPTHREAD
                    570:        pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
                    571: #endif
1.1       misho     572:        return task;
                    573: }
1.3       misho     574: 
                    575: /*
                    576:  * sched_hook_exception() - Default EXCEPTION hook
1.5       misho     577:  *
1.3       misho     578:  * @root = root task
                    579:  * @arg = custom handling: if arg == EV_EOF or other value; default: arg == NULL log errno
                    580:  * return: <0 errors and 0 ok
                    581:  */
                    582: void *
                    583: sched_hook_exception(void *root, void *arg)
                    584: {
                    585:        sched_root_task_t *r = root;
                    586: 
1.6       misho     587:        if (!r)
1.3       misho     588:                return NULL;
                    589: 
                    590:        /* custom exception handling ... */
                    591:        if (arg) {
                    592:                if (arg == (void*) EV_EOF)
                    593:                        return NULL;
                    594:                return (void*) -1;      /* raise scheduler error!!! */
                    595:        }
                    596: 
                    597:        /* if error hook exists */
                    598:        if (r->root_hooks.hook_root.error)
                    599:                return (r->root_hooks.hook_root.error(root, (void*) ((intptr_t) errno)));
                    600: 
                    601:        /* default case! */
                    602:        LOGERR;
                    603:        return NULL;
                    604: }
1.5       misho     605: 
                    606: /*
                    607:  * sched_hook_condition() - Default CONDITION hook
                    608:  *
                    609:  * @root = root task
                    610:  * @arg = killState from schedRun()
                    611:  * return: NULL kill scheduler loop or !=NULL ok
                    612:  */
                    613: void *
                    614: sched_hook_condition(void *root, void *arg)
                    615: {
                    616:        sched_root_task_t *r = root;
                    617: 
1.6       misho     618:        if (!r)
1.5       misho     619:                return NULL;
                    620: 
                    621:        return (void*) (r->root_cond - *(intptr_t*) arg);
                    622: }

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