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

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.5     ! misho       6: * $Id: hooks.c,v 1.4.2.1 2012/03/13 10:00:37 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
                     54:  * @data = optional data if !=NULL
                     55:  * return: <0 errors and 0 ok
                     56:  */
                     57: void *
                     58: sched_hook_init(void *root, void *data)
                     59: {
                     60:        sched_root_task_t *r = root;
                     61: 
                     62:        if (!r || r->root_data.iov_base || r->root_data.iov_len)
                     63:                return (void*) -1;
                     64: 
                     65:        r->root_data.iov_base = malloc(sizeof(struct sched_IO));
                     66:        if (!r->root_data.iov_base) {
                     67:                LOGERR;
                     68:                return (void*) -1;
                     69:        } else {
                     70:                r->root_data.iov_len = sizeof(struct sched_IO);
                     71:                memset(r->root_data.iov_base, 0, r->root_data.iov_len);
                     72:        }
                     73: 
                     74:        r->root_kq = kqueue();
                     75:        if (r->root_kq == -1) {
                     76:                LOGERR;
                     77:                return (void*) -1;
                     78:        }
                     79: 
                     80:        return NULL;
                     81: }
                     82: 
                     83: /*
                     84:  * sched_hook_fini() - Default FINI hook
1.5     ! misho      85:  *
1.1       misho      86:  * @root = root task
                     87:  * @arg = unused
                     88:  * return: <0 errors and 0 ok
                     89:  */
                     90: void *
                     91: sched_hook_fini(void *root, void *arg __unused)
                     92: {
                     93:        sched_root_task_t *r = root;
                     94: 
                     95:        if (!r)
                     96:                return (void*) -1;
                     97: 
                     98:        if (r->root_kq > 2) {
                     99:                close(r->root_kq);
                    100:                r->root_kq = 0;
                    101:        }
                    102: 
                    103:        if (r->root_data.iov_base && r->root_data.iov_len) {
                    104:                free(r->root_data.iov_base);
                    105:                r->root_data.iov_base = NULL;
                    106:                r->root_data.iov_len = 0;
                    107:        }
                    108: 
                    109:        return NULL;
                    110: }
                    111: 
                    112: /*
                    113:  * sched_hook_cancel() - Default CANCEL hook
1.5     ! misho     114:  *
1.1       misho     115:  * @task = current task
                    116:  * @arg = unused
                    117:  * return: <0 errors and 0 ok
                    118:  */
                    119: void *
                    120: sched_hook_cancel(void *task, void *arg __unused)
                    121: {
                    122:        struct sched_IO *io;
                    123:        sched_task_t *t = task;
                    124:        struct kevent chg[1];
1.2       misho     125:        struct timespec timeout = { 0, 0 };
1.1       misho     126: 
1.4       misho     127:        if (!t || !TASK_ROOT(t) || !ROOT_DATA(t->task_root) || !ROOT_DATLEN(t->task_root))
1.1       misho     128:                return (void*) -1;
                    129:        else
                    130:                io = ROOT_DATA(t->task_root);
                    131: 
1.4       misho     132:        switch (TASK_TYPE(t)) {
1.1       misho     133:                case taskREAD:
1.2       misho     134: #ifdef __NetBSD__
                    135:                        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_DELETE, 0, 0, (intptr_t) TASK_FD(t));
                    136: #else
                    137:                        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_DELETE, 0, 0, (void*) TASK_FD(t));
                    138: #endif
1.4       misho     139:                        kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout);
1.1       misho     140:                        FD_CLR(TASK_FD(t), &io->rfd);
                    141:                        break;
                    142:                case taskWRITE:
1.2       misho     143: #ifdef __NetBSD__
                    144:                        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_DELETE, 0, 0, (intptr_t) TASK_FD(t));
                    145: #else
                    146:                        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_DELETE, 0, 0, (void*) TASK_FD(t));
                    147: #endif
