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

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

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