Annotation of libaitsched/src/aitsched.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: #include "hooks.h"
! 48:
! 49:
! 50: #pragma GCC visibility push(hidden)
! 51:
! 52: int sched_Errno;
! 53: char sched_Error[STRSIZ];
! 54:
! 55: #pragma GCC visibility pop
! 56:
! 57:
! 58: // sched_GetErrno() Get error code of last operation
! 59: inline int
! 60: sched_GetErrno()
! 61: {
! 62: return sched_Errno;
! 63: }
! 64:
! 65: // sched_GetError() Get error text of last operation
! 66: inline const char *
! 67: sched_GetError()
! 68: {
! 69: return sched_Error;
! 70: }
! 71:
! 72: // sched_SetErr() Set error to variables for internal use!!!
! 73: inline void
! 74: sched_SetErr(int eno, char *estr, ...)
! 75: {
! 76: va_list lst;
! 77:
! 78: sched_Errno = eno;
! 79: memset(sched_Error, 0, sizeof sched_Error);
! 80: va_start(lst, estr);
! 81: vsnprintf(sched_Error, sizeof sched_Error, estr, lst);
! 82: va_end(lst);
! 83: }
! 84:
! 85: /* Init and prepare scheduler functions */
! 86:
! 87: /*
! 88: * schedInit() - Init scheduler
! 89: * @data = optional data if !=NULL
! 90: * @datlen = data len if data is set
! 91: * return: allocated root task if ok or NULL error
! 92: */
! 93: sched_root_task_t *
! 94: schedInit(void ** __restrict data, size_t datlen)
! 95: {
! 96: sched_root_task_t *root = NULL;
! 97: int (*func)(sched_root_task_t *);
! 98:
! 99: root = malloc(sizeof(sched_root_task_t));
! 100: if (!root)
! 101: LOGERR
! 102: else {
! 103: memset(root, 0, sizeof(sched_root_task_t));
! 104:
! 105: if (data && *data) {
! 106: if (datlen) {
! 107: root->root_data.iov_base = *data;
! 108: root->root_data.iov_len = datlen;
! 109: } else {
! 110: func = *data;
! 111: func(root);
! 112: }
! 113: }
! 114: }
! 115:
! 116: if (root->root_hooks.hook_root.init)
! 117: root->root_hooks.hook_root.init(root, NULL);
! 118: return root;
! 119: }
! 120:
! 121: /*
! 122: * schedRegisterIO() - Register IO handles and bind tasks to it
! 123: * @root = root task
! 124: * return: -1 error or 0 ok
! 125: */
! 126: int
! 127: schedRegisterIO(sched_root_task_t * __restrict root)
! 128: {
! 129: if (!root || (root->root_data.iov_base && root->root_data.iov_len))
! 130: return -1;
! 131:
! 132: if (root->root_hooks.hook_root.fini)
! 133: root->root_hooks.hook_root.fini(root, NULL);
! 134: memset(&root->root_hooks, 0, sizeof root->root_hooks);
! 135:
! 136: root->root_hooks.hook_add.read = sched_hook_read;
! 137: root->root_hooks.hook_add.write = sched_hook_write;
! 138:
! 139: root->root_hooks.hook_exec.cancel = sched_hook_cancel;
! 140: root->root_hooks.hook_exec.fetch = sched_hook_fetch;
! 141:
! 142: root->root_hooks.hook_root.init = sched_hook_init;
! 143: root->root_hooks.hook_root.fini = sched_hook_fini;
! 144:
! 145: if (root->root_hooks.hook_root.init)
! 146: root->root_hooks.hook_root.init(root, NULL);
! 147: return 0;
! 148: }
! 149:
! 150: /*
! 151: * schedEnd() - End scheduler & free all resources
! 152: * @root = root task
! 153: * return: -1 error or 0 ok
! 154: */
! 155: int
! 156: schedEnd(sched_root_task_t * __restrict root)
! 157: {
! 158: sched_task_t *task;
! 159:
! 160: if (!root)
! 161: return -1;
! 162:
! 163: TAILQ_FOREACH(task, &root->root_read, task_node) {
! 164: schedCancel(task);
! 165: }
! 166: TAILQ_FOREACH(task, &root->root_write, task_node) {
! 167: schedCancel(task);
! 168: }
! 169: TAILQ_FOREACH(task, &root->root_timer, task_node) {
! 170: schedCancel(task);
! 171: }
! 172: TAILQ_FOREACH(task, &root->root_event, task_node) {
! 173: schedCancel(task);
! 174: }
! 175: TAILQ_FOREACH(task, &root->root_ready, task_node) {
! 176: schedCancel(task);
! 177: }
! 178:
! 179: while ((task = TAILQ_FIRST(&root->root_unuse))) {
! 180: TAILQ_REMOVE(&root->root_unuse, task, task_node);
! 181: free(task);
! 182: }
! 183:
! 184: if (root->root_hooks.hook_root.fini)
! 185: root->root_hooks.hook_root.fini(root, NULL);
! 186:
! 187: free(root);
! 188: return 0;
! 189: }
! 190:
! 191: /*
! 192: * schedCall() - Call task execution function
! 193: * @task = current task
! 194: * return: !=NULL error or =NULL ok
! 195: */
! 196: inline void *
! 197: schedCall(sched_task_t * __restrict task)
! 198: {
! 199: if (!task)
! 200: return (void*) -1;
! 201:
! 202: task->task_id++;
! 203: return task->task_func(task);
! 204: }
! 205:
! 206: /*
! 207: * schedFetch() - Fetch ready task
! 208: * @root = root task
! 209: * return: =NULL error or !=NULL ready task
! 210: */
! 211: inline void *
! 212: schedFetch(sched_root_task_t * __restrict root)
! 213: {
! 214: void *ptr;
! 215:
! 216: if (!root)
! 217: return NULL;
! 218:
! 219: if (root->root_hooks.hook_exec.fetch)
! 220: ptr = root->root_hooks.hook_exec.fetch(root, NULL);
! 221: else
! 222: ptr = NULL;
! 223:
! 224: return ptr;
! 225: }
! 226:
! 227: /*
! 228: * schedCancel() - Cancel task from scheduler
! 229: * @task = task
! 230: * return: -1 error or 0 ok
! 231: */
! 232: int
! 233: schedCancel(sched_task_t * __restrict task)
! 234: {
! 235: sched_queue_t *queue;
! 236:
! 237: if (!task || !task->task_root)
! 238: return -1;
! 239:
! 240: if (task->task_root->root_hooks.hook_exec.cancel)
! 241: if (task->task_root->root_hooks.hook_exec.cancel(task, NULL))
! 242: return -1;
! 243:
! 244: switch (task->task_type) {
! 245: case taskREAD:
! 246: queue = &task->task_root->root_read;
! 247: break;
! 248: case taskWRITE:
! 249: queue = &task->task_root->root_write;
! 250: break;
! 251: case taskTIMER:
! 252: queue = &task->task_root->root_timer;
! 253: break;
! 254: case taskEVENT:
! 255: queue = &task->task_root->root_event;
! 256: break;
! 257: case taskREADY:
! 258: queue = &task->task_root->root_ready;
! 259: break;
! 260: default:
! 261: queue = NULL;
! 262: }
! 263: if (queue)
! 264: TAILQ_REMOVE(queue, task, task_node);
! 265: if (task->task_type != taskUNUSE) {
! 266: task->task_type = taskUNUSE;
! 267: TAILQ_INSERT_TAIL(&task->task_root->root_unuse, task, task_node);
! 268: }
! 269:
! 270: return 0;
! 271: }
! 272:
! 273: /*
! 274: * schedCancelby() - Cancel task from scheduler by criteria
! 275: * @root = root task
! 276: * @queue = cancel from queue, if =NULL cancel same task from all queues
! 277: * @criteria = find task by criteria [CRITERIA_CALL|CRITERIA_ARG|CRITERIA_FD|CRITERIA_VAL|CRITERIA_TV]
! 278: * @param = search parameter
! 279: * @hook = custom cleanup hook function, may be NULL
! 280: * return: -1 error or 0 ok
! 281: */
! 282: int
! 283: schedCancelby(sched_root_task_t * __restrict root, sched_queue_t * __restrict queue,
! 284: u_char criteria, void *param, sched_hook_func_t hook)
! 285: {
! 286: sched_task_t *task;
! 287: int flg = 0;
! 288:
! 289: if (!root)
! 290: return -1;
! 291: if (!queue) {
! 292: if (schedCancelby(root, &root->root_read, criteria, param, hook))
! 293: return -2;
! 294: if (schedCancelby(root, &root->root_write, criteria, param, hook))
! 295: return -2;
! 296: if (schedCancelby(root, &root->root_timer, criteria, param, hook))
! 297: return -2;
! 298: if (schedCancelby(root, &root->root_event, criteria, param, hook))
! 299: return -2;
! 300: if (schedCancelby(root, &root->root_ready, criteria, param, hook))
! 301: return -2;
! 302: if (schedCancelby(root, &root->root_read, criteria, param, hook))
! 303: return -2;
! 304: return 0;
! 305: }
! 306:
! 307: TAILQ_FOREACH(task, queue, task_node)
! 308: if (criteria == CRITERIA_CALL) {
! 309: if (task->task_func == (sched_task_func_t) param) {
! 310: flg++;
! 311: break;
! 312: }
! 313: } else if (criteria == CRITERIA_ARG) {
! 314: if (task->task_arg == param) {
! 315: flg++;
! 316: break;
! 317: }
! 318: } else if (criteria == CRITERIA_FD) {
! 319: if (TASK_FD(task) == (u_long) param) {
! 320: flg++;
! 321: break;
! 322: }
! 323: } else if (criteria == CRITERIA_VAL) {
! 324: if (TASK_VAL(task) == (u_long) param) {
! 325: flg++;
! 326: break;
! 327: }
! 328: } else if (criteria == CRITERIA_TV) {
! 329: if (&TASK_TV(task) == (struct timeval*) param) {
! 330: flg++;
! 331: break;
! 332: }
! 333: } else {
! 334: sched_SetErr(EINVAL, "Invalid parameter criteria %d", criteria);
! 335: return -1;
! 336: }
! 337: if (!flg || !task) /* task not found */
! 338: return 0;
! 339:
! 340: if (task->task_root->root_hooks.hook_exec.cancel)
! 341: if (task->task_root->root_hooks.hook_exec.cancel(task, NULL))
! 342: return -1;
! 343: if (hook)
! 344: if (hook(task, NULL))
! 345: return -3;
! 346:
! 347: TAILQ_REMOVE(queue, task, task_node);
! 348:
! 349: if (task->task_type != taskUNUSE) {
! 350: task->task_type = taskUNUSE;
! 351: TAILQ_INSERT_TAIL(&task->task_root->root_unuse, task, task_node);
! 352: }
! 353: return 0;
! 354: }
! 355:
! 356: /*
! 357: * schedRun() - Scheduler *run loop*
! 358: * @root = root task
! 359: * return: -1 error or 0 ok
! 360: */
! 361: int
! 362: schedRun(sched_root_task_t * __restrict root)
! 363: {
! 364: sched_task_t *task;
! 365:
! 366: if (!root)
! 367: return -1;
! 368:
! 369: if (root->root_hooks.hook_exec.run)
! 370: if (root->root_hooks.hook_exec.run(root, NULL))
! 371: return -1;
! 372: if (root->root_hooks.hook_exec.fetch)
! 373: while ((task = root->root_hooks.hook_exec.fetch(root, NULL)))
! 374: schedCall(task);
! 375:
! 376: return 0;
! 377: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>