1.4       misho     148:                        kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout);
1.1       misho     149:                        FD_CLR(TASK_FD(t), &io->wfd);
                    150:                        break;
                    151:                default:
                    152:                        break;
                    153:        }
                    154: 
                    155:        return NULL;
                    156: }
                    157: 
                    158: /*
                    159:  * sched_hook_read() - Default READ hook
1.5     ! misho     160:  *
1.1       misho     161:  * @task = current task
                    162:  * @arg = unused
                    163:  * return: <0 errors and 0 ok
                    164:  */
                    165: void *
                    166: sched_hook_read(void *task, void *arg __unused)
                    167: {
                    168:        struct sched_IO *io;
                    169:        sched_task_t *t = task;
                    170:        struct kevent chg[1];
1.2       misho     171:        struct timespec timeout = { 0, 0 };
1.1       misho     172: 
1.4       misho     173:        if (!t || !TASK_ROOT(t) || !ROOT_DATA(t->task_root) || !ROOT_DATLEN(t->task_root))
1.1       misho     174:                return (void*) -1;
                    175:        else
                    176:                io = ROOT_DATA(t->task_root);
                    177: 
                    178:        if (FD_ISSET(TASK_FD(t), &io->rfd))
                    179:                return NULL;
                    180:        else
                    181:                FD_SET(TASK_FD(t), &io->rfd);
                    182: 
1.2       misho     183: #ifdef __NetBSD__
                    184:        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD, 0, 0, (intptr_t) TASK_FD(t));
                    185: #else
                    186:        EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD, 0, 0, (void*) TASK_FD(t));
                    187: #endif
1.4       misho     188:        if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                    189:                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                    190:                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
1.3       misho     191:                else
                    192:                        LOGERR;
1.1       misho     193:                return (void*) -1;
                    194:        }
                    195: 
                    196:        return NULL;
                    197: }
                    198: 
                    199: /*
                    200:  * sched_hook_write() - Default WRITE hook
1.5     ! misho     201:  *
1.1       misho     202:  * @task = current task
                    203:  * @arg = unused
                    204:  * return: <0 errors and 0 ok
                    205:  */
                    206: void *
                    207: sched_hook_write(void *task, void *arg __unused)
                    208: {
                    209:        struct sched_IO *io;
                    210:        sched_task_t *t = task;
                    211:        struct kevent chg[1];
1.2       misho     212:        struct timespec timeout = { 0, 0 };
1.1       misho     213: 
1.4       misho     214:        if (!t || !TASK_ROOT(t) || !ROOT_DATA(t->task_root) || !ROOT_DATLEN(t->task_root))
1.1       misho     215:                return (void*) -1;
                    216:        else
                    217:                io = ROOT_DATA(t->task_root);
                    218: 
                    219:        if (FD_ISSET(TASK_FD(t), &io->wfd))
                    220:                return NULL;
                    221:        else
                    222:                FD_SET(TASK_FD(t), &io->wfd);
                    223: 
1.2       misho     224: #ifdef __NetBSD__
                    225:        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD, 0, 0, (intptr_t) TASK_FD(t));
                    226: #else
                    227:        EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD, 0, 0, (void*) TASK_FD(t));
                    228: #endif
1.4       misho     229:        if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
                    230:                if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
                    231:                        TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
1.3       misho     232:                else
                    233:                        LOGERR;
