Annotation of libaitsched/src/tasks.c, revision 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>