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

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