1.1       misho     234:                return (void*) -1;
                    235:        }
                    236: 
                    237:        return NULL;
                    238: }
                    239: 
                    240: /*
                    241:  * sched_hook_fetch() - Default FETCH hook
1.5     ! misho     242:  *
1.1       misho     243:  * @root = root task
                    244:  * @arg = unused
                    245:  * return: NULL error or !=NULL fetched task
                    246:  */
                    247: void *
                    248: sched_hook_fetch(void *root, void *arg __unused)
                    249: {
                    250:        struct sched_IO *io;
                    251:        sched_root_task_t *r = root;
                    252:        sched_task_t *task;
1.4       misho     253:        struct timespec now, m, mtmp;
                    254:        struct timespec *timeout;
1.1       misho     255:        struct kevent evt[1], res[KQ_EVENTS];
                    256:        register int i;
                    257:        int en;
                    258: 
                    259:        if (!r || !ROOT_DATA(r) || !ROOT_DATLEN(r))
                    260:                return NULL;
                    261: 
                    262:        /* get new task by queue priority */
                    263: retry:
                    264:        while ((task = TAILQ_FIRST(&r->root_event))) {
1.4       misho     265: #ifdef HAVE_LIBPTHREAD
                    266:                pthread_mutex_lock(&r->root_mtx[taskEVENT]);
                    267: #endif
1.1       misho     268:                TAILQ_REMOVE(&r->root_event, task, task_node);
1.4       misho     269: #ifdef HAVE_LIBPTHREAD
                    270:                pthread_mutex_unlock(&r->root_mtx[taskEVENT]);
                    271: #endif
1.1       misho     272:                task->task_type = taskUNUSE;
1.4       misho     273: #ifdef HAVE_LIBPTHREAD
                    274:                pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
                    275: #endif
1.1       misho     276:                TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4       misho     277: #ifdef HAVE_LIBPTHREAD
                    278:                pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
                    279: #endif
1.1       misho     280:                return task;
                    281:        }
                    282:        while ((task = TAILQ_FIRST(&r->root_ready))) {
1.4       misho     283: #ifdef HAVE_LIBPTHREAD
                    284:                pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    285: #endif
1.1       misho     286:                TAILQ_REMOVE(&r->root_ready, task, task_node);
1.4       misho     287: #ifdef HAVE_LIBPTHREAD
                    288:                pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    289: #endif
1.1       misho     290:                task->task_type = taskUNUSE;
1.4       misho     291: #ifdef HAVE_LIBPTHREAD
                    292:                pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
                    293: #endif
1.1       misho     294:                TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4       misho     295: #ifdef HAVE_LIBPTHREAD
                    296:                pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
                    297: #endif
1.1       misho     298:                return task;
                    299:        }
                    300: 
                    301: #ifdef TIMER_WITHOUT_SORT
1.4       misho     302:        clock_gettime(CLOCK_MONOTONIC, &now);
1.1       misho     303: 
1.4       misho     304:        sched_timespecclear(&r->root_wait);
1.1       misho     305:        TAILQ_FOREACH(task, &r->root_timer, task_node) {
1.4       misho     306:                if (!sched_timespecisset(&r->root_wait))
                    307:                        r->root_wait = TASK_TS(task);
                    308:                else if (sched_timespeccmp(&TASK_TS(task), &r->root_wait, -) < 0)
                    309:                        r->root_wait = TASK_TS(task);
1.1       misho     310:        }
                    311: 
                    312:        if (TAILQ_FIRST(&r->root_timer)) {
                    313:                m = r->root_wait;
1.4       misho     314:                sched_timespecsub(&m, &now, &mtmp);
1.1       misho     315:                r->root_wait = mtmp;
                    316:        } else {
                    317:                /* set wait INFTIM */
1.4       misho     318:                sched_timespecinf(&r->root_wait);
1.1       misho     319:        }
                    320: #else
                    321:        if (!TAILQ_FIRST(&r->root_eventlo) && (task = TAILQ_FIRST(&r->root_timer))) {
1.4       misho     322:                clock_gettime(CLOCK_MONOTONIC, &now);
1.1       misho     323: 
1.4       misho     324:                m = TASK_TS(task);
                    325:                sched_timespecsub(&m, &now, &mtmp);
1.1       misho     326:                r->root_wait = mtmp;
                    327:        } else {
                    328:                /* set wait INFTIM */
1.4       misho     329:                sched_timespecinf(&r->root_wait);
1.1       misho     330:        }
                    331: #endif
                    332:        /* if present member of eventLo, set NOWAIT */
                    333:        if (TAILQ_FIRST(&r->root_eventlo))
1.4       misho     334:                sched_timespecclear(&r->root_wait);
1.1       misho     335: 
1.4       misho     336:        if (r->root_wait.tv_sec != -1 && r->root_wait.tv_nsec != -1)
                    337:                timeout = &r->root_wait;
                    338:        else if (sched_timespecisinf(&r->root_poll))
1.1       misho     339:                timeout = NULL;
1.4       misho     340:        else
                    341:                timeout = &r->root_poll;
1.1       misho     342:        if ((en = kevent(r->root_kq, NULL, 0, res, KQ_EVENTS, timeout)) == -1) {
1.3       misho     343:                if (r->root_hooks.hook_exec.exception) {
                    344:                        if (r->root_hooks.hook_exec.exception(r, NULL))
                    345:                                return NULL;
                    346:                } else
                    347:                        LOGERR;
1.2       misho     348: #ifdef NDEBUG
                    349:                /* kevent no exit by error, if non-debug version */
1.1       misho     350:                goto retry;
1.2       misho     351: #else
                    352:                /* diagnostic exit from scheduler if kevent error occur */
                    353:                return NULL;
                    354: #endif
1.1       misho     355:        }
                    356: 
1.4       misho     357:        now.tv_sec = now.tv_nsec = 0;
1.1       misho     358:        /* Go and catch the cat into pipes ... */
                    359:        for (i = 0; i < en; i++) {
                    360:                memcpy(evt, &res[i], sizeof evt);
                    361:                evt->flags = EV_DELETE;
                    362:                /* Put read/write task to ready queue */
                    363:                switch (res[i].filter) {
                    364:                        case EVFILT_READ:
                    365:                                TAILQ_FOREACH(task, &r->root_read, task_node) {
1.3       misho     366:                                        if (TASK_FD(task) != ((intptr_t) res[i].udata))
1.1       misho     367:                                                continue;
                    368:                                        /* remove read handle */
                    369:                                        io = ROOT_DATA(task->task_root);
                    370:                                        FD_CLR(TASK_FD(task), &io->rfd);
                    371: 
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:
                    413:                                TAILQ_FOREACH(task, &r->root_write, task_node) {
1.3       misho     414:                                        if (TASK_FD(task) != ((intptr_t) res[i].udata))
1.1       misho     415:                                                continue;
                    416:                                        /* remove write handle */
                    417:                                        io = ROOT_DATA(task->task_root);
                    418:                                        FD_CLR(TASK_FD(task), &io->wfd);
                    419: 
1.4       misho     420: #ifdef HAVE_LIBPTHREAD
                    421:                                        pthread_mutex_lock(&r->root_mtx[taskWRITE]);
                    422: #endif
1.1       misho     423:                                        TAILQ_REMOVE(&r->root_write, task, task_node);
1.4       misho     424: #ifdef HAVE_LIBPTHREAD
                    425:                                        pthread_mutex_unlock(&r->root_mtx[taskWRITE]);
                    426: #endif
1.3       misho     427:                                        if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
                    428:                                                if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
                    429:                                                        task->task_type = taskUNUSE;
1.4       misho     430: #ifdef HAVE_LIBPTHREAD
                    431:                                                        pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
                    432: #endif
1.3       misho     433:                                                        TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4       misho     434: #ifdef HAVE_LIBPTHREAD
                    435:                                                        pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
                    436: #endif
1.3       misho     437:                                                } else {
                    438:                                                        task->task_type = taskREADY;
1.4       misho     439: #ifdef HAVE_LIBPTHREAD
                    440:                                                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    441: #endif
1.3       misho     442:                                                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4       misho     443: #ifdef HAVE_LIBPTHREAD
                    444:                                                        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    445: #endif
1.3       misho     446:                                                }
                    447:                                        } else {
1.2       misho     448:                                                task->task_type = taskREADY;
1.4       misho     449: #ifdef HAVE_LIBPTHREAD
                    450:                                                pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    451: #endif
1.2       misho     452:                                                TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4       misho     453: #ifdef HAVE_LIBPTHREAD
                    454:                                                pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    455: #endif
1.3       misho     456:                                        }
1.1       misho     457:                                        break;
                    458:                                }
                    459:                                break;
                    460:                }
1.4       misho     461:                if (kevent(r->root_kq, evt, 1, NULL, 0, &now) == -1) {
1.3       misho     462:                        if (r->root_hooks.hook_exec.exception) {
                    463:                                if (r->root_hooks.hook_exec.exception(r, NULL))
                    464:                                        return NULL;
                    465:                        } else
                    466:                                LOGERR;
                    467:                }
1.1       misho     468:        }
                    469: 
