Annotation of libaitsched/src/aitsched.c, revision 1.32.2.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 $
1.32.2.1! misho 6: * $Id: aitsched.c,v 1.32 2023/07/27 20:51: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:
1.30 misho 15: Copyright 2004 - 2023
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: #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
1.18 misho 59: int
1.1 misho 60: sched_GetErrno()
61: {
62: return sched_Errno;
63: }
64:
65: // sched_GetError() Get error text of last operation
1.18 misho 66: const char *
1.1 misho 67: sched_GetError()
68: {
69: return sched_Error;
70: }
71:
72: // sched_SetErr() Set error to variables for internal use!!!
1.18 misho 73: void
1.1 misho 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:
1.26 misho 85:
86: /* string support functions directly imported from OpenBSD */
87:
88: #ifndef HAVE_STRLCAT
89: /*
90: * Appends src to string dst of size siz (unlike strncat, siz is the
91: * full size of dst, not space left). At most siz-1 characters
92: * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
93: * Returns strlen(src) + MIN(siz, strlen(initial dst)).
94: * If retval >= siz, truncation occurred.
95: */
96: size_t
97: strlcat(char * __restrict dst, const char * __restrict src, size_t siz)
98: {
99: char *d = dst;
100: const char *s = src;
101: size_t n = siz;
102: size_t dlen;
103:
104: /* Find the end of dst and adjust bytes left but don't go past end */
105: while (n-- != 0 && *d != '\0')
106: d++;
107: dlen = d - dst;
108: n = siz - dlen;
109:
110: if (n == 0)
111: return(dlen + strlen(s));
112: while (*s != '\0') {
113: if (n != 1) {
114: *d++ = *s;
115: n--;
116: }
117: s++;
118: }
119: *d = '\0';
120:
121: return(dlen + (s - src)); /* count does not include NUL */
122: }
123: #endif
124: #ifndef HAVE_STRLCPY
125: /*
126: * Copy src to string dst of size siz. At most siz-1 characters
127: * will be copied. Always NUL terminates (unless siz == 0).
128: * Returns strlen(src); if retval >= siz, truncation occurred.
129: */
130: size_t
131: strlcpy(char * __restrict dst, const char * __restrict src, size_t siz)
132: {
133: char *d = dst;
134: const char *s = src;
135: size_t n = siz;
136:
137: /* Copy as many bytes as will fit */
138: if (n != 0) {
139: while (--n != 0) {
140: if ((*d++ = *s++) == '\0')
141: break;
142: }
143: }
144:
145: /* Not enough room in dst, add NUL and traverse rest of src */
146: if (n == 0) {
147: if (siz != 0)
148: *d = '\0'; /* NUL-terminate dst */
149: while (*s++)
150: ;
151: }
152:
153: return(s - src - 1); /* count does not include NUL */
154: }
155: #endif
156:
157:
1.1 misho 158: /* Init and prepare scheduler functions */
159:
160: /*
1.2 misho 161: * schedRegisterHooks() - Register IO handles and bind tasks to it
1.6 misho 162: *
1.2 misho 163: * @root = root task
164: * return: -1 error or 0 ok
165: */
166: int
167: schedRegisterHooks(sched_root_task_t * __restrict root)
168: {
1.7 misho 169: assert(root);
1.2 misho 170:
171: if (root->root_hooks.hook_root.fini)
172: root->root_hooks.hook_root.fini(root, NULL);
173: memset(&root->root_hooks, 0, sizeof root->root_hooks);
174:
175: root->root_hooks.hook_add.read = sched_hook_read;
176: root->root_hooks.hook_add.write = sched_hook_write;
1.25 misho 177: #if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME) && defined(HAVE_TIMER_DELETE)
1.19 misho 178: root->root_hooks.hook_add.rtc = sched_hook_rtc;
179: #endif
1.26 misho 180: #if SUP_ENABLE == KQ_SUPPORT
181: root->root_hooks.hook_add.alarm = sched_hook_alarm;
1.10 misho 182: root->root_hooks.hook_add.node = sched_hook_node;
183: root->root_hooks.hook_add.proc = sched_hook_proc;
184: #ifdef EVFILT_USER
185: root->root_hooks.hook_add.user = sched_hook_user;
186: #endif
1.26 misho 187: #endif /* KQ_SUPPORT */
1.15 misho 188: #ifdef HAVE_LIBPTHREAD
189: root->root_hooks.hook_add.thread = sched_hook_thread;
190: #endif
1.31 misho 191: root->root_hooks.hook_add.signal = sched_hook_signal;
1.2 misho 192:
193: root->root_hooks.hook_exec.cancel = sched_hook_cancel;
194: root->root_hooks.hook_exec.fetch = sched_hook_fetch;
1.3 misho 195: root->root_hooks.hook_exec.exception = sched_hook_exception;
1.2 misho 196:
197: root->root_hooks.hook_root.init = sched_hook_init;
198: root->root_hooks.hook_root.fini = sched_hook_fini;
199: return 0;
200: }
201:
202: /*
1.1 misho 203: * schedInit() - Init scheduler
1.6 misho 204: *
1.1 misho 205: * @data = optional data if !=NULL
206: * @datlen = data len if data is set
207: * return: allocated root task if ok or NULL error
208: */
209: sched_root_task_t *
210: schedInit(void ** __restrict data, size_t datlen)
211: {
212: sched_root_task_t *root = NULL;
213: int (*func)(sched_root_task_t *);
1.32.2.1! misho 214: #if SUP_ENABLE == KQ_SUPPORT
1.32 misho 215: sigset_t ss;
1.32.2.1! misho 216: #endif
1.5 misho 217: #ifdef HAVE_LIBPTHREAD
218: register int i;
219: #endif
1.1 misho 220:
1.29 misho 221: root = e_malloc(sizeof(sched_root_task_t));
1.2 misho 222: if (!root) {
223: LOGERR;
224: } else {
1.1 misho 225: memset(root, 0, sizeof(sched_root_task_t));
1.5 misho 226:
1.13 misho 227: /* set default maximum regular task hit misses */
228: root->root_miss = MAX_TASK_MISS;
229:
1.5 misho 230: /* INFINIT polling period by default */
231: sched_timespecinf(&root->root_poll);
232:
233: #ifdef HAVE_LIBPTHREAD
1.31 misho 234: if (pthread_mutex_init(&root->root_sigmtx, NULL)) {
235: LOGERR;
236: e_free(root);
237: return NULL;
238: }
239:
1.5 misho 240: for (i = 0; i < taskMAX; i++)
1.17 misho 241: if ((errno = pthread_mutex_init(&root->root_mtx[i], NULL))) {
1.5 misho 242: LOGERR;
243: while (i)
244: pthread_mutex_destroy(&root->root_mtx[--i]);
1.29 misho 245: e_free(root);
1.5 misho 246: return NULL;
247: }
248:
249: for (i = 0; i < taskMAX; i++)
250: pthread_mutex_lock(&root->root_mtx[i]);
251: #endif
252:
1.2 misho 253: TAILQ_INIT(&root->root_read);
254: TAILQ_INIT(&root->root_write);
1.10 misho 255: TAILQ_INIT(&root->root_timer);
1.9 misho 256: TAILQ_INIT(&root->root_alarm);
1.19 misho 257: TAILQ_INIT(&root->root_rtc);
1.10 misho 258: TAILQ_INIT(&root->root_node);
259: TAILQ_INIT(&root->root_proc);
1.12 misho 260: TAILQ_INIT(&root->root_signal);
261: TAILQ_INIT(&root->root_aio);
262: TAILQ_INIT(&root->root_lio);
1.10 misho 263: TAILQ_INIT(&root->root_user);
1.2 misho 264: TAILQ_INIT(&root->root_event);
1.13 misho 265: TAILQ_INIT(&root->root_task);
1.11 misho 266: TAILQ_INIT(&root->root_suspend);
1.2 misho 267: TAILQ_INIT(&root->root_ready);
268: TAILQ_INIT(&root->root_unuse);
1.15 misho 269: TAILQ_INIT(&root->root_thread);
1.1 misho 270:
1.5 misho 271: #ifdef HAVE_LIBPTHREAD
272: for (i = 0; i < taskMAX; i++)
273: pthread_mutex_unlock(&root->root_mtx[i]);
1.32 misho 274:
1.32.2.1! misho 275: #if SUP_ENABLE == KQ_SUPPORT
1.32 misho 276: sigfillset(&ss);
277: pthread_sigmask(SIG_BLOCK, &ss, &root->root_oldset);
278: #else
1.32.2.1! misho 279: pthread_sigmask(SIG_BLOCK, NULL, &root->root_oldset);
! 280: #endif
! 281: #else
! 282: #if SUP_ENABLE == KQ_SUPPORT
1.32 misho 283: sigprocmask(SIG_BLOCK, &ss, &root->root_oldset);
1.32.2.1! misho 284: #else
! 285: sigprocmask(SIG_BLOCK, NULL, &root->root_oldset);
! 286: #endif
1.5 misho 287: #endif
288:
1.1 misho 289: if (data && *data) {
290: if (datlen) {
291: root->root_data.iov_base = *data;
292: root->root_data.iov_len = datlen;
1.3 misho 293: } else { /* if datlen == 0, switch to callbacks init mode */
294: /* little hack :) for correct initialization of scheduler */
1.2 misho 295: func = (int(*)(sched_root_task_t*)) data;
1.1 misho 296: func(root);
297: }
298: }
1.2 misho 299:
300: if (root->root_hooks.hook_root.init)
301: root->root_hooks.hook_root.init(root, NULL);
1.1 misho 302: }
303:
304: return root;
305: }
306:
307: /*
308: * schedEnd() - End scheduler & free all resources
1.6 misho 309: *
1.1 misho 310: * @root = root task
311: * return: -1 error or 0 ok
312: */
313: int
1.2 misho 314: schedEnd(sched_root_task_t ** __restrict root)
1.1 misho 315: {
1.7 misho 316: sched_task_t *task, *tmp;
1.5 misho 317: #ifdef HAVE_LIBPTHREAD
318: register int i;
319: #endif
1.1 misho 320:
1.2 misho 321: if (!root || !*root)
1.1 misho 322: return -1;
323:
1.26 misho 324: #if 0
325: TAILQ_FOREACH_SAFE(task, &(*root)->root_read, task_node, tmp)
326: printf("read=%p\n", task);
327: TAILQ_FOREACH_SAFE(task, &(*root)->root_write, task_node, tmp)
328: printf("write=%p\n", task);
329: TAILQ_FOREACH_SAFE(task, &(*root)->root_timer, task_node, tmp)
330: printf("timer=%p\n", task);
331: TAILQ_FOREACH_SAFE(task, &(*root)->root_alarm, task_node, tmp)
332: printf("alarm=%p\n", task);
333: TAILQ_FOREACH_SAFE(task, &(*root)->root_rtc, task_node, tmp)
334: printf("rtc=%p\n", task);
335: TAILQ_FOREACH_SAFE(task, &(*root)->root_node, task_node, tmp)
336: printf("node=%p\n", task);
337: TAILQ_FOREACH_SAFE(task, &(*root)->root_proc, task_node, tmp)
338: printf("proc=%p\n", task);
339: TAILQ_FOREACH_SAFE(task, &(*root)->root_signal, task_node, tmp)
340: printf("signal=%p\n", task);
341: TAILQ_FOREACH_SAFE(task, &(*root)->root_aio, task_node, tmp)
342: printf("aio=%p\n", task);
343: TAILQ_FOREACH_SAFE(task, &(*root)->root_lio, task_node, tmp)
344: printf("lio=%p\n", task);
345: TAILQ_FOREACH_SAFE(task, &(*root)->root_user, task_node, tmp)
346: printf("user=%p\n", task);
347: TAILQ_FOREACH_SAFE(task, &(*root)->root_event, task_node, tmp)
348: printf("event=%p\n", task);
349: TAILQ_FOREACH_SAFE(task, &(*root)->root_suspend, task_node, tmp)
350: printf("suspend=%p\n", task);
351: TAILQ_FOREACH_SAFE(task, &(*root)->root_ready, task_node, tmp)
352: printf("ready=%p\n", task);
353: TAILQ_FOREACH_SAFE(task, &(*root)->root_thread, task_node, tmp)
354: printf("thread=%p\n", task);
355: TAILQ_FOREACH_SAFE(task, &(*root)->root_task, task_node, tmp)
356: printf("task=%p\n", task);
357: TAILQ_FOREACH_SAFE(task, &(*root)->root_unuse, task_node, tmp)
358: printf("unuse=%p\n", task);
359: fflush(stdout);
360: #endif
361:
1.10 misho 362: TAILQ_FOREACH_SAFE(task, &(*root)->root_read, task_node, tmp)
363: schedCancel(task);
364: TAILQ_FOREACH_SAFE(task, &(*root)->root_write, task_node, tmp)
1.1 misho 365: schedCancel(task);
1.10 misho 366: TAILQ_FOREACH_SAFE(task, &(*root)->root_timer, task_node, tmp)
367: schedCancel(task);
368: TAILQ_FOREACH_SAFE(task, &(*root)->root_alarm, task_node, tmp)
369: schedCancel(task);
1.19 misho 370: TAILQ_FOREACH_SAFE(task, &(*root)->root_rtc, task_node, tmp)
371: schedCancel(task);
1.10 misho 372: TAILQ_FOREACH_SAFE(task, &(*root)->root_node, task_node, tmp)
373: schedCancel(task);
374: TAILQ_FOREACH_SAFE(task, &(*root)->root_proc, task_node, tmp)
1.1 misho 375: schedCancel(task);
1.12 misho 376: TAILQ_FOREACH_SAFE(task, &(*root)->root_signal, task_node, tmp)
377: schedCancel(task);
378: TAILQ_FOREACH_SAFE(task, &(*root)->root_aio, task_node, tmp)
379: schedCancel(task);
380: TAILQ_FOREACH_SAFE(task, &(*root)->root_lio, task_node, tmp)
381: schedCancel(task);
1.10 misho 382: TAILQ_FOREACH_SAFE(task, &(*root)->root_user, task_node, tmp)
1.9 misho 383: schedCancel(task);
1.10 misho 384: TAILQ_FOREACH_SAFE(task, &(*root)->root_event, task_node, tmp)
1.1 misho 385: schedCancel(task);
1.11 misho 386: TAILQ_FOREACH_SAFE(task, &(*root)->root_suspend, task_node, tmp)
387: schedCancel(task);
1.10 misho 388: TAILQ_FOREACH_SAFE(task, &(*root)->root_ready, task_node, tmp)
1.1 misho 389: schedCancel(task);
1.15 misho 390: TAILQ_FOREACH_SAFE(task, &(*root)->root_thread, task_node, tmp)
391: schedCancel(task);
1.16 misho 392: TAILQ_FOREACH_SAFE(task, &(*root)->root_task, task_node, tmp)
393: schedCancel(task);
1.1 misho 394:
1.26 misho 395: SCHED_QLOCK((*root), taskUNUSE);
1.10 misho 396: TAILQ_FOREACH_SAFE(task, &(*root)->root_unuse, task_node, tmp) {
1.2 misho 397: TAILQ_REMOVE(&(*root)->root_unuse, task, task_node);
1.29 misho 398: e_free(task);
1.1 misho 399: }
1.26 misho 400: SCHED_QUNLOCK((*root), taskUNUSE);
1.1 misho 401:
1.2 misho 402: if ((*root)->root_hooks.hook_root.fini)
403: (*root)->root_hooks.hook_root.fini(*root, NULL);
1.1 misho 404:
1.5 misho 405: #ifdef HAVE_LIBPTHREAD
1.26 misho 406: for (i = 0; i < taskMAX; i++) {
1.28 misho 407: SCHED_QTRYLOCK(*root, i);
1.26 misho 408: SCHED_QUNLOCK(*root, i);
1.5 misho 409: pthread_mutex_destroy(&(*root)->root_mtx[i]);
1.26 misho 410: }
1.31 misho 411:
412: if ((*root)->root_sigthr) {
413: pthread_cancel((*root)->root_sigthr);
414: #ifdef __linux__
415: (*root)->root_sigthr = 0L;
416: #else
417: (*root)->root_sigthr = NULL;
418: #endif
419: pthread_sigmask(SIG_SETMASK, &(*root)->root_oldset, NULL);
420: pthread_mutex_unlock(&(*root)->root_sigmtx);
421: }
422: pthread_mutex_destroy(&(*root)->root_sigmtx);
1.32 misho 423: #else
424: sigprocmask(SIG_SETMASK, &(*root)->root_oldset, NULL);
1.5 misho 425: #endif
426:
1.29 misho 427: e_free(*root);
1.2 misho 428: *root = NULL;
1.1 misho 429: return 0;
430: }
431:
432: /*
433: * schedCall() - Call task execution function
1.6 misho 434: *
1.1 misho 435: * @task = current task
436: * return: !=NULL error or =NULL ok
437: */
1.18 misho 438: void *
1.1 misho 439: schedCall(sched_task_t * __restrict task)
440: {
1.4 misho 441: void *ptr = (void*) -1;
442:
1.1 misho 443: if (!task)
1.4 misho 444: return ptr;
445:
446: if (!TASK_ISLOCKED(task))
447: TASK_LOCK(task);
1.1 misho 448:
1.4 misho 449: ptr = task->task_func(task);
450:
451: TASK_UNLOCK(task);
452: return ptr;
1.1 misho 453: }
454:
455: /*
456: * schedFetch() - Fetch ready task
1.6 misho 457: *
1.1 misho 458: * @root = root task
459: * return: =NULL error or !=NULL ready task
460: */
1.18 misho 461: void *
1.1 misho 462: schedFetch(sched_root_task_t * __restrict root)
463: {
464: void *ptr;
465:
466: if (!root)
467: return NULL;
468:
469: if (root->root_hooks.hook_exec.fetch)
470: ptr = root->root_hooks.hook_exec.fetch(root, NULL);
471: else
472: ptr = NULL;
473:
474: return ptr;
475: }
476:
477: /*
1.10 misho 478: * schedTrigger() - Triggering USER task
479: *
480: * @task = task
481: * return: -1 error or 0 ok
482: */
483: int
484: schedTrigger(sched_task_t * __restrict task)
485: {
1.26 misho 486: #if SUP_ENABLE != KQ_SUPPORT
1.24 misho 487: sched_SetErr(ENOTSUP, "disabled kqueue support");
488: return -1;
489: #else
1.10 misho 490: #ifndef EVFILT_USER
491: sched_SetErr(ENOTSUP, "Not supported kevent() filter");
492: return -1;
493: #else
494: struct kevent chg[1];
495: struct timespec timeout = { 0, 0 };
496:
497: if (!task || !TASK_ROOT(task))
498: return -1;
499:
500: #ifdef __NetBSD__
501: EV_SET(chg, TASK_VAL(task), EVFILT_USER, 0, NOTE_TRIGGER, 0, (intptr_t) TASK_VAL(task));
502: #else
503: EV_SET(chg, TASK_VAL(task), EVFILT_USER, 0, NOTE_TRIGGER, 0, (void*) TASK_VAL(task));
504: #endif
505: if (kevent(TASK_ROOT(task)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
506: LOGERR;
507: return -1;
508: }
509:
510: return 0;
511: #endif
1.26 misho 512: #endif /* KQ_SUPPORT */
1.10 misho 513: }
514:
515: /*
1.20 misho 516: * schedQuery() - Query task in scheduler
517: *
518: * @task = task
519: * return: -1 error, 0 found and 1 not found
520: */
521: int
522: schedQuery(sched_task_t * __restrict task)
523: {
524: sched_queue_t *queue;
525: sched_task_t *t;
526:
527: if (!task || !TASK_ROOT(task))
528: return -1; /* error */
529:
530: switch (TASK_TYPE(task)) {
531: case taskREAD:
532: queue = &TASK_ROOT(task)->root_read;
533: break;
534: case taskWRITE:
535: queue = &TASK_ROOT(task)->root_write;
536: break;
537: case taskTIMER:
538: queue = &TASK_ROOT(task)->root_timer;
539: break;
540: case taskALARM:
541: queue = &TASK_ROOT(task)->root_alarm;
542: break;
543: case taskRTC:
544: queue = &TASK_ROOT(task)->root_rtc;
545: break;
546: case taskNODE:
547: queue = &TASK_ROOT(task)->root_node;
548: break;
549: case taskPROC:
550: queue = &TASK_ROOT(task)->root_proc;
551: break;
552: case taskSIGNAL:
553: queue = &TASK_ROOT(task)->root_signal;
554: break;
555: case taskAIO:
556: queue = &TASK_ROOT(task)->root_aio;
557: break;
558: case taskLIO:
559: queue = &TASK_ROOT(task)->root_lio;
560: break;
561: case taskUSER:
562: queue = &TASK_ROOT(task)->root_user;
563: break;
564: case taskEVENT:
565: queue = &TASK_ROOT(task)->root_event;
566: break;
567: case taskTASK:
568: queue = &TASK_ROOT(task)->root_task;
569: break;
570: case taskSUSPEND:
571: queue = &TASK_ROOT(task)->root_suspend;
572: break;
573: case taskREADY:
574: queue = &TASK_ROOT(task)->root_ready;
575: break;
576: case taskTHREAD:
577: queue = &TASK_ROOT(task)->root_thread;
578: break;
579: default:
580: return 1; /* not in queue */
581: }
582: if (queue)
583: TAILQ_FOREACH(t, queue, task_node)
584: if (TASK_ID(t) == TASK_ID(task))
585: return 0; /* found */
586:
587: return 1; /* not in queue */
588: }
589:
590: /*
591: * schedQueryby() - Query task in scheduler by criteria
592: *
593: * @root = root task
594: * @type = query from queue type, if =taskMAX query same task from all queues
595: * @criteria = find task by criteria
596: * [ CRITERIA_ANY|CRITERIA_CALL|CRITERIA_ARG|CRITERIA_FD|CRITERIA_VAL|
1.23 misho 597: * CRITERIA_ID|CRITERIA_TS|CRITERIA_DATA|CRITERIA_DATLEN ]
1.20 misho 598: * @param = search parameter
1.30 misho 599: * return: NULL not found or !=NULL task
1.20 misho 600: */
1.30 misho 601: sched_task_t *
1.20 misho 602: schedQueryby(sched_root_task_t * __restrict root, sched_task_type_t type,
603: u_char criteria, void *param)
604: {
1.21 misho 605: sched_task_t *task;
1.20 misho 606: sched_queue_t *queue;
607:
608: if (!root)
1.30 misho 609: return NULL;
1.20 misho 610: /* if type == taskMAX check in all queues */
611: if (type == taskMAX) {
1.30 misho 612: if ((task = schedQueryby(root, taskREAD, criteria, param)))
613: return task;
614: if ((task = schedQueryby(root, taskWRITE, criteria, param)))
615: return task;
616: if ((task = schedQueryby(root, taskTIMER, criteria, param)))
617: return task;
618: if ((task = schedQueryby(root, taskALARM, criteria, param)))
619: return task;
620: if ((task = schedQueryby(root, taskRTC, criteria, param)))
621: return task;
622: if ((task = schedQueryby(root, taskNODE, criteria, param)))
623: return task;
624: if ((task = schedQueryby(root, taskPROC, criteria, param)))
625: return task;
626: if ((task = schedQueryby(root, taskSIGNAL, criteria, param)))
627: return task;
628: if ((task = schedQueryby(root, taskAIO, criteria, param)))
629: return task;
630: if ((task = schedQueryby(root, taskLIO, criteria, param)))
631: return task;
632: if ((task = schedQueryby(root, taskUSER, criteria, param)))
633: return task;
634: if ((task = schedQueryby(root, taskEVENT, criteria, param)))
635: return task;
636: if ((task = schedQueryby(root, taskTASK, criteria, param)))
637: return task;
638: if ((task = schedQueryby(root, taskSUSPEND, criteria, param)))
639: return task;
640: if ((task = schedQueryby(root, taskREADY, criteria, param)))
641: return task;
642: if ((task = schedQueryby(root, taskTHREAD, criteria, param)))
643: return task;
644: return NULL; /* not found */
1.20 misho 645: }
646: /* choosen queue */
647: switch (type) {
648: case taskREAD:
649: queue = &root->root_read;
650: break;
651: case taskWRITE:
652: queue = &root->root_write;
653: break;
654: case taskTIMER:
655: queue = &root->root_timer;
656: break;
657: case taskALARM:
658: queue = &root->root_alarm;
659: break;
660: case taskRTC:
661: queue = &root->root_rtc;
662: break;
663: case taskNODE:
664: queue = &root->root_node;
665: break;
666: case taskPROC:
667: queue = &root->root_proc;
668: break;
669: case taskSIGNAL:
670: queue = &root->root_signal;
671: break;
672: case taskAIO:
673: queue = &root->root_aio;
674: break;
675: case taskLIO:
676: queue = &root->root_lio;
677: break;
678: case taskUSER:
679: queue = &root->root_user;
680: break;
681: case taskEVENT:
682: queue = &root->root_event;
683: break;
684: case taskTASK:
685: queue = &root->root_task;
686: break;
687: case taskSUSPEND:
688: queue = &root->root_suspend;
689: break;
690: case taskREADY:
691: queue = &root->root_ready;
692: break;
693: case taskTHREAD:
694: queue = &root->root_thread;
695: break;
696: default:
1.30 misho 697: return NULL; /* not found */
1.20 misho 698: }
699:
700: TAILQ_FOREACH(task, queue, task_node) {
701: switch (criteria) {
702: case CRITERIA_ANY:
1.30 misho 703: return task; /* found */
1.20 misho 704: case CRITERIA_CALL:
705: if (TASK_FUNC(task) == (sched_task_func_t) param)
1.30 misho 706: return task; /* found */
1.20 misho 707: break;
708: case CRITERIA_ARG:
709: if (TASK_ARG(task) == param)
1.30 misho 710: return task; /* found */
1.20 misho 711: break;
712: case CRITERIA_FD:
713: if (TASK_FD(task) == (intptr_t) param)
1.30 misho 714: return task; /* found */
1.20 misho 715: break;
716: case CRITERIA_ID:
717: case CRITERIA_VAL:
718: if (TASK_VAL(task) == (u_long) param)
1.30 misho 719: return task; /* found */
1.20 misho 720: break;
721: case CRITERIA_TS:
722: if (!sched_timespeccmp(&TASK_TS(task),
723: (struct timespec*) param, -))
1.30 misho 724: return task; /* found */
1.20 misho 725: break;
726: case CRITERIA_DATA:
727: if (TASK_DATA(task) == param)
1.30 misho 728: return task; /* found */
1.20 misho 729: break;
1.23 misho 730: case CRITERIA_DATLEN:
731: if (TASK_DATLEN(task) == (size_t) param)
1.30 misho 732: return task; /* found */
1.23 misho 733: break;
1.20 misho 734: default:
735: sched_SetErr(EINVAL, "Invalid parameter criteria %d",
736: criteria);
1.30 misho 737: return NULL; /* not found */
1.20 misho 738: }
739: }
740:
1.30 misho 741: return NULL; /* not found */
1.20 misho 742: }
743:
744: /*
1.1 misho 745: * schedCancel() - Cancel task from scheduler
1.6 misho 746: *
1.1 misho 747: * @task = task
748: * return: -1 error or 0 ok
749: */
750: int
751: schedCancel(sched_task_t * __restrict task)
752: {
753: sched_queue_t *queue;
754:
1.5 misho 755: if (!task || !TASK_ROOT(task))
1.1 misho 756: return -1;
757:
1.5 misho 758: if (TASK_ROOT(task)->root_hooks.hook_exec.cancel)
759: if (TASK_ROOT(task)->root_hooks.hook_exec.cancel(task, NULL))
1.1 misho 760: return -1;
761:
1.5 misho 762: switch (TASK_TYPE(task)) {
1.1 misho 763: case taskREAD:
1.5 misho 764: queue = &TASK_ROOT(task)->root_read;
1.1 misho 765: break;
766: case taskWRITE:
1.5 misho 767: queue = &TASK_ROOT(task)->root_write;
1.1 misho 768: break;
1.10 misho 769: case taskTIMER:
770: queue = &TASK_ROOT(task)->root_timer;
771: break;
1.9 misho 772: case taskALARM:
773: queue = &TASK_ROOT(task)->root_alarm;
774: break;
1.19 misho 775: case taskRTC:
776: queue = &TASK_ROOT(task)->root_rtc;
777: break;
1.10 misho 778: case taskNODE:
779: queue = &TASK_ROOT(task)->root_node;
780: break;
781: case taskPROC:
782: queue = &TASK_ROOT(task)->root_proc;
783: break;
1.12 misho 784: case taskSIGNAL:
785: queue = &TASK_ROOT(task)->root_signal;
786: break;
787: case taskAIO:
788: queue = &TASK_ROOT(task)->root_aio;
789: break;
790: case taskLIO:
791: queue = &TASK_ROOT(task)->root_lio;
792: break;
1.10 misho 793: case taskUSER:
794: queue = &TASK_ROOT(task)->root_user;
795: break;
1.1 misho 796: case taskEVENT:
1.5 misho 797: queue = &TASK_ROOT(task)->root_event;
798: break;
1.13 misho 799: case taskTASK:
800: queue = &TASK_ROOT(task)->root_task;
1.1 misho 801: break;
1.11 misho 802: case taskSUSPEND:
803: queue = &TASK_ROOT(task)->root_suspend;
804: break;
1.1 misho 805: case taskREADY:
1.5 misho 806: queue = &TASK_ROOT(task)->root_ready;
1.1 misho 807: break;
1.15 misho 808: case taskTHREAD:
809: queue = &TASK_ROOT(task)->root_thread;
810: break;
1.1 misho 811: default:
812: queue = NULL;
813: }
1.26 misho 814: if (queue)
815: remove_task_from(task, queue);
1.5 misho 816: if (TASK_TYPE(task) != taskUNUSE)
1.15 misho 817: sched_unuseTask(task);
1.1 misho 818:
819: return 0;
820: }
821:
822: /*
823: * schedCancelby() - Cancel task from scheduler by criteria
1.6 misho 824: *
1.1 misho 825: * @root = root task
1.5 misho 826: * @type = cancel from queue type, if =taskMAX cancel same task from all queues
1.10 misho 827: * @criteria = find task by criteria
1.20 misho 828: * [ CRITERIA_ANY|CRITERIA_CALL|CRITERIA_ARG|CRITERIA_FD|CRITERIA_VAL|
1.23 misho 829: * CRITERIA_ID|CRITERIA_TS|CRITERIA_DATA|CRITERIA_DATLEN ]
1.1 misho 830: * @param = search parameter
831: * @hook = custom cleanup hook function, may be NULL
1.3 misho 832: * return: -1 error, -2 error in sub-stage cancel execution, -3 error from custom hook or 0 ok
1.1 misho 833: */
834: int
1.5 misho 835: schedCancelby(sched_root_task_t * __restrict root, sched_task_type_t type,
1.1 misho 836: u_char criteria, void *param, sched_hook_func_t hook)
837: {
1.8 misho 838: sched_task_t *task, *tmp;
1.5 misho 839: sched_queue_t *queue;
1.8 misho 840: register int flg = 0;
1.1 misho 841:
842: if (!root)
843: return -1;
1.10 misho 844: /* if type == taskMAX check in all queues */
1.5 misho 845: if (type == taskMAX) {
846: if (schedCancelby(root, taskREAD, criteria, param, hook))
1.1 misho 847: return -2;
1.5 misho 848: if (schedCancelby(root, taskWRITE, criteria, param, hook))
1.1 misho 849: return -2;
1.10 misho 850: if (schedCancelby(root, taskTIMER, criteria, param, hook))
851: return -2;
1.9 misho 852: if (schedCancelby(root, taskALARM, criteria, param, hook))
853: return -2;
1.19 misho 854: if (schedCancelby(root, taskRTC, criteria, param, hook))
855: return -2;
1.10 misho 856: if (schedCancelby(root, taskNODE, criteria, param, hook))
857: return -2;
858: if (schedCancelby(root, taskPROC, criteria, param, hook))
859: return -2;
1.12 misho 860: if (schedCancelby(root, taskSIGNAL, criteria, param, hook))
861: return -2;
862: if (schedCancelby(root, taskAIO, criteria, param, hook))
863: return -2;
864: if (schedCancelby(root, taskLIO, criteria, param, hook))
865: return -2;
1.10 misho 866: if (schedCancelby(root, taskUSER, criteria, param, hook))
867: return -2;
1.5 misho 868: if (schedCancelby(root, taskEVENT, criteria, param, hook))
1.1 misho 869: return -2;
1.13 misho 870: if (schedCancelby(root, taskTASK, criteria, param, hook))
1.1 misho 871: return -2;
1.11 misho 872: if (schedCancelby(root, taskSUSPEND, criteria, param, hook))
873: return -2;
1.5 misho 874: if (schedCancelby(root, taskREADY, criteria, param, hook))
1.1 misho 875: return -2;
1.15 misho 876: if (schedCancelby(root, taskTHREAD, criteria, param, hook))
877: return -2;
1.1 misho 878: return 0;
879: }
1.10 misho 880: /* choosen queue */
1.5 misho 881: switch (type) {
882: case taskREAD:
883: queue = &root->root_read;
884: break;
885: case taskWRITE:
886: queue = &root->root_write;
887: break;
1.10 misho 888: case taskTIMER:
889: queue = &root->root_timer;
890: break;
1.9 misho 891: case taskALARM:
892: queue = &root->root_alarm;
893: break;
1.19 misho 894: case taskRTC:
895: queue = &root->root_rtc;
896: break;
1.10 misho 897: case taskNODE:
898: queue = &root->root_node;
899: break;
900: case taskPROC:
901: queue = &root->root_proc;
902: break;
1.12 misho 903: case taskSIGNAL:
904: queue = &root->root_signal;
905: break;
906: case taskAIO:
907: queue = &root->root_aio;
908: break;
909: case taskLIO:
910: queue = &root->root_lio;
911: break;
1.10 misho 912: case taskUSER:
913: queue = &root->root_user;
914: break;
1.5 misho 915: case taskEVENT:
916: queue = &root->root_event;
917: break;
1.13 misho 918: case taskTASK:
919: queue = &root->root_task;
1.5 misho 920: break;
1.11 misho 921: case taskSUSPEND:
922: queue = &root->root_suspend;
923: break;
1.5 misho 924: case taskREADY:
925: queue = &root->root_ready;
926: break;
1.15 misho 927: case taskTHREAD:
928: queue = &root->root_thread;
929: break;
1.5 misho 930: default:
931: return 0;
932: }
1.1 misho 933:
1.26 misho 934: SCHED_QLOCK(root, type);
1.8 misho 935: TAILQ_FOREACH_SAFE(task, queue, task_node, tmp) {
936: flg ^= flg;
937: switch (criteria) {
1.10 misho 938: case CRITERIA_ANY:
939: flg = 1;
940: break;
1.8 misho 941: case CRITERIA_CALL:
942: if (TASK_FUNC(task) == (sched_task_func_t) param)
943: flg = 1;
1.1 misho 944: break;
1.8 misho 945: case CRITERIA_ARG:
946: if (TASK_ARG(task) == param)
947: flg = 1;
1.1 misho 948: break;
1.8 misho 949: case CRITERIA_FD:
950: if (TASK_FD(task) == (intptr_t) param)
951: flg = 1;
1.1 misho 952: break;
1.11 misho 953: case CRITERIA_ID:
1.8 misho 954: case CRITERIA_VAL:
955: if (TASK_VAL(task) == (u_long) param)
956: flg = 1;
1.1 misho 957: break;
1.8 misho 958: case CRITERIA_TS:
959: if (!sched_timespeccmp(&TASK_TS(task), (struct timespec*) param, -))
960: flg = 1;
1.1 misho 961: break;
1.10 misho 962: case CRITERIA_DATA:
963: if (TASK_DATA(task) == param)
964: flg = 1;
965: break;
1.23 misho 966: case CRITERIA_DATLEN:
967: if (TASK_DATLEN(task) == (size_t) param)
968: flg = 1;
969: break;
1.8 misho 970: default:
971: sched_SetErr(EINVAL, "Invalid parameter criteria %d", criteria);
972: flg = -1;
973: }
1.10 misho 974: if (flg < 0) /* error */
1.8 misho 975: break;
976: /* cancel choosen task */
977: if (flg > 0) {
978: if (TASK_ROOT(task)->root_hooks.hook_exec.cancel)
979: if (TASK_ROOT(task)->root_hooks.hook_exec.cancel(task, NULL)) {
980: flg = -1;
981: break;
982: }
983: /* custom hook */
984: if (hook)
985: if (hook(task, NULL)) {
986: flg = -3;
987: break;
988: }
989:
990: TAILQ_REMOVE(queue, task, task_node);
991: if (TASK_TYPE(task) != taskUNUSE)
1.15 misho 992: sched_unuseTask(task);
1.8 misho 993:
994: flg ^= flg; /* ok */
1.1 misho 995: }
1.8 misho 996: }
1.26 misho 997: SCHED_QUNLOCK(root, type);
998:
1.8 misho 999: return flg;
1.1 misho 1000: }
1001:
1002: /*
1003: * schedRun() - Scheduler *run loop*
1.6 misho 1004: *
1.1 misho 1005: * @root = root task
1.2 misho 1006: * @killState = kill condition variable, if !=0 stop scheduler loop
1.1 misho 1007: * return: -1 error or 0 ok
1008: */
1009: int
1.7 misho 1010: schedRun(sched_root_task_t *root, volatile intptr_t * __restrict killState)
1.1 misho 1011: {
1012: sched_task_t *task;
1013:
1014: if (!root)
1015: return -1;
1016:
1017: if (root->root_hooks.hook_exec.run)
1018: if (root->root_hooks.hook_exec.run(root, NULL))
1019: return -1;
1.7 misho 1020:
1021: if (killState) {
1022: if (root->root_hooks.hook_exec.condition)
1023: /* condition scheduler loop */
1024: while (root && root->root_hooks.hook_exec.fetch &&
1025: root->root_hooks.hook_exec.condition &&
1026: root->root_hooks.hook_exec.condition(root, (void*) killState)) {
1027: if ((task = root->root_hooks.hook_exec.fetch(root, NULL)))
1.12 misho 1028: root->root_ret = schedCall(task);
1.7 misho 1029: }
1030: else
1031: /* trigger scheduler loop */
1032: while (!*killState && root && root->root_hooks.hook_exec.fetch) {
1033: if ((task = root->root_hooks.hook_exec.fetch(root, NULL)))
1.12 misho 1034: root->root_ret = schedCall(task);
1.7 misho 1035: }
1036: } else
1037: /* infinite scheduler loop */
1038: while (root && root->root_hooks.hook_exec.fetch)
1039: if ((task = root->root_hooks.hook_exec.fetch(root, NULL)))
1.12 misho 1040: root->root_ret = schedCall(task);
1.1 misho 1041:
1042: return 0;
1043: }
1.5 misho 1044:
1045: /*
1046: * schedPolling() - Polling timeout period if no timer task is present
1.6 misho 1047: *
1.5 misho 1048: * @root = root task
1049: * @ts = timeout polling period, if ==NULL INFINIT timeout
1050: * @tsold = old timeout polling if !=NULL
1051: * return: -1 error or 0 ok
1052: */
1.18 misho 1053: int
1.5 misho 1054: schedPolling(sched_root_task_t * __restrict root, struct timespec * __restrict ts,
1055: struct timespec * __restrict tsold)
1056: {
1057: if (!root)
1058: return -1;
1059:
1060: if (tsold)
1061: *tsold = root->root_poll;
1062:
1063: if (!ts)
1064: sched_timespecinf(&root->root_poll);
1065: else
1066: root->root_poll = *ts;
1067:
1068: return 0;
1069: }
1.6 misho 1070:
1071: /*
1072: * schedTermCondition() - Activate hook for scheduler condition kill
1073: *
1074: * @root = root task
1075: * @condValue = condition value, kill schedRun() if condValue == killState
1.13 misho 1076: * return: -1 error or 0 ok
1.6 misho 1077: */
1.18 misho 1078: int
1.26 misho 1079: schedTermCondition(sched_root_task_t * __restrict root, intptr_t * __restrict condValue)
1.6 misho 1080: {
1.26 misho 1081: if (!root && !condValue)
1.6 misho 1082: return -1;
1083:
1.26 misho 1084: *root->root_cond = *condValue;
1.6 misho 1085: root->root_hooks.hook_exec.condition = sched_hook_condition;
1086: return 0;
1087: }
1.11 misho 1088:
1089: /*
1090: * schedResumeby() - Resume suspended task
1091: *
1092: * @root = root task
1093: * @criteria = find task by criteria
1.23 misho 1094: * [CRITERIA_ANY|CRITERIA_ID|CRITERIA_VAL|CRITERIA_DATA]
1.20 misho 1095: * @param = search parameter (sched_task_t *task| unsigned long id)
1.11 misho 1096: * return: -1 error or 0 resumed ok
1097: */
1098: int
1099: schedResumeby(sched_root_task_t * __restrict root, u_char criteria, void *param)
1100: {
1101: sched_task_t *task, *tmp;
1102: register int flg = 0;
1103:
1104: if (!root)
1105: return -1;
1106:
1.26 misho 1107: SCHED_QLOCK(root, taskSUSPEND);
1.11 misho 1108: TAILQ_FOREACH_SAFE(task, &root->root_suspend, task_node, tmp) {
1109: flg ^= flg;
1110: switch (criteria) {
1111: case CRITERIA_ANY:
1112: flg = 1;
1113: break;
1114: case CRITERIA_ID:
1.23 misho 1115: case CRITERIA_VAL:
1.11 misho 1116: if (TASK_VAL(task) == (u_long) param)
1117: flg = 1;
1118: break;
1119: case CRITERIA_DATA:
1120: if (TASK_ID(task) == (sched_task_t*) param)
1121: flg = 1;
1122: break;
1123: default:
1124: sched_SetErr(EINVAL, "Invalid parameter criteria %d", criteria);
1125: flg = -1;
1126: }
1127: if (flg < 0)
1128: break;
1129: /* resume choosen task */
1130: if (flg > 0) {
1131: if (root->root_hooks.hook_exec.resume)
1132: if (root->root_hooks.hook_exec.resume(task, NULL)) {
1133: flg = -1;
1134: break;
1135: }
1136:
1137: TAILQ_REMOVE(&root->root_suspend, task, task_node);
1138:
1139: task->task_type = taskREADY;
1.26 misho 1140: insert_task_to(task, &root->root_ready);
1.11 misho 1141:
1142: flg ^= flg; /* ok */
1143: }
1144: }
1.26 misho 1145: SCHED_QUNLOCK(root, taskSUSPEND);
1.11 misho 1146:
1147: return flg;
1148: }
1.31 misho 1149:
1150: static void *
1151: _sched_sigDisp(void *arg)
1152: {
1153: sched_root_task_t *root = arg;
1154: sched_task_t *task, *tmp;
1155: int sig, flg;
1156: sigset_t ss;
1157:
1158: sigfillset(&ss);
1159: while (root->root_sigthr) {
1160: if (sigwait(&ss, &sig))
1161: continue;
1162:
1163: pthread_mutex_lock(&root->root_sigmtx);
1164: if (!sigismember(&root->root_sigset, sig)) {
1165: pthread_mutex_unlock(&root->root_sigmtx);
1166: continue;
1167: }
1168:
1169: flg = 0;
1170: TAILQ_FOREACH_SAFE(task, &root->root_signal, task_node, tmp) {
1171: if (TASK_VAL(task) == (uintptr_t) sig) {
1172: if (!flg) {
1173: TASK_RET(task) = 0;
1174: TASK_FLAG(task) = 0;
1175:
1176: /* remove signal handle */
1177: transit_task2ready(task, &root->root_signal);
1178: }
1179: flg++;
1180: }
1181: }
1182: if (flg < 2)
1183: sigdelset(&root->root_sigset, sig);
1184:
1185: pthread_mutex_unlock(&root->root_sigmtx);
1186: }
1187:
1188: return NULL;
1189: }
1190:
1191: /*
1192: * schedSignalDispatch() - Activate or Deactivate signal dispatcher
1193: *
1194: * @root = root task
1195: * @on = Activate or =0 deactivate
1196: * return: -1 error or 0 ok
1197: */
1198: int
1199: schedSignalDispatch(sched_root_task_t * __restrict root, int on)
1200: {
1.32.2.1! misho 1201: sigset_t ss;
1.32 misho 1202: struct timespec ts = { .tv_sec = 1, .tv_nsec = 0 };
1.31 misho 1203: #ifndef HAVE_LIBPTHREAD
1204: sched_SetErr(ENOTSUP, "Library has not support pthreads");
1205: return -1;
1206: #else
1207: pthread_attr_t attr;
1208: #endif
1209:
1210: #if SUP_ENABLE == KQ_SUPPORT
1211: return 0;
1212: #endif
1213:
1214: if (!on) {
1215: pthread_cancel(root->root_sigthr);
1216: #ifdef __linux__
1217: root->root_sigthr = 0L;
1218: #else
1219: root->root_sigthr = NULL;
1220: #endif
1221: return 0;
1222: }
1223:
1.32 misho 1224: /* if we have not using polling, then we must turn on */
1225: if (sched_timespecisinf(&root->root_poll))
1226: schedPolling(root, &ts, NULL);
1227:
1.31 misho 1228: pthread_attr_init(&attr);
1229: pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1230: #ifdef SCHED_RR
1231: pthread_attr_setschedpolicy(&attr, SCHED_RR);
1232: #else
1233: pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
1234: #endif
1235:
1.32.2.1! misho 1236: sigfillset(&ss);
! 1237: pthread_sigmask(SIG_BLOCK, &ss, NULL);
! 1238:
1.31 misho 1239: if (pthread_create(&root->root_sigthr, &attr, _sched_sigDisp, root)) {
1240: sched_SetErr(errno, "pthread_create(SignalDispatch) #%d - %s",
1241: errno, strerror(errno));
1242: #ifdef __linux__
1243: root->root_sigthr = 0L;
1244: #else
1245: root->root_sigthr = NULL;
1246: #endif
1.32.2.1! misho 1247: pthread_sigmask(SIG_SETMASK, &root->root_oldset, NULL);
1.31 misho 1248: return -1;
1249: }
1250:
1251: return 0;
1252: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>