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