1.2       misho     470:        /* timer update & put in ready queue */
1.4       misho     471:        clock_gettime(CLOCK_MONOTONIC, &now);
1.1       misho     472: 
                    473:        TAILQ_FOREACH(task, &r->root_timer, task_node)
1.4       misho     474:                if (sched_timespeccmp(&now, &TASK_TS(task), -) >= 0) {
                    475: #ifdef HAVE_LIBPTHREAD
                    476:                        pthread_mutex_lock(&r->root_mtx[taskTIMER]);
                    477: #endif
1.1       misho     478:                        TAILQ_REMOVE(&r->root_timer, task, task_node);
1.4       misho     479: #ifdef HAVE_LIBPTHREAD
                    480:                        pthread_mutex_unlock(&r->root_mtx[taskTIMER]);
                    481: #endif
1.1       misho     482:                        task->task_type = taskREADY;
1.4       misho     483: #ifdef HAVE_LIBPTHREAD
                    484:                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    485: #endif
1.1       misho     486:                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4       misho     487: #ifdef HAVE_LIBPTHREAD
                    488:                        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    489: #endif
1.1       misho     490:                }
                    491: 
                    492:        /* put eventlo priority task to ready queue, if there is no ready task or 
                    493:                reach max missed fetch-rotate */
                    494:        if ((task = TAILQ_FIRST(&r->root_eventlo))) {
                    495:                if (!TAILQ_FIRST(&r->root_ready) || r->root_eventlo_miss > MAX_EVENTLO_MISS) {
                    496:                        r->root_eventlo_miss = 0;
                    497: 
1.4       misho     498: #ifdef HAVE_LIBPTHREAD
                    499:                        pthread_mutex_lock(&r->root_mtx[taskEVENTLO]);
                    500: #endif
1.1       misho     501:                        TAILQ_REMOVE(&r->root_eventlo, task, task_node);
1.4       misho     502: #ifdef HAVE_LIBPTHREAD
                    503:                        pthread_mutex_unlock(&r->root_mtx[taskEVENTLO]);
                    504: #endif
1.1       misho     505:                        task->task_type = taskREADY;
1.4       misho     506: #ifdef HAVE_LIBPTHREAD
                    507:                        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    508: #endif
1.1       misho     509:                        TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4       misho     510: #ifdef HAVE_LIBPTHREAD
                    511:                        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    512: #endif
1.1       misho     513:                } else
                    514:                        r->root_eventlo_miss++;
                    515:        } else
                    516:                r->root_eventlo_miss = 0;
                    517: 
                    518:        /* OK, lets get ready task !!! */
                    519:        if (!(task = TAILQ_FIRST(&r->root_ready)))
                    520:                goto retry;
