File:  [ELWIX - Embedded LightWeight unIX -] / libaitsched / src / aitsched.c
Revision 1.9.2.2: download - view: text, annotated - select for diffs - revision graph
Thu May 31 21:36:40 2012 UTC (12 years, 4 months ago) by misho
Branches: sched2_2
Diff to: branchpoint 1.9: preferred, unified
PATCH & FIX libaitsched !!!!
very ugly and tricky BUG in cancel hook. It caused unfree task if they not related with kevent
properly free schedCancel when it did copied from another task

    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.9.2.2 2012/05/31 21:36:40 misho Exp $
    7: *
    8: **************************************************************************
    9: The ELWIX and AITNET software is distributed under the following
   10: terms:
   11: 
   12: All of the documentation and software included in the ELWIX and AITNET
   13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
   14: 
   15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
   16: 	by Michael Pounov <misho@elwix.org>.  All rights reserved.
   17: 
   18: Redistribution and use in source and binary forms, with or without
   19: modification, are permitted provided that the following conditions
   20: are met:
   21: 1. Redistributions of source code must retain the above copyright
   22:    notice, this list of conditions and the following disclaimer.
   23: 2. Redistributions in binary form must reproduce the above copyright
   24:    notice, this list of conditions and the following disclaimer in the
   25:    documentation and/or other materials provided with the distribution.
   26: 3. All advertising materials mentioning features or use of this software
   27:    must display the following acknowledgement:
   28: This product includes software developed by Michael Pounov <misho@elwix.org>
   29: ELWIX - Embedded LightWeight unIX and its contributors.
   30: 4. Neither the name of AITNET nor the names of its contributors
   31:    may be used to endorse or promote products derived from this software
   32:    without specific prior written permission.
   33: 
   34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
   35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   37: ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   44: SUCH DAMAGE.
   45: */
   46: #include "global.h"
   47: #include "hooks.h"
   48: 
   49: 
   50: #pragma GCC visibility push(hidden)
   51: 
   52: int sched_Errno;
   53: char sched_Error[STRSIZ];
   54: 
   55: #pragma GCC visibility pop
   56: 
   57: 
   58: // sched_GetErrno() Get error code of last operation
   59: inline int
   60: sched_GetErrno()
   61: {
   62: 	return sched_Errno;
   63: }
   64: 
   65: // sched_GetError() Get error text of last operation
   66: inline const char *
   67: sched_GetError()
   68: {
   69: 	return sched_Error;
   70: }
   71: 
   72: // sched_SetErr() Set error to variables for internal use!!!
   73: inline void
   74: sched_SetErr(int eno, char *estr, ...)
   75: {
   76: 	va_list lst;
   77: 
   78: 	sched_Errno = eno;
   79: 	memset(sched_Error, 0, sizeof sched_Error);
   80: 	va_start(lst, estr);
   81: 	vsnprintf(sched_Error, sizeof sched_Error, estr, lst);
   82: 	va_end(lst);
   83: }
   84: 
   85: /* Init and prepare scheduler functions */
   86: 
   87: /*
   88:  * schedRegisterHooks() - Register IO handles and bind tasks to it
   89:  *
   90:  * @root = root task
   91:  * return: -1 error or 0 ok
   92:  */
   93: int
   94: schedRegisterHooks(sched_root_task_t * __restrict root)
   95: {
   96: 	assert(root);
   97: 
   98: 	if (root->root_hooks.hook_root.fini)
   99: 		root->root_hooks.hook_root.fini(root, NULL);
  100: 	memset(&root->root_hooks, 0, sizeof root->root_hooks);
  101: 
  102: 	root->root_hooks.hook_add.read = sched_hook_read;
  103: 	root->root_hooks.hook_add.write = sched_hook_write;
  104: 	root->root_hooks.hook_add.alarm = sched_hook_alarm;
  105: 	root->root_hooks.hook_add.node = sched_hook_node;
  106: 	root->root_hooks.hook_add.proc = sched_hook_proc;
  107: 	root->root_hooks.hook_add.user = sched_hook_user;
  108: 	root->root_hooks.hook_add.signal = sched_hook_signal;
  109: 
  110: 	root->root_hooks.hook_exec.cancel = sched_hook_cancel;
  111: 	root->root_hooks.hook_exec.fetch = sched_hook_fetch;
  112: 	root->root_hooks.hook_exec.exception = sched_hook_exception;
  113: 
  114: 	root->root_hooks.hook_root.init = sched_hook_init;
  115: 	root->root_hooks.hook_root.fini = sched_hook_fini;
  116: 	return 0;
  117: }
  118: 
  119: /*
  120:  * schedInit() - Init scheduler
  121:  *
  122:  * @data = optional data if !=NULL
  123:  * @datlen = data len if data is set
  124:  * return: allocated root task if ok or NULL error
  125:  */
  126: sched_root_task_t *
  127: schedInit(void ** __restrict data, size_t datlen)
  128: {
  129: 	sched_root_task_t *root = NULL;
  130: 	int (*func)(sched_root_task_t *);
  131: #ifdef HAVE_LIBPTHREAD
  132: 	register int i;
  133: #endif
  134: 
  135: 	root = malloc(sizeof(sched_root_task_t));
  136: 	if (!root) {
  137: 		LOGERR;
  138: 	} else {
  139: 		memset(root, 0, sizeof(sched_root_task_t));
  140: 
  141: 		/* INFINIT polling period by default */
  142: 		sched_timespecinf(&root->root_poll);
  143: 
  144: #ifdef HAVE_LIBPTHREAD
  145: 		for (i = 0; i < taskMAX; i++)
  146: 			if (pthread_mutex_init(&root->root_mtx[i], NULL)) {
  147: 				LOGERR;
  148: 				while (i)
  149: 					pthread_mutex_destroy(&root->root_mtx[--i]);
  150: 				free(root);
  151: 				return NULL;
  152: 			}
  153: 
  154: 		for (i = 0; i < taskMAX; i++)
  155: 			pthread_mutex_lock(&root->root_mtx[i]);
  156: #endif
  157: 
  158: 		TAILQ_INIT(&root->root_read);
  159: 		TAILQ_INIT(&root->root_write);
  160: 		TAILQ_INIT(&root->root_timer);
  161: 		TAILQ_INIT(&root->root_alarm);
  162: 		TAILQ_INIT(&root->root_node);
  163: 		TAILQ_INIT(&root->root_proc);
  164: 		TAILQ_INIT(&root->root_user);
  165: 		TAILQ_INIT(&root->root_signal);
  166: 		TAILQ_INIT(&root->root_event);
  167: 		TAILQ_INIT(&root->root_eventlo);
  168: 		TAILQ_INIT(&root->root_ready);
  169: 		TAILQ_INIT(&root->root_unuse);
  170: 
  171: #ifdef HAVE_LIBPTHREAD
  172: 		for (i = 0; i < taskMAX; i++)
  173: 			pthread_mutex_unlock(&root->root_mtx[i]);
  174: #endif
  175: 
  176: 		if (data && *data) {
  177: 			if (datlen) {
  178: 				root->root_data.iov_base = *data;
  179: 				root->root_data.iov_len = datlen;
  180: 			} else { /* if datlen == 0, switch to callbacks init mode */
  181: 				 /* little hack :) for correct initialization of scheduler */
  182: 				func = (int(*)(sched_root_task_t*)) data;
  183: 				func(root);
  184: 			}
  185: 		}
  186: 
  187: 		if (root->root_hooks.hook_root.init)
  188: 			root->root_hooks.hook_root.init(root, NULL);
  189: 	}
  190: 
  191: 	return root;
  192: }
  193: 
  194: /*
  195:  * schedEnd() - End scheduler & free all resources
  196:  *
  197:  * @root = root task
  198:  * return: -1 error or 0 ok
  199:  */
  200: int
  201: schedEnd(sched_root_task_t ** __restrict root)
  202: {
  203: 	sched_task_t *task, *tmp;
  204: #ifdef HAVE_LIBPTHREAD
  205: 	register int i;
  206: #endif
  207: 
  208: 	if (!root || !*root)
  209: 		return -1;
  210: 
  211: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_read, task_node, tmp)
  212: 		schedCancel(task);
  213: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_write, task_node, tmp)
  214: 		schedCancel(task);
  215: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_timer, task_node, tmp)
  216: 		schedCancel(task);
  217: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_alarm, task_node, tmp)
  218: 		schedCancel(task);
  219: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_node, task_node, tmp)
  220: 		schedCancel(task);
  221: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_proc, task_node, tmp)
  222: 		schedCancel(task);
  223: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_user, task_node, tmp)
  224: 		schedCancel(task);
  225: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_signal, task_node, tmp)
  226: 		schedCancel(task);
  227: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_event, task_node, tmp)
  228: 		schedCancel(task);
  229: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_eventlo, task_node, tmp)
  230: 		schedCancel(task);
  231: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_ready, task_node, tmp)
  232: 		schedCancel(task);
  233: 
  234: #ifdef HAVE_LIBPTHREAD
  235: 	pthread_mutex_lock(&(*root)->root_mtx[taskUNUSE]);
  236: #endif
  237: 	TAILQ_FOREACH_SAFE(task, &(*root)->root_unuse, task_node, tmp) {
  238: 		TAILQ_REMOVE(&(*root)->root_unuse, task, task_node);
  239: 		free(task);
  240: 	}
  241: #ifdef HAVE_LIBPTHREAD
  242: 	pthread_mutex_unlock(&(*root)->root_mtx[taskUNUSE]);
  243: #endif
  244: 
  245: 	if ((*root)->root_hooks.hook_root.fini)
  246: 		(*root)->root_hooks.hook_root.fini(*root, NULL);
  247: 
  248: #ifdef HAVE_LIBPTHREAD
  249: 	for (i = 0; i < taskMAX; i++)
  250: 		pthread_mutex_destroy(&(*root)->root_mtx[i]);
  251: #endif
  252: 
  253: 	free(*root);
  254: 	*root = NULL;
  255: 	return 0;
  256: }
  257: 
  258: /*
  259:  * schedCall() - Call task execution function
  260:  *
  261:  * @task = current task
  262:  * return: !=NULL error or =NULL ok
  263:  */
  264: inline void *
  265: schedCall(sched_task_t * __restrict task)
  266: {
  267: 	void *ptr = (void*) -1;
  268: 
  269: 	if (!task)
  270: 		return ptr;
  271: 
  272: 	if (!TASK_ISLOCKED(task))
  273: 		TASK_LOCK(task);
  274: 
  275: 	ptr = task->task_func(task);
  276: 
  277: 	TASK_UNLOCK(task);
  278: 	return ptr;
  279: }
  280: 
  281: /*
  282:  * schedFetch() - Fetch ready task
  283:  *
  284:  * @root = root task
  285:  * return: =NULL error or !=NULL ready task
  286:  */
  287: inline void *
  288: schedFetch(sched_root_task_t * __restrict root)
  289: {
  290: 	void *ptr;
  291: 
  292: 	if (!root)
  293: 		return NULL;
  294: 
  295: 	if (root->root_hooks.hook_exec.fetch)
  296: 		ptr = root->root_hooks.hook_exec.fetch(root, NULL);
  297: 	else
  298: 		ptr = NULL;
  299: 
  300: 	return ptr;
  301: }
  302: 
  303: /*
  304:  * schedTrigger() - Triggering USER task
  305:  *
  306:  * @task = task
  307:  * return: -1 error or 0 ok
  308:  */
  309: int
  310: schedTrigger(sched_task_t * __restrict task)
  311: {
  312: 	struct kevent chg[1];
  313: 	struct timespec timeout = { 0, 0 };
  314: 
  315: 	if (!task || !TASK_ROOT(task))
  316: 		return -1;
  317: 
  318: #ifdef __NetBSD__
  319: 	EV_SET(chg, TASK_VAL(task), EVFILT_USER, 0, NOTE_TRIGGER, 0, (intptr_t) TASK_VAL(task));
  320: #else
  321: 	EV_SET(chg, TASK_VAL(task), EVFILT_USER, 0, NOTE_TRIGGER, 0, (void*) TASK_VAL(task));
  322: #endif
  323: 	if (kevent(TASK_ROOT(task)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
  324: 		LOGERR;
  325: 		return -1;
  326: 	}
  327: 
  328: 	return 0;
  329: }
  330: 
  331: /*
  332:  * schedCancel() - Cancel task from scheduler
  333:  *
  334:  * @task = task
  335:  * return: -1 error or 0 ok
  336:  */
  337: int
  338: schedCancel(sched_task_t * __restrict task)
  339: {
  340: 	sched_queue_t *queue;
  341: 
  342: 	if (!task || !TASK_ROOT(task))
  343: 		return -1;
  344: 
  345: 	if (TASK_ROOT(task)->root_hooks.hook_exec.cancel)
  346: 		if (TASK_ROOT(task)->root_hooks.hook_exec.cancel(task, NULL))
  347: 			return -1;
  348: 
  349: 	switch (TASK_TYPE(task)) {
  350: 		case taskREAD:
  351: 			queue = &TASK_ROOT(task)->root_read;
  352: 			break;
  353: 		case taskWRITE:
  354: 			queue = &TASK_ROOT(task)->root_write;
  355: 			break;
  356: 		case taskTIMER:
  357: 			queue = &TASK_ROOT(task)->root_timer;
  358: 			break;
  359: 		case taskALARM:
  360: 			queue = &TASK_ROOT(task)->root_alarm;
  361: 			break;
  362: 		case taskNODE:
  363: 			queue = &TASK_ROOT(task)->root_node;
  364: 			break;
  365: 		case taskPROC:
  366: 			queue = &TASK_ROOT(task)->root_proc;
  367: 			break;
  368: 		case taskUSER:
  369: 			queue = &TASK_ROOT(task)->root_user;
  370: 			break;
  371: 		case taskSIGNAL:
  372: 			queue = &TASK_ROOT(task)->root_signal;
  373: 			break;
  374: 		case taskEVENT:
  375: 			queue = &TASK_ROOT(task)->root_event;
  376: 			break;
  377: 		case taskEVENTLO:
  378: 			queue = &TASK_ROOT(task)->root_eventlo;
  379: 			break;
  380: 		case taskREADY:
  381: 			queue = &TASK_ROOT(task)->root_ready;
  382: 			break;
  383: 		default:
  384: 			queue = NULL;
  385: 	}
  386: 	if (queue) {
  387: #ifdef HAVE_LIBPTHREAD
  388: 		pthread_mutex_lock(&TASK_ROOT(task)->root_mtx[TASK_TYPE(task)]);
  389: #endif
  390: 		TAILQ_REMOVE(queue, TASK_ID(task), task_node);
  391: #ifdef HAVE_LIBPTHREAD
  392: 		pthread_mutex_unlock(&TASK_ROOT(task)->root_mtx[TASK_TYPE(task)]);
  393: #endif
  394: 	}
  395: 	if (TASK_TYPE(task) != taskUNUSE)
  396: 		_sched_unuseTask(task);
  397: 
  398: 	return 0;
  399: }
  400: 
  401: /*
  402:  * schedCancelby() - Cancel task from scheduler by criteria
  403:  *
  404:  * @root = root task
  405:  * @type = cancel from queue type, if =taskMAX cancel same task from all queues
  406:  * @criteria = find task by criteria 
  407:  * 	[CRITERIA_ANY|CRITERIA_CALL|CRITERIA_ARG|CRITERIA_FD|CRITERIA_VAL|CRITERIA_TS|CRITERIA_DATA]
  408:  * @param = search parameter
  409:  * @hook = custom cleanup hook function, may be NULL
  410:  * return: -1 error, -2 error in sub-stage cancel execution, -3 error from custom hook or 0 ok
  411:  */
  412: int
  413: schedCancelby(sched_root_task_t * __restrict root, sched_task_type_t type, 
  414: 		u_char criteria, void *param, sched_hook_func_t hook)
  415: {
  416: 	sched_task_t *task, *tmp;
  417: 	sched_queue_t *queue;
  418: 	register int flg = 0;
  419: 
  420: 	if (!root)
  421: 		return -1;
  422: 	/* if type == taskMAX check in all queues */
  423: 	if (type == taskMAX) {
  424: 		if (schedCancelby(root, taskREAD, criteria, param, hook))
  425: 			return -2;
  426: 		if (schedCancelby(root, taskWRITE, criteria, param, hook))
  427: 			return -2;
  428: 		if (schedCancelby(root, taskTIMER, criteria, param, hook))
  429: 			return -2;
  430: 		if (schedCancelby(root, taskALARM, criteria, param, hook))
  431: 			return -2;
  432: 		if (schedCancelby(root, taskNODE, criteria, param, hook))
  433: 			return -2;
  434: 		if (schedCancelby(root, taskPROC, criteria, param, hook))
  435: 			return -2;
  436: 		if (schedCancelby(root, taskUSER, criteria, param, hook))
  437: 			return -2;
  438: 		if (schedCancelby(root, taskSIGNAL, criteria, param, hook))
  439: 			return -2;
  440: 		if (schedCancelby(root, taskEVENT, criteria, param, hook))
  441: 			return -2;
  442: 		if (schedCancelby(root, taskEVENTLO, criteria, param, hook))
  443: 			return -2;
  444: 		if (schedCancelby(root, taskREADY, criteria, param, hook))
  445: 			return -2;
  446: 		return 0;
  447: 	}
  448: 	/* choosen queue */
  449: 	switch (type) {
  450: 		case taskREAD:
  451: 			queue = &root->root_read;
  452: 			break;
  453: 		case taskWRITE:
  454: 			queue = &root->root_write;
  455: 			break;
  456: 		case taskTIMER:
  457: 			queue = &root->root_timer;
  458: 			break;
  459: 		case taskALARM:
  460: 			queue = &root->root_alarm;
  461: 			break;
  462: 		case taskNODE:
  463: 			queue = &root->root_node;
  464: 			break;
  465: 		case taskPROC:
  466: 			queue = &root->root_proc;
  467: 			break;
  468: 		case taskUSER:
  469: 			queue = &root->root_user;
  470: 			break;
  471: 		case taskSIGNAL:
  472: 			queue = &root->root_signal;
  473: 			break;
  474: 		case taskEVENT:
  475: 			queue = &root->root_event;
  476: 			break;
  477: 		case taskEVENTLO:
  478: 			queue = &root->root_eventlo;
  479: 			break;
  480: 		case taskREADY:
  481: 			queue = &root->root_ready;
  482: 			break;
  483: 		default:
  484: 			return 0;
  485: 	}
  486: 
  487: #ifdef HAVE_LIBPTHREAD
  488: 	pthread_mutex_lock(&root->root_mtx[type]);
  489: #endif
  490: 	TAILQ_FOREACH_SAFE(task, queue, task_node, tmp) {
  491: 		flg ^= flg;
  492: 		switch (criteria) {
  493: 			case CRITERIA_ANY:
  494: 				flg = 1;
  495: 				break;
  496: 			case CRITERIA_CALL:
  497: 				if (TASK_FUNC(task) == (sched_task_func_t) param)
  498: 					flg = 1;
  499: 				break;
  500: 			case CRITERIA_ARG:
  501: 				if (TASK_ARG(task) == param)
  502: 					flg = 1;
  503: 				break;
  504: 			case CRITERIA_FD:
  505: 				if (TASK_FD(task) == (intptr_t) param)
  506: 					flg = 1;
  507: 				break;
  508: 			case CRITERIA_VAL:
  509: 				if (TASK_VAL(task) == (u_long) param)
  510: 					flg = 1;
  511: 				break;
  512: 			case CRITERIA_TS:
  513: 				if (!sched_timespeccmp(&TASK_TS(task), (struct timespec*) param, -))
  514: 					flg = 1;
  515: 				break;
  516: 			case CRITERIA_DATA:
  517: 				if (TASK_DATA(task) == param)
  518: 					flg = 1;
  519: 				break;
  520: 			default:
  521: 				sched_SetErr(EINVAL, "Invalid parameter criteria %d", criteria);
  522: 				flg = -1;
  523: 		}
  524: 		if (flg < 0)		/* error */
  525: 			break;
  526: 		/* cancel choosen task */
  527: 		if (flg > 0) {
  528: 			if (TASK_ROOT(task)->root_hooks.hook_exec.cancel)
  529: 				if (TASK_ROOT(task)->root_hooks.hook_exec.cancel(task, NULL)) {
  530: 					flg = -1;
  531: 					break;
  532: 				}
  533: 			/* custom hook */
  534: 			if (hook)
  535: 				if (hook(task, NULL)) {
  536: 					flg = -3;
  537: 					break;
  538: 				}
  539: 
  540: 			TAILQ_REMOVE(queue, task, task_node);
  541: 			if (TASK_TYPE(task) != taskUNUSE)
  542: 				_sched_unuseTask(task);
  543: 
  544: 			flg ^= flg;	/* ok */
  545: 		}
  546: 	}
  547: #ifdef HAVE_LIBPTHREAD
  548: 	pthread_mutex_unlock(&root->root_mtx[type]);
  549: #endif
  550: 	return flg;
  551: }
  552: 
  553: /*
  554:  * schedRun() - Scheduler *run loop*
  555:  *
  556:  * @root = root task
  557:  * @killState = kill condition variable, if !=0 stop scheduler loop
  558:  * return: -1 error or 0 ok
  559:  */
  560: int
  561: schedRun(sched_root_task_t *root, volatile intptr_t * __restrict killState)
  562: {
  563: 	sched_task_t *task;
  564: 
  565: 	if (!root)
  566: 		return -1;
  567: 
  568: 	if (root->root_hooks.hook_exec.run)
  569: 		if (root->root_hooks.hook_exec.run(root, NULL))
  570: 			return -1;
  571: 
  572: 	if (killState) {
  573: 		if (root->root_hooks.hook_exec.condition)
  574: 			/* condition scheduler loop */
  575: 			while (root && root->root_hooks.hook_exec.fetch && 
  576: 					root->root_hooks.hook_exec.condition && 
  577: 					root->root_hooks.hook_exec.condition(root, (void*) killState)) {
  578: 				if ((task = root->root_hooks.hook_exec.fetch(root, NULL)))
  579: 					schedCall(task);
  580: 			}
  581: 		else
  582: 			/* trigger scheduler loop */
  583: 			while (!*killState && root && root->root_hooks.hook_exec.fetch) {
  584: 				if ((task = root->root_hooks.hook_exec.fetch(root, NULL)))
  585: 					schedCall(task);
  586: 			}
  587: 	} else
  588: 		/* infinite scheduler loop */
  589: 		while (root && root->root_hooks.hook_exec.fetch)
  590: 			if ((task = root->root_hooks.hook_exec.fetch(root, NULL)))
  591: 				schedCall(task);
  592: 
  593: 	return 0;
  594: }
  595: 
  596: /*
  597:  * schedPolling() - Polling timeout period if no timer task is present
  598:  *
  599:  * @root = root task
  600:  * @ts = timeout polling period, if ==NULL INFINIT timeout
  601:  * @tsold = old timeout polling if !=NULL
  602:  * return: -1 error or 0 ok
  603:  */
  604: inline int
  605: schedPolling(sched_root_task_t * __restrict root, struct timespec * __restrict ts, 
  606: 		struct timespec * __restrict tsold)
  607: {
  608: 	if (!root)
  609: 		return -1;
  610: 
  611: 	if (tsold)
  612: 		*tsold = root->root_poll;
  613: 
  614: 	if (!ts)
  615: 		sched_timespecinf(&root->root_poll);
  616: 	else
  617: 		root->root_poll = *ts;
  618: 
  619: 	return 0;
  620: }
  621: 
  622: /*
  623:  * schedTermCondition() - Activate hook for scheduler condition kill
  624:  *
  625:  * @root = root task
  626:  * @condValue = condition value, kill schedRun() if condValue == killState
  627:  * return: -1 error ok 0 ok
  628:  */
  629: inline int
  630: schedTermCondition(sched_root_task_t * __restrict root, intptr_t condValue)
  631: {
  632: 	if (!root)
  633: 		return -1;
  634: 
  635: 	root->root_cond = condValue;
  636: 	root->root_hooks.hook_exec.condition = sched_hook_condition;
  637: 	return 0;
  638: }

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