File:  [ELWIX - Embedded LightWeight unIX -] / libaitsched / src / aitsched.c
Revision 1.30.2.6: download - view: text, annotated - select for diffs - revision graph
Sat Feb 25 15:46:15 2023 UTC (16 months ago) by misho
Branches: sched7_4
Diff to: branchpoint 1.30: preferred, unified
implement signal handling and dispatcher for signal on epoll() and select()
improve wait state of event fetch hook. when we have small polling period against timer task.
then we will rolling event state machine on smallest period between polling and timer

    1: /*************************************************************************
    2: * (C) 2011 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
    3: *  by Michael Pounov <misho@openbsd-bg.org>
    4: *
    5: * $Author: misho $
    6: * $Id: aitsched.c,v 1.30.2.6 2023/02/25 15:46:15 misho Exp $
    7: *
    8: **************************************************************************
    9: The ELWIX and AITNET software is distributed under the following
   10: terms:
   11: 
   12: All of the documentation and software included in the ELWIX and AITNET
   13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
   14: 
   15: Copyright 2004 - 2023
   16: 	by Michael Pounov <misho@elwix.org>.  All rights reserved.
   17: 
   18: Redistribution and use in source and binary forms, with or without
   19: modification, are permitted provided that the following conditions
   20: are met:
   21: 1. Redistributions of source code must retain the above copyright
   22:    notice, this list of conditions and the following disclaimer.
   23: 2. Redistributions in binary form must reproduce the above copyright
   24:    notice, this list of conditions and the following disclaimer in the
   25:    documentation and/or other materials provided with the distribution.
   26: 3. All advertising materials mentioning features or use of this software
   27:    must display the following acknowledgement:
   28: This product includes software developed by Michael Pounov <misho@elwix.org>
   29: ELWIX - Embedded LightWeight unIX and its contributors.
   30: 4. Neither the name of AITNET nor the names of its contributors
   31:    may be used to endorse or promote products derived from this software
   32:    without specific prior written permission.
   33: 
   34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
   35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   37: ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   44: SUCH DAMAGE.
   45: */
   46: #include "global.h"
   47: #include "hooks.h"
   48: 
   49: 
   50: #pragma GCC visibility push(hidden)
   51: 
   52: int sched_Errno;
   53: char sched_Error[STRSIZ];
   54: 
   55: #pragma GCC visibility pop
   56: 
   57: 
   58: // sched_GetErrno() Get error code of last operation
   59: int
   60: sched_GetErrno()
   61: {
   62: 	return sched_Errno;
   63: }
   64: 
   65: // sched_GetError() Get error text of last operation
   66: const char *
   67: sched_GetError()
   68: {
   69: 	return sched_Error;
   70: }
   71: 
   72: // sched_SetErr() Set error to variables for internal use!!!
   73: void
   74: sched_SetErr(int eno, char *estr, ...)
   75: {
   76: 	va_list lst;
   77: 
   78: 	sched_Errno = eno;
   79: 	memset(sched_Error, 0, sizeof sched_Error);
   80: 	va_start(lst, estr);
   81: 	vsnprintf(sched_Error, sizeof sched_Error, estr, lst);
   82: 	va_end(lst);
   83: }
   84: 
   85: 
   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: 
  158: /* Init and prepare scheduler functions */
  159: 
  160: /*
  161:  * schedRegisterHooks() - Register IO handles and bind tasks to it
  162:  *
  163:  * @root = root task
  164:  * return: -1 error or 0 ok
  165:  */
  166: int
  167: schedRegisterHooks(sched_root_task_t * __restrict root)
  168: {
  169: 	assert(root);
  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;
  177: #if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME) && defined(HAVE_TIMER_DELETE)
  178: 	root->root_hooks.hook_add.rtc = sched_hook_rtc;
  179: #endif
  180: #if SUP_ENABLE == KQ_SUPPORT
  181: 	root->root_hooks.hook_add.alarm = sched_hook_alarm;
  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
  187: #endif	/* KQ_SUPPORT */
  188: #ifdef HAVE_LIBPTHREAD
  189: 	root->root_hooks.hook_add.thread = sched_hook_thread;
  190: #endif
  191: 	root->root_hooks.hook_add.signal = sched_hook_signal;
  192: 
  193: 	root->root_hooks.hook_exec.cancel = sched_hook_cancel;
  194: 	root->root_hooks.hook_exec.fetch = sched_hook_fetch;
  195: 	root->root_hooks.hook_exec.exception = sched_hook_exception;
  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: /*
  203:  * schedInit() - Init scheduler
  204:  *
  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 *);
  214: #ifdef HAVE_LIBPTHREAD
  215: 	register int i;
  216: #endif
  217: 
  218: 	root = e_malloc(sizeof(sched_root_task_t));
  219: 	if (!root) {
  220: 		LOGERR;
  221: 	} else {
  222: 		memset(root, 0, sizeof(sched_root_task_t));
  223: 
  224: 		/* set default maximum regular task hit misses */
  225: 		root->root_miss = MAX_TASK_MISS;
  226: 
  227: 		/* INFINIT polling period by default */
  228: 		sched_timespecinf(&root->root_poll);
  229: 
  230: #ifdef HAVE_LIBPTHREAD
  231: 		if (pthread_mutex_init(&root->root_sigmtx, NULL)) {
  232: 			LOGERR;
  233: 			e_free(root);
  234: 			return NULL;
  235: 		}
  236: 
  237: 		for (i = 0; i < taskMAX; i++)
  238: 			if ((errno = pthread_mutex_init(&root->root_mtx[i], NULL))) {
  239: 				LOGERR;
  240: 				while (i)
  241: 					pthread_mutex_destroy(&root->root_mtx[--i]);
  242: 				e_free(root);
  243: 				return NULL;
  244: 			}
  245: 
  246: 		for (i = 0; i < taskMAX; i++)
  247: 			pthread_mutex_lock(&root->root_mtx[i]);
  248: #endif
  249: 
  250: 		TAILQ_INIT(&root->root_read);
  251: 		TAILQ_INIT(&root->root_write);
  252: 		TAILQ_INIT(&root->root_timer);
  253: 		TAILQ_INIT(&root->root_alarm);
  254: 		TAILQ_INIT(&root->root_rtc);
  255: 		TAILQ_INIT(&root->root_node);
  256: 		TAILQ_INIT(&root->root_proc);
  257: 		TAILQ_INIT(&root->root_signal);
  258: 		TAILQ_INIT(&root->root_aio);
  259: 		TAILQ_INIT(&root->root_lio);
  260: 		TAILQ_INIT(&root->root_user);
  261: 		TAILQ_INIT(&root->root_event);
  262: 		TAILQ_INIT(&root->root_task);
  263: 		TAILQ_INIT(&root->root_suspend);
  264: 		TAILQ_INIT(&root->root_ready);
  265: 		TAILQ_INIT(&root->root_unuse);
  266: 		TAILQ_INIT(&root->root_thread);
  267: 
  268: #ifdef HAVE_LIBPTHREAD
  269: 		for (i = 0; i < taskMAX; i++)
  270: 			pthread_mutex_unlock(&root->root_mtx[i]);
  271: #endif
  272: 
  273: 		if (data && *data) {
  274: 			if (datlen) {
  275: 				root->root_data.iov_base = *data;
  276: 				root->root_data.iov_len = datlen;
  277: 			} else { /* if datlen == 0, switch to callbacks init mode */
  278: 				 /* little hack :) for correct initialization of scheduler */
  279: 				func = (int(*)(sched_root_task_t*)) data;
  280: 				func(root);
  281: 			}
  282: 		}
  283: 
  284: 		if (root->root_hooks.hook_root.init)
  285: 			root->root_hooks.hook_root.init(root, NULL);
  286: 	}
  287: 
  288: 	return root;
  289: }
  290: 
  291: /*
  292:  * schedEnd() - End scheduler & free all resources
  293:  *
  294:  * @root = root task
  295:  * return: -1 error or 0 ok
  296:  */
  297: int
  298: schedEnd(sched_root_task_t ** __restrict root)
  299: {
  300: 	sched_task_t *task, *tmp;
  301: #ifdef HAVE_LIBPTHREAD
  302: 	register int i;
  303: #endif
  304: 
  305: 	if (!root || !*root)
  306: 		return -1;
  307: 
  308: #if 0
  309: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_read, task_node, tmp)
  310: 		printf("read=%p\n", task);
  311: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_write, task_node, tmp)
  312: 		printf("write=%p\n", task);
  313: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_timer, task_node, tmp)
  314: 		printf("timer=%p\n", task);
  315: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_alarm, task_node, tmp)
  316: 		printf("alarm=%p\n", task);
  317: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_rtc, task_node, tmp)
  318: 		printf("rtc=%p\n", task);
  319: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_node, task_node, tmp)
  320: 		printf("node=%p\n", task);
  321: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_proc, task_node, tmp)
  322: 		printf("proc=%p\n", task);
  323: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_signal, task_node, tmp)
  324: 		printf("signal=%p\n", task);
  325: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_aio, task_node, tmp)
  326: 		printf("aio=%p\n", task);
  327: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_lio, task_node, tmp)
  328: 		printf("lio=%p\n", task);
  329: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_user, task_node, tmp)
  330: 		printf("user=%p\n", task);
  331: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_event, task_node, tmp)
  332: 		printf("event=%p\n", task);
  333: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_suspend, task_node, tmp)
  334: 		printf("suspend=%p\n", task);
  335: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_ready, task_node, tmp)
  336: 		printf("ready=%p\n", task);
  337: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_thread, task_node, tmp)
  338: 		printf("thread=%p\n", task);
  339: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_task, task_node, tmp)
  340: 		printf("task=%p\n", task);
  341: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_unuse, task_node, tmp)
  342: 		printf("unuse=%p\n", task);
  343: 	fflush(stdout);
  344: #endif
  345: 
  346: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_read, task_node, tmp)
  347: 		schedCancel(task);
  348: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_write, task_node, tmp)
  349: 		schedCancel(task);
  350: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_timer, task_node, tmp)
  351: 		schedCancel(task);
  352: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_alarm, task_node, tmp)
  353: 		schedCancel(task);
  354: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_rtc, task_node, tmp)
  355: 		schedCancel(task);
  356: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_node, task_node, tmp)
  357: 		schedCancel(task);
  358: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_proc, task_node, tmp)
  359: 		schedCancel(task);
  360: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_signal, task_node, tmp)
  361: 		schedCancel(task);
  362: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_aio, task_node, tmp)
  363: 		schedCancel(task);
  364: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_lio, task_node, tmp)
  365: 		schedCancel(task);
  366: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_user, task_node, tmp)
  367: 		schedCancel(task);
  368: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_event, task_node, tmp)
  369: 		schedCancel(task);
  370: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_suspend, task_node, tmp)
  371: 		schedCancel(task);
  372: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_ready, task_node, tmp)
  373: 		schedCancel(task);
  374: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_thread, task_node, tmp)
  375: 		schedCancel(task);
  376: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_task, task_node, tmp)
  377: 		schedCancel(task);
  378: 
  379: 	SCHED_QLOCK((*root), taskUNUSE);
  380: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_unuse, task_node, tmp) {
  381: 		TAILQ_REMOVE(&(*root)->root_unuse, task, task_node);
  382: 		e_free(task);
  383: 	}
  384: 	SCHED_QUNLOCK((*root), taskUNUSE);
  385: 
  386: 	if ((*root)->root_hooks.hook_root.fini)
  387: 		(*root)->root_hooks.hook_root.fini(*root, NULL);
  388: 
  389: #ifdef HAVE_LIBPTHREAD
  390: 	for (i = 0; i < taskMAX; i++) {
  391: 		SCHED_QTRYLOCK(*root, i);
  392: 		SCHED_QUNLOCK(*root, i);
  393: 		pthread_mutex_destroy(&(*root)->root_mtx[i]);
  394: 	}
  395: 
  396: 	if ((*root)->root_sigthr) {
  397: 		pthread_cancel((*root)->root_sigthr);
  398: #ifdef __linux__
  399: 		(*root)->root_sigthr = 0L;
  400: #else
  401: 		(*root)->root_sigthr = NULL;
  402: #endif
  403: 		pthread_sigmask(SIG_SETMASK, &(*root)->root_oldset, NULL);
  404: 		pthread_mutex_unlock(&(*root)->root_sigmtx);
  405: 	}
  406: 	pthread_mutex_destroy(&(*root)->root_sigmtx);
  407: #endif
  408: 
  409: 	e_free(*root);
  410: 	*root = NULL;
  411: 	return 0;
  412: }
  413: 
  414: /*
  415:  * schedCall() - Call task execution function
  416:  *
  417:  * @task = current task
  418:  * return: !=NULL error or =NULL ok
  419:  */
  420: void *
  421: schedCall(sched_task_t * __restrict task)
  422: {
  423: 	void *ptr = (void*) -1;
  424: 
  425: 	if (!task)
  426: 		return ptr;
  427: 
  428: 	if (!TASK_ISLOCKED(task))
  429: 		TASK_LOCK(task);
  430: 
  431: 	ptr = task->task_func(task);
  432: 
  433: 	TASK_UNLOCK(task);
  434: 	return ptr;
  435: }
  436: 
  437: /*
  438:  * schedFetch() - Fetch ready task
  439:  *
  440:  * @root = root task
  441:  * return: =NULL error or !=NULL ready task
  442:  */
  443: void *
  444: schedFetch(sched_root_task_t * __restrict root)
  445: {
  446: 	void *ptr;
  447: 
  448: 	if (!root)
  449: 		return NULL;
  450: 
  451: 	if (root->root_hooks.hook_exec.fetch)
  452: 		ptr = root->root_hooks.hook_exec.fetch(root, NULL);
  453: 	else
  454: 		ptr = NULL;
  455: 
  456: 	return ptr;
  457: }
  458: 
  459: /*
  460:  * schedTrigger() - Triggering USER task
  461:  *
  462:  * @task = task
  463:  * return: -1 error or 0 ok
  464:  */
  465: int
  466: schedTrigger(sched_task_t * __restrict task)
  467: {
  468: #if SUP_ENABLE != KQ_SUPPORT
  469: 	sched_SetErr(ENOTSUP, "disabled kqueue support");
  470: 	return -1;
  471: #else
  472: #ifndef EVFILT_USER
  473: 	sched_SetErr(ENOTSUP, "Not supported kevent() filter");
  474: 	return -1;
  475: #else
  476: 	struct kevent chg[1];
  477: 	struct timespec timeout = { 0, 0 };
  478: 
  479: 	if (!task || !TASK_ROOT(task))
  480: 		return -1;
  481: 
  482: #ifdef __NetBSD__
  483: 	EV_SET(chg, TASK_VAL(task), EVFILT_USER, 0, NOTE_TRIGGER, 0, (intptr_t) TASK_VAL(task));
  484: #else
  485: 	EV_SET(chg, TASK_VAL(task), EVFILT_USER, 0, NOTE_TRIGGER, 0, (void*) TASK_VAL(task));
  486: #endif
  487: 	if (kevent(TASK_ROOT(task)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
  488: 		LOGERR;
  489: 		return -1;
  490: 	}
  491: 
  492: 	return 0;
  493: #endif
  494: #endif	/* KQ_SUPPORT */
  495: }
  496: 
  497: /*
  498:  * schedQuery() - Query task in scheduler
  499:  *
  500:  * @task = task
  501:  * return: -1 error, 0 found  and 1 not found
  502:  */
  503: int
  504: schedQuery(sched_task_t * __restrict task)
  505: {
  506: 	sched_queue_t *queue;
  507: 	sched_task_t *t;
  508: 
  509: 	if (!task || !TASK_ROOT(task))
  510: 		return -1;	/* error */
  511: 
  512: 	switch (TASK_TYPE(task)) {
  513: 		case taskREAD:
  514: 			queue = &TASK_ROOT(task)->root_read;
  515: 			break;
  516: 		case taskWRITE:
  517: 			queue = &TASK_ROOT(task)->root_write;
  518: 			break;
  519: 		case taskTIMER:
  520: 			queue = &TASK_ROOT(task)->root_timer;
  521: 			break;
  522: 		case taskALARM:
  523: 			queue = &TASK_ROOT(task)->root_alarm;
  524: 			break;
  525: 		case taskRTC:
  526: 			queue = &TASK_ROOT(task)->root_rtc;
  527: 			break;
  528: 		case taskNODE:
  529: 			queue = &TASK_ROOT(task)->root_node;
  530: 			break;
  531: 		case taskPROC:
  532: 			queue = &TASK_ROOT(task)->root_proc;
  533: 			break;
  534: 		case taskSIGNAL:
  535: 			queue = &TASK_ROOT(task)->root_signal;
  536: 			break;
  537: 		case taskAIO:
  538: 			queue = &TASK_ROOT(task)->root_aio;
  539: 			break;
  540: 		case taskLIO:
  541: 			queue = &TASK_ROOT(task)->root_lio;
  542: 			break;
  543: 		case taskUSER:
  544: 			queue = &TASK_ROOT(task)->root_user;
  545: 			break;
  546: 		case taskEVENT:
  547: 			queue = &TASK_ROOT(task)->root_event;
  548: 			break;
  549: 		case taskTASK:
  550: 			queue = &TASK_ROOT(task)->root_task;
  551: 			break;
  552: 		case taskSUSPEND:
  553: 			queue = &TASK_ROOT(task)->root_suspend;
  554: 			break;
  555: 		case taskREADY:
  556: 			queue = &TASK_ROOT(task)->root_ready;
  557: 			break;
  558: 		case taskTHREAD:
  559: 			queue = &TASK_ROOT(task)->root_thread;
  560: 			break;
  561: 		default:
  562: 			return 1;	/* not in queue */
  563: 	}
  564: 	if (queue)
  565: 		TAILQ_FOREACH(t, queue, task_node)
  566: 			if (TASK_ID(t) == TASK_ID(task))
  567: 				return 0;	/* found */
  568: 
  569: 	return 1;	/* not in queue */
  570: }
  571: 
  572: /*
  573:  * schedQueryby() - Query task in scheduler by criteria
  574:  *
  575:  * @root = root task
  576:  * @type = query from queue type, if =taskMAX query same task from all queues
  577:  * @criteria = find task by criteria 
  578:  * 	[ CRITERIA_ANY|CRITERIA_CALL|CRITERIA_ARG|CRITERIA_FD|CRITERIA_VAL|
  579:  * 		CRITERIA_ID|CRITERIA_TS|CRITERIA_DATA|CRITERIA_DATLEN ]
  580:  * @param = search parameter
  581:  * return: NULL not found or !=NULL task
  582:  */
  583: sched_task_t *
  584: schedQueryby(sched_root_task_t * __restrict root, sched_task_type_t type, 
  585: 		u_char criteria, void *param)
  586: {
  587: 	sched_task_t *task;
  588: 	sched_queue_t *queue;
  589: 
  590: 	if (!root)
  591: 		return NULL;
  592: 	/* if type == taskMAX check in all queues */
  593: 	if (type == taskMAX) {
  594: 		if ((task = schedQueryby(root, taskREAD, criteria, param)))
  595: 			return task;
  596: 		if ((task = schedQueryby(root, taskWRITE, criteria, param)))
  597: 			return task;
  598: 		if ((task = schedQueryby(root, taskTIMER, criteria, param)))
  599: 			return task;
  600: 		if ((task = schedQueryby(root, taskALARM, criteria, param)))
  601: 			return task;
  602: 		if ((task = schedQueryby(root, taskRTC, criteria, param)))
  603: 			return task;
  604: 		if ((task = schedQueryby(root, taskNODE, criteria, param)))
  605: 			return task;
  606: 		if ((task = schedQueryby(root, taskPROC, criteria, param)))
  607: 			return task;
  608: 		if ((task = schedQueryby(root, taskSIGNAL, criteria, param)))
  609: 			return task;
  610: 		if ((task = schedQueryby(root, taskAIO, criteria, param)))
  611: 			return task;
  612: 		if ((task = schedQueryby(root, taskLIO, criteria, param)))
  613: 			return task;
  614: 		if ((task = schedQueryby(root, taskUSER, criteria, param)))
  615: 			return task;
  616: 		if ((task = schedQueryby(root, taskEVENT, criteria, param)))
  617: 			return task;
  618: 		if ((task = schedQueryby(root, taskTASK, criteria, param)))
  619: 			return task;
  620: 		if ((task = schedQueryby(root, taskSUSPEND, criteria, param)))
  621: 			return task;
  622: 		if ((task = schedQueryby(root, taskREADY, criteria, param)))
  623: 			return task;
  624: 		if ((task = schedQueryby(root, taskTHREAD, criteria, param)))
  625: 			return task;
  626: 		return NULL;	/* not found */
  627: 	}
  628: 	/* choosen queue */
  629: 	switch (type) {
  630: 		case taskREAD:
  631: 			queue = &root->root_read;
  632: 			break;
  633: 		case taskWRITE:
  634: 			queue = &root->root_write;
  635: 			break;
  636: 		case taskTIMER:
  637: 			queue = &root->root_timer;
  638: 			break;
  639: 		case taskALARM:
  640: 			queue = &root->root_alarm;
  641: 			break;
  642: 		case taskRTC:
  643: 			queue = &root->root_rtc;
  644: 			break;
  645: 		case taskNODE:
  646: 			queue = &root->root_node;
  647: 			break;
  648: 		case taskPROC:
  649: 			queue = &root->root_proc;
  650: 			break;
  651: 		case taskSIGNAL:
  652: 			queue = &root->root_signal;
  653: 			break;
  654: 		case taskAIO:
  655: 			queue = &root->root_aio;
  656: 			break;
  657: 		case taskLIO:
  658: 			queue = &root->root_lio;
  659: 			break;
  660: 		case taskUSER:
  661: 			queue = &root->root_user;
  662: 			break;
  663: 		case taskEVENT:
  664: 			queue = &root->root_event;
  665: 			break;
  666: 		case taskTASK:
  667: 			queue = &root->root_task;
  668: 			break;
  669: 		case taskSUSPEND:
  670: 			queue = &root->root_suspend;
  671: 			break;
  672: 		case taskREADY:
  673: 			queue = &root->root_ready;
  674: 			break;
  675: 		case taskTHREAD:
  676: 			queue = &root->root_thread;
  677: 			break;
  678: 		default:
  679: 			return NULL;	/* not found */
  680: 	}
  681: 
  682: 	TAILQ_FOREACH(task, queue, task_node) {
  683: 		switch (criteria) {
  684: 			case CRITERIA_ANY:
  685: 				return task;		/* found */
  686: 			case CRITERIA_CALL:
  687: 				if (TASK_FUNC(task) == (sched_task_func_t) param)
  688: 					return task;	/* found */
  689: 				break;
  690: 			case CRITERIA_ARG:
  691: 				if (TASK_ARG(task) == param)
  692: 					return task;	/* found */
  693: 				break;
  694: 			case CRITERIA_FD:
  695: 				if (TASK_FD(task) == (intptr_t) param)
  696: 					return task;	/* found */
  697: 				break;
  698: 			case CRITERIA_ID:
  699: 			case CRITERIA_VAL:
  700: 				if (TASK_VAL(task) == (u_long) param)
  701: 					return task;	/* found */
  702: 				break;
  703: 			case CRITERIA_TS:
  704: 				if (!sched_timespeccmp(&TASK_TS(task), 
  705: 							(struct timespec*) param, -))
  706: 					return task;	/* found */
  707: 				break;
  708: 			case CRITERIA_DATA:
  709: 				if (TASK_DATA(task) == param)
  710: 					return task;	/* found */
  711: 				break;
  712: 			case CRITERIA_DATLEN:
  713: 				if (TASK_DATLEN(task) == (size_t) param)
  714: 					return task;	/* found */
  715: 				break;
  716: 			default:
  717: 				sched_SetErr(EINVAL, "Invalid parameter criteria %d", 
  718: 						criteria);
  719: 				return NULL;		/* not found */
  720: 		}
  721: 	}
  722: 
  723: 	return NULL;	/* not found */
  724: }
  725: 
  726: /*
  727:  * schedCancel() - Cancel task from scheduler
  728:  *
  729:  * @task = task
  730:  * return: -1 error or 0 ok
  731:  */
  732: int
  733: schedCancel(sched_task_t * __restrict task)
  734: {
  735: 	sched_queue_t *queue;
  736: 
  737: 	if (!task || !TASK_ROOT(task))
  738: 		return -1;
  739: 
  740: 	if (TASK_ROOT(task)->root_hooks.hook_exec.cancel)
  741: 		if (TASK_ROOT(task)->root_hooks.hook_exec.cancel(task, NULL))
  742: 			return -1;
  743: 
  744: 	switch (TASK_TYPE(task)) {
  745: 		case taskREAD:
  746: 			queue = &TASK_ROOT(task)->root_read;
  747: 			break;
  748: 		case taskWRITE:
  749: 			queue = &TASK_ROOT(task)->root_write;
  750: 			break;
  751: 		case taskTIMER:
  752: 			queue = &TASK_ROOT(task)->root_timer;
  753: 			break;
  754: 		case taskALARM:
  755: 			queue = &TASK_ROOT(task)->root_alarm;
  756: 			break;
  757: 		case taskRTC:
  758: 			queue = &TASK_ROOT(task)->root_rtc;
  759: 			break;
  760: 		case taskNODE:
  761: 			queue = &TASK_ROOT(task)->root_node;
  762: 			break;
  763: 		case taskPROC:
  764: 			queue = &TASK_ROOT(task)->root_proc;
  765: 			break;
  766: 		case taskSIGNAL:
  767: 			queue = &TASK_ROOT(task)->root_signal;
  768: 			break;
  769: 		case taskAIO:
  770: 			queue = &TASK_ROOT(task)->root_aio;
  771: 			break;
  772: 		case taskLIO:
  773: 			queue = &TASK_ROOT(task)->root_lio;
  774: 			break;
  775: 		case taskUSER:
  776: 			queue = &TASK_ROOT(task)->root_user;
  777: 			break;
  778: 		case taskEVENT:
  779: 			queue = &TASK_ROOT(task)->root_event;
  780: 			break;
  781: 		case taskTASK:
  782: 			queue = &TASK_ROOT(task)->root_task;
  783: 			break;
  784: 		case taskSUSPEND:
  785: 			queue = &TASK_ROOT(task)->root_suspend;
  786: 			break;
  787: 		case taskREADY:
  788: 			queue = &TASK_ROOT(task)->root_ready;
  789: 			break;
  790: 		case taskTHREAD:
  791: 			queue = &TASK_ROOT(task)->root_thread;
  792: 			break;
  793: 		default:
  794: 			queue = NULL;
  795: 	}
  796: 	if (queue)
  797: 		remove_task_from(task, queue);
  798: 	if (TASK_TYPE(task) != taskUNUSE)
  799: 		sched_unuseTask(task);
  800: 
  801: 	return 0;
  802: }
  803: 
  804: /*
  805:  * schedCancelby() - Cancel task from scheduler by criteria
  806:  *
  807:  * @root = root task
  808:  * @type = cancel from queue type, if =taskMAX cancel same task from all queues
  809:  * @criteria = find task by criteria 
  810:  * 	[ CRITERIA_ANY|CRITERIA_CALL|CRITERIA_ARG|CRITERIA_FD|CRITERIA_VAL|
  811:  * 		CRITERIA_ID|CRITERIA_TS|CRITERIA_DATA|CRITERIA_DATLEN ]
  812:  * @param = search parameter
  813:  * @hook = custom cleanup hook function, may be NULL
  814:  * return: -1 error, -2 error in sub-stage cancel execution, -3 error from custom hook or 0 ok
  815:  */
  816: int
  817: schedCancelby(sched_root_task_t * __restrict root, sched_task_type_t type, 
  818: 		u_char criteria, void *param, sched_hook_func_t hook)
  819: {
  820: 	sched_task_t *task, *tmp;
  821: 	sched_queue_t *queue;
  822: 	register int flg = 0;
  823: 
  824: 	if (!root)
  825: 		return -1;
  826: 	/* if type == taskMAX check in all queues */
  827: 	if (type == taskMAX) {
  828: 		if (schedCancelby(root, taskREAD, criteria, param, hook))
  829: 			return -2;
  830: 		if (schedCancelby(root, taskWRITE, criteria, param, hook))
  831: 			return -2;
  832: 		if (schedCancelby(root, taskTIMER, criteria, param, hook))
  833: 			return -2;
  834: 		if (schedCancelby(root, taskALARM, criteria, param, hook))
  835: 			return -2;
  836: 		if (schedCancelby(root, taskRTC, criteria, param, hook))
  837: 			return -2;
  838: 		if (schedCancelby(root, taskNODE, criteria, param, hook))
  839: 			return -2;
  840: 		if (schedCancelby(root, taskPROC, criteria, param, hook))
  841: 			return -2;
  842: 		if (schedCancelby(root, taskSIGNAL, criteria, param, hook))
  843: 			return -2;
  844: 		if (schedCancelby(root, taskAIO, criteria, param, hook))
  845: 			return -2;
  846: 		if (schedCancelby(root, taskLIO, criteria, param, hook))
  847: 			return -2;
  848: 		if (schedCancelby(root, taskUSER, criteria, param, hook))
  849: 			return -2;
  850: 		if (schedCancelby(root, taskEVENT, criteria, param, hook))
  851: 			return -2;
  852: 		if (schedCancelby(root, taskTASK, criteria, param, hook))
  853: 			return -2;
  854: 		if (schedCancelby(root, taskSUSPEND, criteria, param, hook))
  855: 			return -2;
  856: 		if (schedCancelby(root, taskREADY, criteria, param, hook))
  857: 			return -2;
  858: 		if (schedCancelby(root, taskTHREAD, criteria, param, hook))
  859: 			return -2;
  860: 		return 0;
  861: 	}
  862: 	/* choosen queue */
  863: 	switch (type) {
  864: 		case taskREAD:
  865: 			queue = &root->root_read;
  866: 			break;
  867: 		case taskWRITE:
  868: 			queue = &root->root_write;
  869: 			break;
  870: 		case taskTIMER:
  871: 			queue = &root->root_timer;
  872: 			break;
  873: 		case taskALARM:
  874: 			queue = &root->root_alarm;
  875: 			break;
  876: 		case taskRTC:
  877: 			queue = &root->root_rtc;
  878: 			break;
  879: 		case taskNODE:
  880: 			queue = &root->root_node;
  881: 			break;
  882: 		case taskPROC:
  883: 			queue = &root->root_proc;
  884: 			break;
  885: 		case taskSIGNAL:
  886: 			queue = &root->root_signal;
  887: 			break;
  888: 		case taskAIO:
  889: 			queue = &root->root_aio;
  890: 			break;
  891: 		case taskLIO:
  892: 			queue = &root->root_lio;
  893: 			break;
  894: 		case taskUSER:
  895: 			queue = &root->root_user;
  896: 			break;
  897: 		case taskEVENT:
  898: 			queue = &root->root_event;
  899: 			break;
  900: 		case taskTASK:
  901: 			queue = &root->root_task;
  902: 			break;
  903: 		case taskSUSPEND:
  904: 			queue = &root->root_suspend;
  905: 			break;
  906: 		case taskREADY:
  907: 			queue = &root->root_ready;
  908: 			break;
  909: 		case taskTHREAD:
  910: 			queue = &root->root_thread;
  911: 			break;
  912: 		default:
  913: 			return 0;
  914: 	}
  915: 
  916: 	SCHED_QLOCK(root, type);
  917: 	TAILQ_FOREACH_SAFE(task, queue, task_node, tmp) {
  918: 		flg ^= flg;
  919: 		switch (criteria) {
  920: 			case CRITERIA_ANY:
  921: 				flg = 1;
  922: 				break;
  923: 			case CRITERIA_CALL:
  924: 				if (TASK_FUNC(task) == (sched_task_func_t) param)
  925: 					flg = 1;
  926: 				break;
  927: 			case CRITERIA_ARG:
  928: 				if (TASK_ARG(task) == param)
  929: 					flg = 1;
  930: 				break;
  931: 			case CRITERIA_FD:
  932: 				if (TASK_FD(task) == (intptr_t) param)
  933: 					flg = 1;
  934: 				break;
  935: 			case CRITERIA_ID:
  936: 			case CRITERIA_VAL:
  937: 				if (TASK_VAL(task) == (u_long) param)
  938: 					flg = 1;
  939: 				break;
  940: 			case CRITERIA_TS:
  941: 				if (!sched_timespeccmp(&TASK_TS(task), (struct timespec*) param, -))
  942: 					flg = 1;
  943: 				break;
  944: 			case CRITERIA_DATA:
  945: 				if (TASK_DATA(task) == param)
  946: 					flg = 1;
  947: 				break;
  948: 			case CRITERIA_DATLEN:
  949: 				if (TASK_DATLEN(task) == (size_t) param)
  950: 					flg = 1;
  951: 				break;
  952: 			default:
  953: 				sched_SetErr(EINVAL, "Invalid parameter criteria %d", criteria);
  954: 				flg = -1;
  955: 		}
  956: 		if (flg < 0)		/* error */
  957: 			break;
  958: 		/* cancel choosen task */
  959: 		if (flg > 0) {
  960: 			if (TASK_ROOT(task)->root_hooks.hook_exec.cancel)
  961: 				if (TASK_ROOT(task)->root_hooks.hook_exec.cancel(task, NULL)) {
  962: 					flg = -1;
  963: 					break;
  964: 				}
  965: 			/* custom hook */
  966: 			if (hook)
  967: 				if (hook(task, NULL)) {
  968: 					flg = -3;
  969: 					break;
  970: 				}
  971: 
  972: 			TAILQ_REMOVE(queue, task, task_node);
  973: 			if (TASK_TYPE(task) != taskUNUSE)
  974: 				sched_unuseTask(task);
  975: 
  976: 			flg ^= flg;	/* ok */
  977: 		}
  978: 	}
  979: 	SCHED_QUNLOCK(root, type);
  980: 
  981: 	return flg;
  982: }
  983: 
  984: /*
  985:  * schedRun() - Scheduler *run loop*
  986:  *
  987:  * @root = root task
  988:  * @killState = kill condition variable, if !=0 stop scheduler loop
  989:  * return: -1 error or 0 ok
  990:  */
  991: int
  992: schedRun(sched_root_task_t *root, volatile intptr_t * __restrict killState)
  993: {
  994: 	sched_task_t *task;
  995: 
  996: 	if (!root)
  997: 		return -1;
  998: 
  999: 	if (root->root_hooks.hook_exec.run)
 1000: 		if (root->root_hooks.hook_exec.run(root, NULL))
 1001: 			return -1;
 1002: 
 1003: 	if (killState) {
 1004: 		if (root->root_hooks.hook_exec.condition)
 1005: 			/* condition scheduler loop */
 1006: 			while (root && root->root_hooks.hook_exec.fetch && 
 1007: 					root->root_hooks.hook_exec.condition && 
 1008: 					root->root_hooks.hook_exec.condition(root, (void*) killState)) {
 1009: 				if ((task = root->root_hooks.hook_exec.fetch(root, NULL)))
 1010: 					root->root_ret = schedCall(task);
 1011: 			}
 1012: 		else
 1013: 			/* trigger scheduler loop */
 1014: 			while (!*killState && root && root->root_hooks.hook_exec.fetch) {
 1015: 				if ((task = root->root_hooks.hook_exec.fetch(root, NULL)))
 1016: 					root->root_ret = schedCall(task);
 1017: 			}
 1018: 	} else
 1019: 		/* infinite scheduler loop */
 1020: 		while (root && root->root_hooks.hook_exec.fetch)
 1021: 			if ((task = root->root_hooks.hook_exec.fetch(root, NULL)))
 1022: 				root->root_ret = schedCall(task);
 1023: 
 1024: 	return 0;
 1025: }
 1026: 
 1027: /*
 1028:  * schedPolling() - Polling timeout period if no timer task is present
 1029:  *
 1030:  * @root = root task
 1031:  * @ts = timeout polling period, if ==NULL INFINIT timeout
 1032:  * @tsold = old timeout polling if !=NULL
 1033:  * return: -1 error or 0 ok
 1034:  */
 1035: int
 1036: schedPolling(sched_root_task_t * __restrict root, struct timespec * __restrict ts, 
 1037: 		struct timespec * __restrict tsold)
 1038: {
 1039: 	if (!root)
 1040: 		return -1;
 1041: 
 1042: 	if (tsold)
 1043: 		*tsold = root->root_poll;
 1044: 
 1045: 	if (!ts)
 1046: 		sched_timespecinf(&root->root_poll);
 1047: 	else
 1048: 		root->root_poll = *ts;
 1049: 
 1050: 	return 0;
 1051: }
 1052: 
 1053: /*
 1054:  * schedTermCondition() - Activate hook for scheduler condition kill
 1055:  *
 1056:  * @root = root task
 1057:  * @condValue = condition value, kill schedRun() if condValue == killState
 1058:  * return: -1 error or 0 ok
 1059:  */
 1060: int
 1061: schedTermCondition(sched_root_task_t * __restrict root, intptr_t * __restrict condValue)
 1062: {
 1063: 	if (!root && !condValue)
 1064: 		return -1;
 1065: 
 1066: 	*root->root_cond = *condValue;
 1067: 	root->root_hooks.hook_exec.condition = sched_hook_condition;
 1068: 	return 0;
 1069: }
 1070: 
 1071: /*
 1072:  * schedResumeby() - Resume suspended task
 1073:  *
 1074:  * @root = root task
 1075:  * @criteria = find task by criteria 
 1076:  * 	[CRITERIA_ANY|CRITERIA_ID|CRITERIA_VAL|CRITERIA_DATA]
 1077:  * @param = search parameter (sched_task_t *task| unsigned long id)
 1078:  * return: -1 error or 0 resumed ok
 1079:  */
 1080: int
 1081: schedResumeby(sched_root_task_t * __restrict root, u_char criteria, void *param)
 1082: {
 1083: 	sched_task_t *task, *tmp;
 1084: 	register int flg = 0;
 1085: 
 1086: 	if (!root)
 1087: 		return -1;
 1088: 
 1089: 	SCHED_QLOCK(root, taskSUSPEND);
 1090: 	TAILQ_FOREACH_SAFE(task, &root->root_suspend, task_node, tmp) {
 1091: 		flg ^= flg;
 1092: 		switch (criteria) {
 1093: 			case CRITERIA_ANY:
 1094: 				flg = 1;
 1095: 				break;
 1096: 			case CRITERIA_ID:
 1097: 			case CRITERIA_VAL:
 1098: 				if (TASK_VAL(task) == (u_long) param)
 1099: 					flg = 1;
 1100: 				break;
 1101: 			case CRITERIA_DATA:
 1102: 				if (TASK_ID(task) == (sched_task_t*) param)
 1103: 					flg = 1;
 1104: 				break;
 1105: 			default:
 1106: 				sched_SetErr(EINVAL, "Invalid parameter criteria %d", criteria);
 1107: 				flg = -1;
 1108: 		}
 1109: 		if (flg < 0)
 1110: 			break;
 1111: 		/* resume choosen task */
 1112: 		if (flg > 0) {
 1113: 			if (root->root_hooks.hook_exec.resume)
 1114: 				if (root->root_hooks.hook_exec.resume(task, NULL)) {
 1115: 					flg = -1;
 1116: 					break;
 1117: 				}
 1118: 
 1119: 			TAILQ_REMOVE(&root->root_suspend, task, task_node);
 1120: 
 1121: 			task->task_type = taskREADY;
 1122: 			insert_task_to(task, &root->root_ready);
 1123: 
 1124: 			flg ^= flg;	/* ok */
 1125: 		}
 1126: 	}
 1127: 	SCHED_QUNLOCK(root, taskSUSPEND);
 1128: 
 1129: 	return flg;
 1130: }
 1131: 
 1132: static void *
 1133: _sched_sigDisp(void *arg)
 1134: {
 1135: 	sched_root_task_t *root = arg;
 1136: 	sched_task_t *task, *tmp;
 1137: 	int sig, flg;
 1138: 	sigset_t ss;
 1139: 
 1140: 	sigfillset(&ss);
 1141: 	while (root->root_sigthr) {
 1142: 		if (sigwait(&ss, &sig))
 1143: 			continue;
 1144: 
 1145: 		pthread_mutex_lock(&root->root_sigmtx);
 1146: 		if (!sigismember(&root->root_sigset, sig)) {
 1147: 			pthread_mutex_unlock(&root->root_sigmtx);
 1148: 			continue;
 1149: 		}
 1150: 
 1151: 		flg = 0;
 1152: 		TAILQ_FOREACH_SAFE(task, &root->root_signal, task_node, tmp) {
 1153: 			if (TASK_VAL(task) == (uintptr_t) sig) {
 1154: 				if (!flg) {
 1155: 					TASK_RET(task) = 0;
 1156: 					TASK_FLAG(task) = 0;
 1157: 
 1158: 					/* remove signal handle */
 1159: 					transit_task2ready(task, &root->root_signal);
 1160: 				}
 1161: 				flg++;
 1162: 			}
 1163: 		}
 1164: 		if (flg < 2)
 1165: 			sigdelset(&root->root_sigset, sig);
 1166: 
 1167: 		pthread_mutex_unlock(&root->root_sigmtx);
 1168: 	}
 1169: 
 1170: 	return NULL;
 1171: }
 1172: 
 1173: /*
 1174:  * schedSignalDispatch() - Activate or Deactivate signal dispatcher
 1175:  *
 1176:  * @root = root task
 1177:  * @on = Activate or =0 deactivate
 1178:  * return: -1 error or 0 ok
 1179:  */
 1180: int
 1181: schedSignalDispatch(sched_root_task_t * __restrict root, int on)
 1182: {
 1183: 	sigset_t ss;
 1184: #ifndef HAVE_LIBPTHREAD
 1185: 	sched_SetErr(ENOTSUP, "Library has not support pthreads");
 1186: 	return -1;
 1187: #else
 1188: 	pthread_attr_t attr;
 1189: #endif
 1190: 
 1191: #if SUP_ENABLE == KQ_SUPPORT
 1192: 	return 0;
 1193: #endif
 1194: 
 1195: 	if (!on) {
 1196: 		pthread_cancel(root->root_sigthr);
 1197: #ifdef __linux__
 1198: 		root->root_sigthr = 0L;
 1199: #else
 1200: 		root->root_sigthr = NULL;
 1201: #endif
 1202: 		pthread_sigmask(SIG_SETMASK, &root->root_oldset, NULL);
 1203: 
 1204: 		pthread_mutex_unlock(&root->root_sigmtx);
 1205: 		return 0;
 1206: 	}
 1207: 
 1208: 	pthread_attr_init(&attr);
 1209: 	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 1210: #ifdef SCHED_RR
 1211: 	pthread_attr_setschedpolicy(&attr, SCHED_RR);
 1212: #else
 1213: 	pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
 1214: #endif
 1215: 
 1216: 	sigfillset(&ss);
 1217: 	pthread_sigmask(SIG_BLOCK, &ss, &root->root_oldset);
 1218: 	if (pthread_create(&root->root_sigthr, &attr, _sched_sigDisp, root)) {
 1219: 		sched_SetErr(errno, "pthread_create(SignalDispatch) #%d - %s", 
 1220: 				errno, strerror(errno));
 1221: #ifdef __linux__
 1222: 		root->root_sigthr = 0L;
 1223: #else
 1224: 		root->root_sigthr = NULL;
 1225: #endif
 1226: 		pthread_sigmask(SIG_SETMASK, &root->root_oldset, NULL);
 1227: 		return -1;
 1228: 	}
 1229: 
 1230: 	return 0;
 1231: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>