1.4       misho     521: #ifdef HAVE_LIBPTHREAD
                    522:        pthread_mutex_lock(&r->root_mtx[taskREADY]);
                    523: #endif
1.1       misho     524:        TAILQ_REMOVE(&r->root_ready, task, task_node);
1.4       misho     525: #ifdef HAVE_LIBPTHREAD
                    526:        pthread_mutex_unlock(&r->root_mtx[taskREADY]);
                    527: #endif
1.1       misho     528:        task->task_type = taskUNUSE;
1.4       misho     529: #ifdef HAVE_LIBPTHREAD
                    530:        pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
                    531: #endif
1.1       misho     532:        TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4       misho     533: #ifdef HAVE_LIBPTHREAD
                    534:        pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
                    535: #endif
1.1       misho     536:        return task;
                    537: }
1.3       misho     538: 
                    539: /*
                    540:  * sched_hook_exception() - Default EXCEPTION hook
1.5     ! misho     541:  *
1.3       misho     542:  * @root = root task
                    543:  * @arg = custom handling: if arg == EV_EOF or other value; default: arg == NULL log errno
                    544:  * return: <0 errors and 0 ok
                    545:  */
                    546: void *
                    547: sched_hook_exception(void *root, void *arg)
                    548: {
                    549:        sched_root_task_t *r = root;
                    550: 
                    551:        if (!r || !ROOT_DATA(r) || !ROOT_DATLEN(r))
                    552:                return NULL;
                    553: 
                    554:        /* custom exception handling ... */
                    555:        if (arg) {
                    556:                if (arg == (void*) EV_EOF)
                    557:                        return NULL;
                    558:                return (void*) -1;      /* raise scheduler error!!! */
                    559:        }
                    560: 
                    561:        /* if error hook exists */
                    562:        if (r->root_hooks.hook_root.error)
                    563:                return (r->root_hooks.hook_root.error(root, (void*) ((intptr_t) errno)));
                    564: 
                    565:        /* default case! */
                    566:        LOGERR;
                    567:        return NULL;
                    568: }
1.5     ! misho     569: 
        !           570: /*
        !           571:  * sched_hook_condition() - Default CONDITION hook
        !           572:  *
        !           573:  * @root = root task
        !           574:  * @arg = killState from schedRun()
        !           575:  * return: NULL kill scheduler loop or !=NULL ok
        !           576:  */
        !           577: void *
        !           578: sched_hook_condition(void *root, void *arg)
        !           579: {
        !           580:        sched_root_task_t *r = root;
        !           581: 
        !           582:        if (!r || !ROOT_DATA(r) || !ROOT_DATLEN(r))
        !           583:                return NULL;
        !           584: 
        !           585:        return (void*) (r->root_cond - *(intptr_t*) arg);
        !           586: }

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