Annotation of libaitsched/src/tasks.c, revision 1.1.1.1

1.1       misho       1: /*************************************************************************
                      2: * (C) 2011 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
                      3: *  by Michael Pounov <misho@openbsd-bg.org>
                      4: *
                      5: * $Author: misho $
                      6: * $Id: aitcrc.c,v 1.4.2.1 2011/05/10 20:48:49 misho Exp $
                      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: 
                     15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
                     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: 
                     48: 
                     49: /*
                     50:  * schedRead() - Add READ task to scheduler queue
                     51:  * @root = root task
                     52:  * @func = task execution function
                     53:  * @arg = 1st func argument
                     54:  * @... = next func arguments, like fd handle
                     55:  * return: NULL error or !=NULL new queued task
                     56:  */
                     57: sched_task_t *
                     58: schedRead(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, ...)
                     59: {
                     60:        sched_task_t *task;
                     61:        void *ptr;
                     62:        va_list lst;
                     63: 
                     64:        if (!root || !func)
                     65:                return NULL;
                     66: 
                     67:        /* get new task */
                     68:        if ((task = TAILQ_FIRST(&root->root_unuse)))
                     69:                TAILQ_REMOVE(&root->root_unuse, task, task_node);
                     70:        else {
                     71:                task = malloc(sizeof(sched_task_t));
                     72:                if (!task) {
                     73:                        LOGERR;
                     74:                        return NULL;
                     75:                }
                     76:        }
                     77: 
                     78:        memset(task, 0, sizeof(sched_task_t));
                     79:        task->task_id = 0;
                     80:        task->task_type = taskREAD;
                     81:        task->task_root = root;
                     82:        task->task_func = func;
                     83: 
                     84:        TASK_ARG(task) = arg;
                     85:        va_start(lst, arg);
                     86:        TASK_FD(task) = va_arg(lst, int);
                     87:        va_end(lst);
                     88: 
                     89:        if (root->root_hooks.hook_add.read)
                     90:                ptr = root->root_hooks.hook_add.read(task, NULL);
                     91:        else
                     92:                ptr = NULL;
                     93: 
                     94:        if (!ptr)
                     95:                TAILQ_INSERT_TAIL(&root->root_read, task, task_node);
                     96:        else {
                     97:                task->task_type = taskUNUSE;
                     98:                TAILQ_INSERT_TAIL(&root->root_unuse, task, task_node);
                     99:                task = NULL;
                    100:        }
                    101: 
                    102:        return task;
                    103: }
                    104: 
                    105: /*
                    106:  * schedWrite() - Add WRITE task to scheduler queue
                    107:  * @root = root task
                    108:  * @func = task execution function
                    109:  * @arg = 1st func argument
                    110:  * @... = next func arguments, like fd handle
                    111:  * return: NULL error or !=NULL new queued task
                    112:  */
                    113: sched_task_t *
                    114: schedWrite(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, ...)
                    115: {
                    116:        sched_task_t *task;
                    117:        void *ptr;
                    118:        va_list lst;
                    119: 
                    120:        if (!root || !func)
                    121:                return NULL;
                    122: 
                    123:        /* get new task */
                    124:        if ((task = TAILQ_FIRST(&root->root_unuse)))
                    125:                TAILQ_REMOVE(&root->root_unuse, task, task_node);
                    126:        else {
                    127:                task = malloc(sizeof(sched_task_t));
                    128:                if (!task) {
                    129:                        LOGERR;
                    130:                        return NULL;
                    131:                }
                    132:        }
                    133: 
                    134:        memset(task, 0, sizeof(sched_task_t));
                    135:        task->task_id = 0;
                    136:        task->task_type = taskWRITE;
                    137:        task->task_root = root;
                    138:        task->task_func = func;
                    139: 
                    140:        TASK_ARG(task) = arg;
                    141:        va_start(lst, arg);
                    142:        TASK_FD(task) = va_arg(lst, int);
                    143:        va_end(lst);
                    144: 
                    145:        if (root->root_hooks.hook_add.write)
                    146:                ptr = root->root_hooks.hook_add.write(task, NULL);
                    147:        else
                    148:                ptr = NULL;
                    149: 
                    150:        if (!ptr)
                    151:                TAILQ_INSERT_TAIL(&root->root_write, task, task_node);
                    152:        else {
                    153:                task->task_type = taskUNUSE;
                    154:                TAILQ_INSERT_TAIL(&root->root_unuse, task, task_node);
                    155:                task = NULL;
                    156:        }
                    157: 
                    158:        return task;
                    159: }
                    160: 
                    161: /*
                    162:  * schedTimer() - Add TIMER task to scheduler queue
                    163:  * @root = root task
                    164:  * @func = task execution function
                    165:  * @arg = 1st func argument
                    166:  * @... = next func arguments in microSecs, define period 1sec == 1000000
                    167:  * return: NULL error or !=NULL new queued task
                    168:  */
                    169: sched_task_t *
                    170: schedTimer(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, ...)
                    171: {
                    172:        sched_task_t *task, *t = NULL;
                    173:        void *ptr;
                    174:        va_list lst;
                    175:        struct timeval now;
                    176:        struct timespec nw;
                    177:        u_int tim;
                    178: 
                    179:        if (!root || !func)
                    180:                return NULL;
                    181: 
                    182:        /* get new task */
                    183:        if ((task = TAILQ_FIRST(&root->root_unuse)))
                    184:                TAILQ_REMOVE(&root->root_unuse, task, task_node);
                    185:        else {
                    186:                task = malloc(sizeof(sched_task_t));
                    187:                if (!task) {
                    188:                        LOGERR;
                    189:                        return NULL;
                    190:                }
                    191:        }
                    192: 
                    193:        memset(task, 0, sizeof(sched_task_t));
                    194:        task->task_id = 0;
                    195:        task->task_type = taskTIMER;
                    196:        task->task_root = root;
                    197:        task->task_func = func;
                    198: 
                    199:        TASK_ARG(task) = arg;
                    200:        va_start(lst, arg);
                    201:        tim = va_arg(lst, u_int);
                    202:        va_end(lst);
                    203: 
                    204:        /* calculate timeval structure */
                    205:        clock_gettime(CLOCK_MONOTONIC, &nw);
                    206:        now.tv_sec = nw.tv_sec + tim / 1000000;
                    207:        now.tv_usec = nw.tv_nsec / 1000 + (tim % 1000000);
                    208:        if (now.tv_usec >= 1000000) {
                    209:                now.tv_sec++;
                    210:                now.tv_usec -= 1000000;
                    211:        } else if (now.tv_usec < 0) {
                    212:                now.tv_sec--;
                    213:                now.tv_usec += 1000000;
                    214:        }
                    215:        TASK_TV(task) = now;
                    216: 
                    217:        if (root->root_hooks.hook_add.timer)
                    218:                ptr = root->root_hooks.hook_add.timer(task, NULL);
                    219:        else
                    220:                ptr = NULL;
                    221: 
                    222:        if (!ptr) {
                    223: #ifdef TIMER_WITHOUT_SORT
                    224:                TAILQ_INSERT_TAIL(&root->root_timer, task, task_node);
                    225: #else
                    226:                TAILQ_FOREACH(t, &root->root_timer, task_node)
                    227:                        if (timercmp(&TASK_TV(task), &TASK_TV(t), -) < 1)
                    228:                                break;
                    229:                if (!t)
                    230:                        TAILQ_INSERT_TAIL(&root->root_timer, task, task_node);
                    231:                else
                    232:                        TAILQ_INSERT_BEFORE(t, task, task_node);
                    233: #endif
                    234:        } else {
                    235:                task->task_type = taskUNUSE;
                    236:                TAILQ_INSERT_TAIL(&root->root_unuse, task, task_node);
                    237:                task = NULL;
                    238:        }
                    239: 
                    240:        return task;
                    241: }
                    242: 
                    243: /*
                    244:  * schedEvent() - Add EVENT task to scheduler queue
                    245:  * @root = root task
                    246:  * @func = task execution function
                    247:  * @arg = 1st func argument
                    248:  * @... = next func arguments, like u_long
                    249:  * return: NULL error or !=NULL new queued task
                    250:  */
                    251: sched_task_t *
                    252: schedEvent(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, ...)
                    253: {
                    254:        sched_task_t *task;
                    255:        void *ptr;
                    256:        va_list lst;
                    257: 
                    258:        if (!root || !func)
                    259:                return NULL;
                    260: 
                    261:        /* get new task */
                    262:        if ((task = TAILQ_FIRST(&root->root_unuse)))
                    263:                TAILQ_REMOVE(&root->root_unuse, task, task_node);
                    264:        else {
                    265:                task = malloc(sizeof(sched_task_t));
                    266:                if (!task) {
                    267:                        LOGERR;
                    268:                        return NULL;
                    269:                }
                    270:        }
                    271: 
                    272:        memset(task, 0, sizeof(sched_task_t));
                    273:        task->task_id = 0;
                    274:        task->task_type = taskEVENT;
                    275:        task->task_root = root;
                    276:        task->task_func = func;
                    277: 
                    278:        TASK_ARG(task) = arg;
                    279:        va_start(lst, arg);
                    280:        TASK_VAL(task) = va_arg(lst, u_long);
                    281:        va_end(lst);
                    282: 
                    283:        if (root->root_hooks.hook_add.event)
                    284:                ptr = root->root_hooks.hook_add.event(task, NULL);
                    285:        else
                    286:                ptr = NULL;
                    287: 
                    288:        if (!ptr)
                    289:                TAILQ_INSERT_TAIL(&root->root_event, task, task_node);
                    290:        else {
                    291:                task->task_type = taskUNUSE;
                    292:                TAILQ_INSERT_TAIL(&root->root_unuse, task, task_node);
                    293:                task = NULL;
                    294:        }
                    295: 
                    296:        return task;
                    297: }
                    298: 
                    299: 
                    300: /*
                    301:  * schedEventLo() - Add EVENT_Lo task to scheduler queue
                    302:  * @root = root task
                    303:  * @func = task execution function
                    304:  * @arg = 1st func argument
                    305:  * @... = next func arguments, like u_long
                    306:  * return: NULL error or !=NULL new queued task
                    307:  */
                    308: sched_task_t *
                    309: schedEventLo(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, ...)
                    310: {
                    311:        sched_task_t *task;
                    312:        void *ptr;
                    313:        va_list lst;
                    314: 
                    315:        if (!root || !func)
                    316:                return NULL;
                    317: 
                    318:        /* get new task */
                    319:        if ((task = TAILQ_FIRST(&root->root_unuse)))
                    320:                TAILQ_REMOVE(&root->root_unuse, task, task_node);
                    321:        else {
                    322:                task = malloc(sizeof(sched_task_t));
                    323:                if (!task) {
                    324:                        LOGERR;
                    325:                        return NULL;
                    326:                }
                    327:        }
                    328: 
                    329:        memset(task, 0, sizeof(sched_task_t));
                    330:        task->task_id = 0;
                    331:        task->task_type = taskEVENT;
                    332:        task->task_root = root;
                    333:        task->task_func = func;
                    334: 
                    335:        TASK_ARG(task) = arg;
                    336:        va_start(lst, arg);
                    337:        TASK_VAL(task) = va_arg(lst, u_long);
                    338:        va_end(lst);
                    339: 
                    340:        if (root->root_hooks.hook_add.eventlo)
                    341:                ptr = root->root_hooks.hook_add.eventlo(task, NULL);
                    342:        else
                    343:                ptr = NULL;
                    344: 
                    345:        if (!ptr)
                    346:                TAILQ_INSERT_TAIL(&root->root_eventlo, task, task_node);
                    347:        else {
                    348:                task->task_type = taskUNUSE;
                    349:                TAILQ_INSERT_TAIL(&root->root_unuse, task, task_node);
                    350:                task = NULL;
                    351:        }
                    352: 
                    353:        return task;
                    354: }
                    355: 
                    356: /*
                    357:  * schedCallOnce() - Call once from scheduler
                    358:  * @root = root task
                    359:  * @func = task execution function
                    360:  * @arg = 1st func argument
                    361:  * @... = next func arguments, like u_long
                    362:  * return: NULL error or !=NULL new queued task
                    363:  */
                    364: sched_task_t *
                    365: schedCallOnce(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, ...)
                    366: {
                    367:        sched_task_t *task;
                    368:        va_list lst;
                    369: 
                    370:        if (!root || !func)
                    371:                return NULL;
                    372: 
                    373:        /* get new task */
                    374:        if ((task = TAILQ_FIRST(&root->root_unuse)))
                    375:                TAILQ_REMOVE(&root->root_unuse, task, task_node);
                    376:        else {
                    377:                task = malloc(sizeof(sched_task_t));
                    378:                if (!task) {
                    379:                        LOGERR;
                    380:                        return NULL;
                    381:                }
                    382:        }
                    383: 
                    384:        memset(task, 0, sizeof(sched_task_t));
                    385:        task->task_id = 0;
                    386:        task->task_type = taskEVENT;
                    387:        task->task_root = root;
                    388:        task->task_func = func;
                    389: 
                    390:        TASK_ARG(task) = arg;
                    391:        va_start(lst, arg);
                    392:        TASK_VAL(task) = va_arg(lst, u_long);
                    393:        va_end(lst);
                    394: 
                    395:        if (schedCall(task)) {
                    396:                task->task_type = taskUNUSE;
                    397:                TAILQ_INSERT_TAIL(&root->root_unuse, task, task_node);
                    398:                task = NULL;
                    399:        }
                    400: 
                    401:        return task;
                    402: }

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