Annotation of libaitsched/src/tasks.c, revision 1.24.2.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.24.2.4! misho 6: * $Id: tasks.c,v 1.24.2.3 2014/05/21 22:09:01 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:
1.23 misho 15: Copyright 2004 - 2014
1.1 misho 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.13 misho 49: /*
50: * sched_useTask() - Get and init new task
51: *
52: * @root = root task
53: * return: NULL error or !=NULL prepared task
54: */
1.16 misho 55: sched_task_t *
1.13 misho 56: sched_useTask(sched_root_task_t * __restrict root)
1.4 misho 57: {
1.7 misho 58: sched_task_t *task, *tmp;
1.4 misho 59:
1.24.2.4! misho 60: SCHED_QLOCK(root, taskUNUSE);
1.7 misho 61: TAILQ_FOREACH_SAFE(task, &root->root_unuse, task_node, tmp) {
1.4 misho 62: if (!TASK_ISLOCKED(task)) {
63: TAILQ_REMOVE(&root->root_unuse, task, task_node);
64: break;
65: }
66: }
1.24.2.4! misho 67: SCHED_QUNLOCK(root, taskUNUSE);
1.4 misho 68:
69: if (!task) {
70: task = malloc(sizeof(sched_task_t));
71: if (!task) {
72: LOGERR;
73: return NULL;
74: }
75: }
76:
1.9 misho 77: memset(task, 0, sizeof(sched_task_t));
78: task->task_id = (uintptr_t) task;
1.4 misho 79: return task;
80: }
81:
1.13 misho 82: /*
83: * sched_unuseTask() - Unlock and put task to unuse queue
84: *
85: * @task = task
86: * return: always is NULL
87: */
1.16 misho 88: sched_task_t *
1.13 misho 89: sched_unuseTask(sched_task_t * __restrict task)
1.4 misho 90: {
91: TASK_UNLOCK(task);
1.24.2.4! misho 92:
1.5 misho 93: TASK_TYPE(task) = taskUNUSE;
1.24.2.4! misho 94: insert_task_to(task, &(TASK_ROOT(task))->root_unuse);
1.4 misho 95:
1.24.2.4! misho 96: task = NULL;
1.4 misho 97: return task;
98: }
99:
1.14 misho 100: #pragma GCC visibility push(hidden)
101:
102: #ifdef HAVE_LIBPTHREAD
103: void *
104: _sched_threadWrapper(sched_task_t *t)
105: {
106: void *ret = NULL;
1.24.2.4! misho 107: sched_root_task_t *r;
1.21 misho 108:
109: if (!t || !TASK_ROOT(t))
1.14 misho 110: pthread_exit(ret);
1.24.2.4! misho 111: else
! 112: r = (sched_root_task_t*) TASK_ROOT(t);
1.14 misho 113:
114: pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
1.21 misho 115: /*
1.14 misho 116: pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
1.21 misho 117: */
1.20 misho 118:
1.15 misho 119: /* notify parent, thread is ready for execution */
1.14 misho 120: pthread_testcancel();
121:
1.22 misho 122: ret = schedCall(t);
1.24.2.4! misho 123: r->root_ret = ret;
! 124:
! 125: if (TASK_VAL(t)) {
! 126: transit_task2unuse(t, &r->root_thread);
! 127: TASK_VAL(t) = 0;
! 128: }
1.14 misho 129:
130: pthread_exit(ret);
131: }
132: #endif
133:
1.24 misho 134: #if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME) && defined(HAVE_TIMER_DELETE)
1.19 misho 135: void *
136: _sched_rtcWrapper(sched_task_t *t)
137: {
138: sched_task_t *task;
1.24.2.4! misho 139: void *ret;
1.19 misho 140:
141: if (!t || !TASK_ROOT(t) || !TASK_DATA(t))
142: return NULL;
143: else {
144: task = (sched_task_t*) TASK_DATA(t);
1.24.2.4! misho 145: timer_delete((timer_t) TASK_DATLEN(t));
1.19 misho 146: }
147:
1.24.2.4! misho 148: ret = schedCall(task);
1.20 misho 149:
1.24.2.4! misho 150: transit_task2unuse(task, &(TASK_ROOT(task))->root_rtc);
! 151: return ret;
1.19 misho 152: }
153: #endif
154:
1.14 misho 155: #pragma GCC visibility pop
156:
157: /*
158: * sched_taskExit() - Exit routine for scheduler task, explicit required for thread tasks
159: *
160: * @task = current task
161: * @retcode = return code
162: * return: return code
163: */
1.16 misho 164: void *
1.14 misho 165: sched_taskExit(sched_task_t *task, intptr_t retcode)
166: {
167: if (!task || !TASK_ROOT(task))
168: return (void*) -1;
169:
170: if (TASK_ROOT(task)->root_hooks.hook_exec.exit)
171: TASK_ROOT(task)->root_hooks.hook_exec.exit(task, (void*) retcode);
172:
173: TASK_ROOT(task)->root_ret = (void*) retcode;
174: return (void*) retcode;
175: }
176:
1.4 misho 177:
1.1 misho 178: /*
1.2 misho 179: * schedRead() - Add READ I/O task to scheduler queue
1.6 misho 180: *
1.1 misho 181: * @root = root task
182: * @func = task execution function
183: * @arg = 1st func argument
1.2 misho 184: * @fd = fd handle
1.5 misho 185: * @opt_data = Optional data
186: * @opt_dlen = Optional data length
1.1 misho 187: * return: NULL error or !=NULL new queued task
188: */
189: sched_task_t *
1.5 misho 190: schedRead(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd,
191: void *opt_data, size_t opt_dlen)
1.1 misho 192: {
193: sched_task_t *task;
194: void *ptr;
195:
196: if (!root || !func)
197: return NULL;
198:
199: /* get new task */
1.13 misho 200: if (!(task = sched_useTask(root)))
1.4 misho 201: return NULL;
1.1 misho 202:
1.24.2.4! misho 203: TASK_FUNC(task) = func;
1.5 misho 204: TASK_TYPE(task) = taskREAD;
205: TASK_ROOT(task) = root;
1.1 misho 206:
207: TASK_ARG(task) = arg;
1.2 misho 208: TASK_FD(task) = fd;
1.1 misho 209:
1.5 misho 210: TASK_DATA(task) = opt_data;
211: TASK_DATLEN(task) = opt_dlen;
212:
1.1 misho 213: if (root->root_hooks.hook_add.read)
214: ptr = root->root_hooks.hook_add.read(task, NULL);
215: else
216: ptr = NULL;
217:
1.24.2.4! misho 218: if (!ptr)
! 219: insert_task_to(task, &root->root_read);
! 220: else
1.13 misho 221: task = sched_unuseTask(task);
1.1 misho 222:
223: return task;
224: }
225:
226: /*
1.2 misho 227: * schedWrite() - Add WRITE I/O task to scheduler queue
1.6 misho 228: *
1.1 misho 229: * @root = root task
230: * @func = task execution function
231: * @arg = 1st func argument
1.2 misho 232: * @fd = fd handle
1.5 misho 233: * @opt_data = Optional data
234: * @opt_dlen = Optional data length
1.1 misho 235: * return: NULL error or !=NULL new queued task
236: */
237: sched_task_t *
1.5 misho 238: schedWrite(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd,
239: void *opt_data, size_t opt_dlen)
1.1 misho 240: {
241: sched_task_t *task;
242: void *ptr;
243:
244: if (!root || !func)
245: return NULL;
246:
247: /* get new task */
1.13 misho 248: if (!(task = sched_useTask(root)))
1.4 misho 249: return NULL;
1.1 misho 250:
1.24.2.4! misho 251: TASK_FUNC(task) = func;
1.5 misho 252: TASK_TYPE(task) = taskWRITE;
253: TASK_ROOT(task) = root;
1.1 misho 254:
255: TASK_ARG(task) = arg;
1.2 misho 256: TASK_FD(task) = fd;
1.1 misho 257:
1.5 misho 258: TASK_DATA(task) = opt_data;
259: TASK_DATLEN(task) = opt_dlen;
260:
1.1 misho 261: if (root->root_hooks.hook_add.write)
262: ptr = root->root_hooks.hook_add.write(task, NULL);
263: else
264: ptr = NULL;
265:
1.24.2.4! misho 266: if (!ptr)
! 267: insert_task_to(task, &root->root_write);
! 268: else
1.13 misho 269: task = sched_unuseTask(task);
1.1 misho 270:
271: return task;
272: }
273:
274: /*
1.9 misho 275: * schedNode() - Add NODE task to scheduler queue
276: *
277: * @root = root task
278: * @func = task execution function
279: * @arg = 1st func argument
280: * @fd = fd handle
281: * @opt_data = Optional data
282: * @opt_dlen = Optional data length
283: * return: NULL error or !=NULL new queued task
284: */
285: sched_task_t *
286: schedNode(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd,
287: void *opt_data, size_t opt_dlen)
288: {
1.24.2.3 misho 289: #if SUP_ENABLE != KQ_SUPPORT
1.23 misho 290: sched_SetErr(ENOTSUP, "disabled kqueue support");
291: return NULL;
292: #else
1.9 misho 293: sched_task_t *task;
294: void *ptr;
295:
296: if (!root || !func)
297: return NULL;
298:
299: /* get new task */
1.13 misho 300: if (!(task = sched_useTask(root)))
1.9 misho 301: return NULL;
302:
1.24.2.4! misho 303: TASK_FUNC(task) = func;
1.9 misho 304: TASK_TYPE(task) = taskNODE;
305: TASK_ROOT(task) = root;
306:
307: TASK_ARG(task) = arg;
308: TASK_FD(task) = fd;
309:
310: TASK_DATA(task) = opt_data;
311: TASK_DATLEN(task) = opt_dlen;
312:
313: if (root->root_hooks.hook_add.node)
314: ptr = root->root_hooks.hook_add.node(task, NULL);
315: else
316: ptr = NULL;
317:
1.24.2.4! misho 318: if (!ptr)
! 319: insert_task_to(task, &root->root_node);
! 320: else
1.13 misho 321: task = sched_unuseTask(task);
1.9 misho 322:
323: return task;
1.24.2.3 misho 324: #endif /* KQ_SUPPORT */
1.9 misho 325: }
326:
327: /*
328: * schedProc() - Add PROC task to scheduler queue
329: *
330: * @root = root task
331: * @func = task execution function
332: * @arg = 1st func argument
333: * @pid = PID
334: * @opt_data = Optional data
335: * @opt_dlen = Optional data length
336: * return: NULL error or !=NULL new queued task
337: */
338: sched_task_t *
339: schedProc(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, u_long pid,
340: void *opt_data, size_t opt_dlen)
341: {
1.24.2.3 misho 342: #if SUP_ENABLE != KQ_SUPPORT
1.23 misho 343: sched_SetErr(ENOTSUP, "disabled kqueue support");
344: return NULL;
345: #else
1.9 misho 346: sched_task_t *task;
347: void *ptr;
348:
349: if (!root || !func)
350: return NULL;
351:
352: /* get new task */
1.13 misho 353: if (!(task = sched_useTask(root)))
1.9 misho 354: return NULL;
355:
1.24.2.4! misho 356: TASK_FUNC(task) = func;
1.9 misho 357: TASK_TYPE(task) = taskPROC;
358: TASK_ROOT(task) = root;
359:
360: TASK_ARG(task) = arg;
361: TASK_VAL(task) = pid;
362:
363: TASK_DATA(task) = opt_data;
364: TASK_DATLEN(task) = opt_dlen;
365:
366: if (root->root_hooks.hook_add.proc)
367: ptr = root->root_hooks.hook_add.proc(task, NULL);
368: else
369: ptr = NULL;
370:
1.24.2.4! misho 371: if (!ptr)
! 372: insert_task_to(task, &root->root_proc);
! 373: else
1.13 misho 374: task = sched_unuseTask(task);
1.9 misho 375:
376: return task;
1.24.2.3 misho 377: #endif /* KQ_SUPPORT */
1.9 misho 378: }
379:
380: /*
381: * schedUser() - Add trigger USER task to scheduler queue
382: *
383: * @root = root task
384: * @func = task execution function
385: * @arg = 1st func argument
386: * @id = Trigger ID
387: * @opt_data = Optional data
388: * @opt_dlen = Optional user's trigger flags
389: * return: NULL error or !=NULL new queued task
390: */
391: sched_task_t *
392: schedUser(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, u_long id,
393: void *opt_data, size_t opt_dlen)
394: {
1.24.2.3 misho 395: #if SUP_ENABLE != KQ_SUPPORT
1.23 misho 396: sched_SetErr(ENOTSUP, "disabled kqueue support");
397: return NULL;
398: #else
1.9 misho 399: #ifndef EVFILT_USER
400: sched_SetErr(ENOTSUP, "Not supported kevent() filter");
401: return NULL;
402: #else
403: sched_task_t *task;
404: void *ptr;
405:
406: if (!root || !func)
407: return NULL;
408:
409: /* get new task */
1.13 misho 410: if (!(task = sched_useTask(root)))
1.9 misho 411: return NULL;
412:
1.24.2.4! misho 413: TASK_FUNC(task) = func;
1.9 misho 414: TASK_TYPE(task) = taskUSER;
415: TASK_ROOT(task) = root;
416:
417: TASK_ARG(task) = arg;
418: TASK_VAL(task) = id;
419:
420: TASK_DATA(task) = opt_data;
421: TASK_DATLEN(task) = opt_dlen;
422:
423: if (root->root_hooks.hook_add.user)
424: ptr = root->root_hooks.hook_add.user(task, NULL);
425: else
426: ptr = NULL;
427:
1.24.2.4! misho 428: if (!ptr)
! 429: insert_task_to(task, &root->root_user);
! 430: else
1.13 misho 431: task = sched_unuseTask(task);
1.9 misho 432:
433: return task;
1.23 misho 434: #endif /* EVFILT_USER */
1.24.2.3 misho 435: #endif /* KQ_SUPPORT */
1.9 misho 436: }
437:
438: /*
439: * schedSignal() - Add SIGNAL task to scheduler queue
440: *
441: * @root = root task
442: * @func = task execution function
443: * @arg = 1st func argument
444: * @sig = Signal
445: * @opt_data = Optional data
446: * @opt_dlen = Optional data length
447: * return: NULL error or !=NULL new queued task
448: */
449: sched_task_t *
450: schedSignal(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, u_long sig,
451: void *opt_data, size_t opt_dlen)
452: {
1.24.2.3 misho 453: #if SUP_ENABLE != KQ_SUPPORT
1.23 misho 454: sched_SetErr(ENOTSUP, "disabled kqueue support");
455: return NULL;
456: #else
1.9 misho 457: sched_task_t *task;
458: void *ptr;
459:
460: if (!root || !func)
461: return NULL;
462:
463: /* get new task */
1.13 misho 464: if (!(task = sched_useTask(root)))
1.9 misho 465: return NULL;
466:
1.24.2.4! misho 467: TASK_FUNC(task) = func;
1.9 misho 468: TASK_TYPE(task) = taskSIGNAL;
469: TASK_ROOT(task) = root;
470:
471: TASK_ARG(task) = arg;
472: TASK_VAL(task) = sig;
473:
474: TASK_DATA(task) = opt_data;
475: TASK_DATLEN(task) = opt_dlen;
476:
477: if (root->root_hooks.hook_add.signal)
478: ptr = root->root_hooks.hook_add.signal(task, NULL);
479: else
480: ptr = NULL;
481:
1.24.2.4! misho 482: if (!ptr)
! 483: insert_task_to(task, &root->root_signal);
! 484: else
1.13 misho 485: task = sched_unuseTask(task);
1.9 misho 486:
487: return task;
1.24.2.3 misho 488: #endif /* KQ_SUPPORT */
1.9 misho 489: }
490:
491: /*
1.8 misho 492: * schedAlarm() - Add ALARM task to scheduler queue
493: *
494: * @root = root task
495: * @func = task execution function
496: * @arg = 1st func argument
497: * @ts = timeout argument structure, minimum alarm timer resolution is 1msec!
1.17 misho 498: * @opt_data = Alarm timer ID
1.8 misho 499: * @opt_dlen = Optional data length
500: * return: NULL error or !=NULL new queued task
501: */
502: sched_task_t *
503: schedAlarm(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, struct timespec ts,
504: void *opt_data, size_t opt_dlen)
505: {
1.24.2.3 misho 506: #if SUP_ENABLE != KQ_SUPPORT
1.23 misho 507: sched_SetErr(ENOTSUP, "disabled kqueue support");
508: return NULL;
509: #else
1.8 misho 510: sched_task_t *task;
511: void *ptr;
512:
513: if (!root || !func)
514: return NULL;
515:
516: /* get new task */
1.13 misho 517: if (!(task = sched_useTask(root)))
1.8 misho 518: return NULL;
519:
1.24.2.4! misho 520: TASK_FUNC(task) = func;
1.8 misho 521: TASK_TYPE(task) = taskALARM;
522: TASK_ROOT(task) = root;
523:
524: TASK_ARG(task) = arg;
525: TASK_TS(task) = ts;
526:
527: TASK_DATA(task) = opt_data;
528: TASK_DATLEN(task) = opt_dlen;
529:
530: if (root->root_hooks.hook_add.alarm)
531: ptr = root->root_hooks.hook_add.alarm(task, NULL);
532: else
533: ptr = NULL;
534:
1.24.2.4! misho 535: if (!ptr)
! 536: insert_task_to(task, &root->root_alarm);
! 537: else
1.13 misho 538: task = sched_unuseTask(task);
1.8 misho 539:
540: return task;
1.24.2.3 misho 541: #endif /* KQ_SUPPORT */
1.8 misho 542: }
543:
1.11 misho 544: #ifdef AIO_SUPPORT
545: /*
546: * schedAIO() - Add AIO task to scheduler queue
547: *
548: * @root = root task
549: * @func = task execution function
550: * @arg = 1st func argument
551: * @acb = AIO cb structure address
552: * @opt_data = Optional data
553: * @opt_dlen = Optional data length
554: * return: NULL error or !=NULL new queued task
555: */
556: sched_task_t *
557: schedAIO(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg,
558: struct aiocb * __restrict acb, void *opt_data, size_t opt_dlen)
559: {
1.24.2.3 misho 560: #if SUP_ENABLE != KQ_SUPPORT
1.23 misho 561: sched_SetErr(ENOTSUP, "disabled kqueue support");
562: return NULL;
563: #else
1.11 misho 564: sched_task_t *task;
565: void *ptr;
566:
567: if (!root || !func || !acb || !opt_dlen)
568: return NULL;
569:
570: /* get new task */
1.13 misho 571: if (!(task = sched_useTask(root)))
1.11 misho 572: return NULL;
573:
1.24.2.4! misho 574: TASK_FUNC(task) = func;
1.11 misho 575: TASK_TYPE(task) = taskAIO;
576: TASK_ROOT(task) = root;
577:
578: TASK_ARG(task) = arg;
579: TASK_VAL(task) = (u_long) acb;
580:
581: TASK_DATA(task) = opt_data;
582: TASK_DATLEN(task) = opt_dlen;
583:
584: if (root->root_hooks.hook_add.aio)
585: ptr = root->root_hooks.hook_add.aio(task, NULL);
586: else
587: ptr = NULL;
588:
1.24.2.4! misho 589: if (!ptr)
! 590: insert_task_to(task, &root->root_aio);
! 591: else
1.13 misho 592: task = sched_unuseTask(task);
1.11 misho 593:
594: return task;
1.24.2.3 misho 595: #endif /* KQ_SUPPORT */
1.11 misho 596: }
597:
598: /*
599: * schedAIORead() - Add AIO read task to scheduler queue
600: *
601: * @root = root task
602: * @func = task execution function
603: * @arg = 1st func argument
604: * @fd = file descriptor
605: * @buffer = Buffer
606: * @buflen = Buffer length
607: * @offset = Offset from start of file, if =-1 from current position
608: * return: NULL error or !=NULL new queued task
609: */
1.16 misho 610: sched_task_t *
1.11 misho 611: schedAIORead(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd,
612: void *buffer, size_t buflen, off_t offset)
613: {
1.24.2.3 misho 614: #if SUP_ENABLE != KQ_SUPPORT
1.23 misho 615: sched_SetErr(ENOTSUP, "disabled kqueue support");
616: return NULL;
617: #else
1.11 misho 618: struct aiocb *acb;
619: off_t off;
620:
621: if (!root || !func || !buffer || !buflen)
622: return NULL;
623:
624: if (offset == (off_t) -1) {
625: off = lseek(fd, 0, SEEK_CUR);
626: if (off == -1) {
627: LOGERR;
628: return NULL;
629: }
630: } else
631: off = offset;
632:
633: if (!(acb = malloc(sizeof(struct aiocb)))) {
634: LOGERR;
635: return NULL;
636: } else
637: memset(acb, 0, sizeof(struct aiocb));
638:
639: acb->aio_fildes = fd;
640: acb->aio_nbytes = buflen;
641: acb->aio_buf = buffer;
642: acb->aio_offset = off;
643: acb->aio_sigevent.sigev_notify = SIGEV_KEVENT;
644: acb->aio_sigevent.sigev_notify_kqueue = root->root_kq;
645: acb->aio_sigevent.sigev_value.sival_ptr = acb;
646:
647: if (aio_read(acb)) {
648: LOGERR;
649: free(acb);
650: return NULL;
651: }
652:
653: return schedAIO(root, func, arg, acb, buffer, buflen);
1.24.2.3 misho 654: #endif /* KQ_SUPPORT */
1.11 misho 655: }
656:
657: /*
658: * schedAIOWrite() - Add AIO write task to scheduler queue
659: *
660: * @root = root task
661: * @func = task execution function
662: * @arg = 1st func argument
663: * @fd = file descriptor
664: * @buffer = Buffer
665: * @buflen = Buffer length
666: * @offset = Offset from start of file, if =-1 from current position
667: * return: NULL error or !=NULL new queued task
668: */
1.16 misho 669: sched_task_t *
1.11 misho 670: schedAIOWrite(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd,
671: void *buffer, size_t buflen, off_t offset)
672: {
1.24.2.3 misho 673: #if SUP_ENABLE != KQ_SUPPORT
1.23 misho 674: sched_SetErr(ENOTSUP, "disabled kqueue support");
675: return NULL;
676: #else
1.11 misho 677: struct aiocb *acb;
678: off_t off;
679:
680: if (!root || !func || !buffer || !buflen)
681: return NULL;
682:
683: if (offset == (off_t) -1) {
684: off = lseek(fd, 0, SEEK_CUR);
685: if (off == -1) {
686: LOGERR;
687: return NULL;
688: }
689: } else
690: off = offset;
691:
692: if (!(acb = malloc(sizeof(struct aiocb)))) {
693: LOGERR;
694: return NULL;
695: } else
696: memset(acb, 0, sizeof(struct aiocb));
697:
698: acb->aio_fildes = fd;
699: acb->aio_nbytes = buflen;
700: acb->aio_buf = buffer;
701: acb->aio_offset = off;
702: acb->aio_sigevent.sigev_notify = SIGEV_KEVENT;
703: acb->aio_sigevent.sigev_notify_kqueue = root->root_kq;
704: acb->aio_sigevent.sigev_value.sival_ptr = acb;
705:
706: if (aio_write(acb)) {
707: LOGERR;
708: free(acb);
709: return NULL;
710: }
711:
712: return schedAIO(root, func, arg, acb, buffer, buflen);
1.24.2.3 misho 713: #endif /* KQ_SUPPORT */
1.11 misho 714: }
715:
716: #ifdef EVFILT_LIO
717: /*
718: * schedLIO() - Add AIO bulk tasks to scheduler queue
719: *
720: * @root = root task
721: * @func = task execution function
722: * @arg = 1st func argument
723: * @acbs = AIO cb structure addresses
724: * @opt_data = Optional data
725: * @opt_dlen = Optional data length
726: * return: NULL error or !=NULL new queued task
727: */
728: sched_task_t *
729: schedLIO(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg,
730: struct aiocb ** __restrict acbs, void *opt_data, size_t opt_dlen)
731: {
1.24.2.3 misho 732: #if SUP_ENABLE != KQ_SUPPORT
1.23 misho 733: sched_SetErr(ENOTSUP, "disabled kqueue support");
734: return NULL;
735: #else
1.11 misho 736: sched_task_t *task;
737: void *ptr;
738:
739: if (!root || !func || !acbs || !opt_dlen)
740: return NULL;
741:
742: /* get new task */
1.13 misho 743: if (!(task = sched_useTask(root)))
1.11 misho 744: return NULL;
745:
1.24.2.4! misho 746: TASK_FUNC(task) = func;
1.11 misho 747: TASK_TYPE(task) = taskLIO;
748: TASK_ROOT(task) = root;
749:
750: TASK_ARG(task) = arg;
751: TASK_VAL(task) = (u_long) acbs;
752:
753: TASK_DATA(task) = opt_data;
754: TASK_DATLEN(task) = opt_dlen;
755:
756: if (root->root_hooks.hook_add.lio)
757: ptr = root->root_hooks.hook_add.lio(task, NULL);
758: else
759: ptr = NULL;
760:
1.24.2.4! misho 761: if (!ptr)
! 762: insert_task_to(task, &root->root_lio);
! 763: else
1.13 misho 764: task = sched_unuseTask(task);
1.11 misho 765:
766: return task;
1.24.2.3 misho 767: #endif /* KQ_SUPPORT */
1.11 misho 768: }
769:
770: /*
771: * schedLIORead() - Add list of AIO read tasks to scheduler queue
772: *
773: * @root = root task
774: * @func = task execution function
775: * @arg = 1st func argument
776: * @fd = file descriptor
777: * @bufs = Buffer's list
778: * @nbufs = Number of Buffers
779: * @offset = Offset from start of file, if =-1 from current position
780: * return: NULL error or !=NULL new queued task
781: */
782: sched_task_t *
783: schedLIORead(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd,
784: struct iovec *bufs, size_t nbufs, off_t offset)
785: {
1.24.2.3 misho 786: #if SUP_ENABLE != KQ_SUPPORT
1.23 misho 787: sched_SetErr(ENOTSUP, "disabled kqueue support");
788: return NULL;
789: #else
1.11 misho 790: struct sigevent sig;
791: struct aiocb **acb;
792: off_t off;
793: register int i;
794:
795: if (!root || !func || !bufs || !nbufs)
796: return NULL;
797:
798: if (offset == (off_t) -1) {
799: off = lseek(fd, 0, SEEK_CUR);
800: if (off == -1) {
801: LOGERR;
802: return NULL;
803: }
804: } else
805: off = offset;
806:
807: if (!(acb = calloc(sizeof(void*), nbufs))) {
808: LOGERR;
809: return NULL;
810: } else
811: memset(acb, 0, sizeof(void*) * nbufs);
812: for (i = 0; i < nbufs; off += bufs[i++].iov_len) {
813: acb[i] = malloc(sizeof(struct aiocb));
814: if (!acb[i]) {
815: LOGERR;
816: for (i = 0; i < nbufs; i++)
817: if (acb[i])
818: free(acb[i]);
819: free(acb);
820: return NULL;
821: } else
822: memset(acb[i], 0, sizeof(struct aiocb));
823: acb[i]->aio_fildes = fd;
824: acb[i]->aio_nbytes = bufs[i].iov_len;
825: acb[i]->aio_buf = bufs[i].iov_base;
826: acb[i]->aio_offset = off;
827: acb[i]->aio_lio_opcode = LIO_READ;
828: }
829: memset(&sig, 0, sizeof sig);
830: sig.sigev_notify = SIGEV_KEVENT;
831: sig.sigev_notify_kqueue = root->root_kq;
832: sig.sigev_value.sival_ptr = acb;
833:
834: if (lio_listio(LIO_NOWAIT, acb, nbufs, &sig)) {
835: LOGERR;
836: for (i = 0; i < nbufs; i++)
837: if (acb[i])
838: free(acb[i]);
839: free(acb);
840: return NULL;
841: }
842:
843: return schedLIO(root, func, arg, (void*) acb, bufs, nbufs);
1.24.2.3 misho 844: #endif /* KQ_SUPPORT */
1.11 misho 845: }
846:
847: /*
848: * schedLIOWrite() - Add list of AIO write tasks to scheduler queue
849: *
850: * @root = root task
851: * @func = task execution function
852: * @arg = 1st func argument
853: * @fd = file descriptor
854: * @bufs = Buffer's list
855: * @nbufs = Number of Buffers
856: * @offset = Offset from start of file, if =-1 from current position
857: * return: NULL error or !=NULL new queued task
858: */
1.16 misho 859: sched_task_t *
1.11 misho 860: schedLIOWrite(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd,
861: struct iovec *bufs, size_t nbufs, off_t offset)
862: {
1.24.2.3 misho 863: #if SUP_ENABLE != KQ_SUPPORT
1.23 misho 864: sched_SetErr(ENOTSUP, "disabled kqueue support");
865: return NULL;
866: #else
1.11 misho 867: struct sigevent sig;
868: struct aiocb **acb;
869: off_t off;
870: register int i;
871:
872: if (!root || !func || !bufs || !nbufs)
873: return NULL;
874:
875: if (offset == (off_t) -1) {
876: off = lseek(fd, 0, SEEK_CUR);
877: if (off == -1) {
878: LOGERR;
879: return NULL;
880: }
881: } else
882: off = offset;
883:
884: if (!(acb = calloc(sizeof(void*), nbufs))) {
885: LOGERR;
886: return NULL;
887: } else
888: memset(acb, 0, sizeof(void*) * nbufs);
889: for (i = 0; i < nbufs; off += bufs[i++].iov_len) {
890: acb[i] = malloc(sizeof(struct aiocb));
891: if (!acb[i]) {
892: LOGERR;
893: for (i = 0; i < nbufs; i++)
894: if (acb[i])
895: free(acb[i]);
896: free(acb);
897: return NULL;
898: } else
899: memset(acb[i], 0, sizeof(struct aiocb));
900: acb[i]->aio_fildes = fd;
901: acb[i]->aio_nbytes = bufs[i].iov_len;
902: acb[i]->aio_buf = bufs[i].iov_base;
903: acb[i]->aio_offset = off;
904: acb[i]->aio_lio_opcode = LIO_WRITE;
905: }
906: memset(&sig, 0, sizeof sig);
907: sig.sigev_notify = SIGEV_KEVENT;
908: sig.sigev_notify_kqueue = root->root_kq;
909: sig.sigev_value.sival_ptr = acb;
910:
911: if (lio_listio(LIO_NOWAIT, acb, nbufs, &sig)) {
912: LOGERR;
913: for (i = 0; i < nbufs; i++)
914: if (acb[i])
915: free(acb[i]);
916: free(acb);
917: return NULL;
918: }
919:
920: return schedLIO(root, func, arg, (void*) acb, bufs, nbufs);
1.24.2.3 misho 921: #endif /* KQ_SUPPORT */
1.11 misho 922: }
923: #endif /* EVFILT_LIO */
924: #endif /* AIO_SUPPORT */
925:
1.8 misho 926: /*
1.1 misho 927: * schedTimer() - Add TIMER task to scheduler queue
1.6 misho 928: *
1.1 misho 929: * @root = root task
930: * @func = task execution function
931: * @arg = 1st func argument
1.5 misho 932: * @ts = timeout argument structure
933: * @opt_data = Optional data
934: * @opt_dlen = Optional data length
1.1 misho 935: * return: NULL error or !=NULL new queued task
936: */
937: sched_task_t *
1.5 misho 938: schedTimer(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, struct timespec ts,
939: void *opt_data, size_t opt_dlen)
1.1 misho 940: {
1.9 misho 941: sched_task_t *task, *tmp, *t = NULL;
1.1 misho 942: void *ptr;
1.5 misho 943: struct timespec now;
1.1 misho 944:
945: if (!root || !func)
946: return NULL;
947:
948: /* get new task */
1.13 misho 949: if (!(task = sched_useTask(root)))
1.4 misho 950: return NULL;
1.1 misho 951:
1.24.2.4! misho 952: TASK_FUNC(task) = func;
1.5 misho 953: TASK_TYPE(task) = taskTIMER;
954: TASK_ROOT(task) = root;
1.1 misho 955:
956: TASK_ARG(task) = arg;
957:
1.5 misho 958: TASK_DATA(task) = opt_data;
959: TASK_DATLEN(task) = opt_dlen;
960:
1.1 misho 961: /* calculate timeval structure */
1.5 misho 962: clock_gettime(CLOCK_MONOTONIC, &now);
963: now.tv_sec += ts.tv_sec;
964: now.tv_nsec += ts.tv_nsec;
965: if (now.tv_nsec >= 1000000000L) {
1.1 misho 966: now.tv_sec++;
1.5 misho 967: now.tv_nsec -= 1000000000L;
968: } else if (now.tv_nsec < 0) {
1.1 misho 969: now.tv_sec--;
1.5 misho 970: now.tv_nsec += 1000000000L;
1.1 misho 971: }
1.5 misho 972: TASK_TS(task) = now;
1.1 misho 973:
974: if (root->root_hooks.hook_add.timer)
975: ptr = root->root_hooks.hook_add.timer(task, NULL);
976: else
977: ptr = NULL;
978:
979: if (!ptr) {
1.24.2.4! misho 980: SCHED_QLOCK(root, taskTIMER);
1.1 misho 981: #ifdef TIMER_WITHOUT_SORT
1.24.2.4! misho 982: TAILQ_INSERT_TAIL(&root->root_timer, task, task_node);
1.1 misho 983: #else
1.9 misho 984: TAILQ_FOREACH_SAFE(t, &root->root_timer, task_node, tmp)
1.5 misho 985: if (sched_timespeccmp(&TASK_TS(task), &TASK_TS(t), -) < 1)
1.1 misho 986: break;
987: if (!t)
1.24.2.4! misho 988: TAILQ_INSERT_TAIL(&root->root_timer, task, task_node);
1.1 misho 989: else
1.24.2.4! misho 990: TAILQ_INSERT_BEFORE(t, task, task_node);
1.5 misho 991: #endif
1.24.2.4! misho 992: SCHED_QUNLOCK(root, taskTIMER);
1.4 misho 993: } else
1.13 misho 994: task = sched_unuseTask(task);
1.1 misho 995:
996: return task;
997: }
998:
999: /*
1000: * schedEvent() - Add EVENT task to scheduler queue
1.6 misho 1001: *
1.1 misho 1002: * @root = root task
1003: * @func = task execution function
1004: * @arg = 1st func argument
1.2 misho 1005: * @val = additional func argument
1.5 misho 1006: * @opt_data = Optional data
1007: * @opt_dlen = Optional data length
1.1 misho 1008: * return: NULL error or !=NULL new queued task
1009: */
1010: sched_task_t *
1.5 misho 1011: schedEvent(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, u_long val,
1012: void *opt_data, size_t opt_dlen)
1.1 misho 1013: {
1014: sched_task_t *task;
1015: void *ptr;
1016:
1017: if (!root || !func)
1018: return NULL;
1019:
1020: /* get new task */
1.13 misho 1021: if (!(task = sched_useTask(root)))
1.4 misho 1022: return NULL;
1.1 misho 1023:
1.24.2.4! misho 1024: TASK_FUNC(task) = func;
1.5 misho 1025: TASK_TYPE(task) = taskEVENT;
1026: TASK_ROOT(task) = root;
1.1 misho 1027:
1028: TASK_ARG(task) = arg;
1.2 misho 1029: TASK_VAL(task) = val;
1.1 misho 1030:
1.5 misho 1031: TASK_DATA(task) = opt_data;
1032: TASK_DATLEN(task) = opt_dlen;
1033:
1.1 misho 1034: if (root->root_hooks.hook_add.event)
1035: ptr = root->root_hooks.hook_add.event(task, NULL);
1036: else
1037: ptr = NULL;
1038:
1.24.2.4! misho 1039: if (!ptr)
! 1040: insert_task_to(task, &root->root_event);
! 1041: else
1.13 misho 1042: task = sched_unuseTask(task);
1.1 misho 1043:
1044: return task;
1045: }
1046:
1047:
1048: /*
1.12 misho 1049: * schedTask() - Add regular task to scheduler queue
1.6 misho 1050: *
1.1 misho 1051: * @root = root task
1052: * @func = task execution function
1053: * @arg = 1st func argument
1.12 misho 1054: * @prio = regular task priority, 0 is hi priority for regular tasks
1.5 misho 1055: * @opt_data = Optional data
1056: * @opt_dlen = Optional data length
1.1 misho 1057: * return: NULL error or !=NULL new queued task
1058: */
1059: sched_task_t *
1.12 misho 1060: schedTask(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, u_long prio,
1.5 misho 1061: void *opt_data, size_t opt_dlen)
1.1 misho 1062: {
1.12 misho 1063: sched_task_t *task, *tmp, *t = NULL;
1.1 misho 1064: void *ptr;
1065:
1066: if (!root || !func)
1067: return NULL;
1068:
1069: /* get new task */
1.13 misho 1070: if (!(task = sched_useTask(root)))
1.4 misho 1071: return NULL;
1.1 misho 1072:
1.24.2.4! misho 1073: TASK_FUNC(task) = func;
1.12 misho 1074: TASK_TYPE(task) = taskTASK;
1.5 misho 1075: TASK_ROOT(task) = root;
1.1 misho 1076:
1077: TASK_ARG(task) = arg;
1.12 misho 1078: TASK_VAL(task) = prio;
1.1 misho 1079:
1.5 misho 1080: TASK_DATA(task) = opt_data;
1081: TASK_DATLEN(task) = opt_dlen;
1082:
1.12 misho 1083: if (root->root_hooks.hook_add.task)
1084: ptr = root->root_hooks.hook_add.task(task, NULL);
1.1 misho 1085: else
1086: ptr = NULL;
1087:
1.5 misho 1088: if (!ptr) {
1.24.2.4! misho 1089: SCHED_QLOCK(root, taskTASK);
1.12 misho 1090: TAILQ_FOREACH_SAFE(t, &root->root_task, task_node, tmp)
1091: if (TASK_VAL(task) < TASK_VAL(t))
1092: break;
1093: if (!t)
1.24.2.4! misho 1094: TAILQ_INSERT_TAIL(&root->root_task, task, task_node);
1.12 misho 1095: else
1.24.2.4! misho 1096: TAILQ_INSERT_BEFORE(t, task, task_node);
! 1097: SCHED_QUNLOCK(root, taskTASK);
1.5 misho 1098: } else
1.13 misho 1099: task = sched_unuseTask(task);
1.1 misho 1100:
1101: return task;
1102: }
1103:
1104: /*
1.10 misho 1105: * schedSuspend() - Add Suspended task to scheduler queue
1106: *
1107: * @root = root task
1108: * @func = task execution function
1109: * @arg = 1st func argument
1110: * @id = Trigger ID
1111: * @opt_data = Optional data
1112: * @opt_dlen = Optional data length
1113: * return: NULL error or !=NULL new queued task
1114: */
1115: sched_task_t *
1116: schedSuspend(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, u_long id,
1117: void *opt_data, size_t opt_dlen)
1118: {
1119: sched_task_t *task;
1120: void *ptr;
1121:
1122: if (!root || !func)
1123: return NULL;
1124:
1125: /* get new task */
1.13 misho 1126: if (!(task = sched_useTask(root)))
1.10 misho 1127: return NULL;
1128:
1.24.2.4! misho 1129: TASK_FUNC(task) = func;
1.10 misho 1130: TASK_TYPE(task) = taskSUSPEND;
1131: TASK_ROOT(task) = root;
1132:
1133: TASK_ARG(task) = arg;
1134: TASK_VAL(task) = id;
1135:
1136: TASK_DATA(task) = opt_data;
1137: TASK_DATLEN(task) = opt_dlen;
1138:
1139: if (root->root_hooks.hook_add.suspend)
1140: ptr = root->root_hooks.hook_add.suspend(task, NULL);
1141: else
1142: ptr = NULL;
1143:
1.24.2.4! misho 1144: if (!ptr)
! 1145: insert_task_to(task, &root->root_suspend);
! 1146: else
1.13 misho 1147: task = sched_unuseTask(task);
1.10 misho 1148:
1149: return task;
1150: }
1151:
1152: /*
1.1 misho 1153: * schedCallOnce() - Call once from scheduler
1.6 misho 1154: *
1.1 misho 1155: * @root = root task
1156: * @func = task execution function
1157: * @arg = 1st func argument
1.2 misho 1158: * @val = additional func argument
1.5 misho 1159: * @opt_data = Optional data
1160: * @opt_dlen = Optional data length
1.2 misho 1161: * return: return value from called func
1.1 misho 1162: */
1163: sched_task_t *
1.5 misho 1164: schedCallOnce(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, u_long val,
1165: void *opt_data, size_t opt_dlen)
1.1 misho 1166: {
1167: sched_task_t *task;
1.2 misho 1168: void *ret;
1.1 misho 1169:
1170: if (!root || !func)
1171: return NULL;
1172:
1173: /* get new task */
1.13 misho 1174: if (!(task = sched_useTask(root)))
1.4 misho 1175: return NULL;
1.1 misho 1176:
1.24.2.4! misho 1177: TASK_FUNC(task) = func;
1.5 misho 1178: TASK_TYPE(task) = taskEVENT;
1179: TASK_ROOT(task) = root;
1.1 misho 1180:
1181: TASK_ARG(task) = arg;
1.2 misho 1182: TASK_VAL(task) = val;
1.1 misho 1183:
1.5 misho 1184: TASK_DATA(task) = opt_data;
1185: TASK_DATLEN(task) = opt_dlen;
1186:
1.2 misho 1187: ret = schedCall(task);
1.1 misho 1188:
1.13 misho 1189: sched_unuseTask(task);
1.2 misho 1190: return ret;
1.1 misho 1191: }
1.13 misho 1192:
1193: /*
1194: * schedThread() - Add thread task to scheduler queue
1195: *
1196: * @root = root task
1197: * @func = task execution function
1198: * @arg = 1st func argument
1.15 misho 1199: * @ss = stack size
1.13 misho 1200: * @opt_data = Optional data
1201: * @opt_dlen = Optional data length
1202: * return: NULL error or !=NULL new queued task
1203: */
1204: sched_task_t *
1.21 misho 1205: schedThread(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg,
1.15 misho 1206: size_t ss, void *opt_data, size_t opt_dlen)
1.13 misho 1207: {
1208: #ifndef HAVE_LIBPTHREAD
1209: sched_SetErr(ENOTSUP, "Not supported thread tasks");
1210: return NULL;
1211: #endif
1212: sched_task_t *task;
1213: pthread_attr_t attr;
1.24.2.4! misho 1214: void *ptr;
1.13 misho 1215:
1216: if (!root || !func)
1217: return NULL;
1218:
1219: /* get new task */
1.24.2.4! misho 1220: if (!(task = sched_useTask(root)))
1.13 misho 1221: return NULL;
1222:
1.24.2.4! misho 1223: TASK_FUNC(task) = func;
1.13 misho 1224: TASK_TYPE(task) = taskTHREAD;
1225: TASK_ROOT(task) = root;
1226:
1227: TASK_ARG(task) = arg;
1228:
1229: TASK_DATA(task) = opt_data;
1230: TASK_DATLEN(task) = opt_dlen;
1231:
1232: pthread_attr_init(&attr);
1.24.2.1 misho 1233: pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1.15 misho 1234: if (ss && (errno = pthread_attr_setstacksize(&attr, ss))) {
1235: LOGERR;
1236: pthread_attr_destroy(&attr);
1237: return sched_unuseTask(task);
1238: }
1239: if ((errno = pthread_attr_getstacksize(&attr, &ss))) {
1240: LOGERR;
1241: pthread_attr_destroy(&attr);
1242: return sched_unuseTask(task);
1243: } else
1.21 misho 1244: TASK_FLAG(task) = ss;
1.24.2.2 misho 1245:
1.15 misho 1246: #ifdef SCHED_RR
1247: pthread_attr_setschedpolicy(&attr, SCHED_RR);
1248: #else
1249: pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
1250: #endif
1.21 misho 1251:
1.13 misho 1252: if (root->root_hooks.hook_add.thread)
1.24.2.4! misho 1253: ptr = root->root_hooks.hook_add.thread(task, &attr);
! 1254: else
! 1255: ptr = NULL;
! 1256:
! 1257: if (!ptr)
! 1258: insert_task_to(task, &root->root_thread);
! 1259: else
! 1260: task = sched_unuseTask(task);
! 1261:
1.13 misho 1262: pthread_attr_destroy(&attr);
1263: return task;
1264: }
1265:
1.17 misho 1266: /*
1267: * schedRTC() - Add RTC task to scheduler queue
1268: *
1269: * @root = root task
1270: * @func = task execution function
1271: * @arg = 1st func argument
1272: * @ts = timeout argument structure, minimum alarm timer resolution is 1msec!
1273: * @opt_data = Optional RTC ID
1.18 misho 1274: * @opt_dlen = Optional data length
1.17 misho 1275: * return: NULL error or !=NULL new queued task
1276: */
1277: sched_task_t *
1278: schedRTC(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, struct timespec ts,
1279: void *opt_data, size_t opt_dlen)
1280: {
1.24 misho 1281: #if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME) && defined(HAVE_TIMER_DELETE)
1.17 misho 1282: sched_task_t *task;
1283: void *ptr;
1284:
1285: if (!root || !func)
1286: return NULL;
1287:
1288: /* get new task */
1289: if (!(task = sched_useTask(root)))
1290: return NULL;
1291:
1.24.2.4! misho 1292: TASK_FUNC(task) = func;
1.17 misho 1293: TASK_TYPE(task) = taskRTC;
1294: TASK_ROOT(task) = root;
1295:
1296: TASK_ARG(task) = arg;
1297: TASK_TS(task) = ts;
1298:
1299: TASK_DATA(task) = opt_data;
1300: TASK_DATLEN(task) = opt_dlen;
1301:
1302: if (root->root_hooks.hook_add.rtc)
1303: ptr = root->root_hooks.hook_add.rtc(task, NULL);
1304: else
1305: ptr = NULL;
1306:
1.24.2.4! misho 1307: if (!ptr)
! 1308: insert_task_to(task, &root->root_rtc);
! 1309: else
1.17 misho 1310: task = sched_unuseTask(task);
1311:
1312: return task;
1313: #else
1314: sched_SetErr(ENOTSUP, "Not supported realtime clock extensions");
1315: return NULL;
1316: #endif
1317: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>