File:  [ELWIX - Embedded LightWeight unIX -] / libaitsched / src / tasks.c
Revision 1.8.2.3: 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.8: 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: tasks.c,v 1.8.2.3 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: 
   48: 
   49: #pragma GCC visibility push(hidden)
   50: 
   51: inline sched_task_t *
   52: _sched_useTask(sched_root_task_t * __restrict root)
   53: {
   54: 	sched_task_t *task, *tmp;
   55: 
   56: 	TAILQ_FOREACH_SAFE(task, &root->root_unuse, task_node, tmp) {
   57: 		if (!TASK_ISLOCKED(task)) {
   58: #ifdef HAVE_LIBPTHREAD
   59: 			pthread_mutex_lock(&root->root_mtx[taskUNUSE]);
   60: #endif
   61: 			TAILQ_REMOVE(&root->root_unuse, task, task_node);
   62: #ifdef HAVE_LIBPTHREAD
   63: 			pthread_mutex_unlock(&root->root_mtx[taskUNUSE]);
   64: #endif
   65: 			break;
   66: 		}
   67: 	}
   68: 
   69: 	if (!task) {
   70: 		task = malloc(sizeof(sched_task_t));
   71: 		if (!task) {
   72: 			LOGERR;
   73: 			return NULL;
   74: 		}
   75: 	}
   76: 
   77: 	memset(task, 0, sizeof(sched_task_t));
   78: 	task->task_id = (uintptr_t) task;
   79: 	return task;
   80: }
   81: 
   82: inline sched_task_t *
   83: _sched_unuseTask(sched_task_t * __restrict task)
   84: {
   85: 	TASK_UNLOCK(task);
   86: 	TASK_TYPE(task) = taskUNUSE;
   87: #ifdef HAVE_LIBPTHREAD
   88: 	pthread_mutex_lock(&TASK_ROOT(task)->root_mtx[taskUNUSE]);
   89: #endif
   90: 	TAILQ_INSERT_TAIL(&TASK_ROOT(task)->root_unuse, TASK_ID(task), task_node);
   91: #ifdef HAVE_LIBPTHREAD
   92: 	pthread_mutex_unlock(&TASK_ROOT(task)->root_mtx[taskUNUSE]);
   93: #endif
   94: 	task = NULL;
   95: 
   96: 	return task;
   97: }
   98: 
   99: #pragma GCC visibility pop
  100: 
  101: 
  102: /*
  103:  * schedRead() - Add READ I/O task to scheduler queue
  104:  *
  105:  * @root = root task
  106:  * @func = task execution function
  107:  * @arg = 1st func argument
  108:  * @fd = fd handle
  109:  * @opt_data = Optional data
  110:  * @opt_dlen = Optional data length
  111:  * return: NULL error or !=NULL new queued task
  112:  */
  113: sched_task_t *
  114: schedRead(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd, 
  115: 		void *opt_data, size_t opt_dlen)
  116: {
  117: 	sched_task_t *task;
  118: 	void *ptr;
  119: 
  120: 	if (!root || !func)
  121: 		return NULL;
  122: 
  123: 	/* get new task */
  124: 	if (!(task = _sched_useTask(root)))
  125: 		return NULL;
  126: 
  127: 	task->task_func = func;
  128: 	TASK_TYPE(task) = taskREAD;
  129: 	TASK_ROOT(task) = root;
  130: 
  131: 	TASK_ARG(task) = arg;
  132: 	TASK_FD(task) = fd;
  133: 
  134: 	TASK_DATA(task) = opt_data;
  135: 	TASK_DATLEN(task) = opt_dlen;
  136: 
  137: 	if (root->root_hooks.hook_add.read)
  138: 		ptr = root->root_hooks.hook_add.read(task, NULL);
  139: 	else
  140: 		ptr = NULL;
  141: 
  142: 	if (!ptr) {
  143: #ifdef HAVE_LIBPTHREAD
  144: 		pthread_mutex_lock(&root->root_mtx[taskREAD]);
  145: #endif
  146: 		TAILQ_INSERT_TAIL(&root->root_read, TASK_ID(task), task_node);
  147: #ifdef HAVE_LIBPTHREAD
  148: 		pthread_mutex_unlock(&root->root_mtx[taskREAD]);
  149: #endif
  150: 	} else
  151: 		task = _sched_unuseTask(task);
  152: 
  153: 	return task;
  154: }
  155: 
  156: /*
  157:  * schedWrite() - Add WRITE I/O task to scheduler queue
  158:  *
  159:  * @root = root task
  160:  * @func = task execution function
  161:  * @arg = 1st func argument
  162:  * @fd = fd handle
  163:  * @opt_data = Optional data
  164:  * @opt_dlen = Optional data length
  165:  * return: NULL error or !=NULL new queued task
  166:  */
  167: sched_task_t *
  168: schedWrite(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd, 
  169: 		void *opt_data, size_t opt_dlen)
  170: {
  171: 	sched_task_t *task;
  172: 	void *ptr;
  173: 
  174: 	if (!root || !func)
  175: 		return NULL;
  176: 
  177: 	/* get new task */
  178: 	if (!(task = _sched_useTask(root)))
  179: 		return NULL;
  180: 
  181: 	task->task_func = func;
  182: 	TASK_TYPE(task) = taskWRITE;
  183: 	TASK_ROOT(task) = root;
  184: 
  185: 	TASK_ARG(task) = arg;
  186: 	TASK_FD(task) = fd;
  187: 
  188: 	TASK_DATA(task) = opt_data;
  189: 	TASK_DATLEN(task) = opt_dlen;
  190: 
  191: 	if (root->root_hooks.hook_add.write)
  192: 		ptr = root->root_hooks.hook_add.write(task, NULL);
  193: 	else
  194: 		ptr = NULL;
  195: 
  196: 	if (!ptr) {
  197: #ifdef HAVE_LIBPTHREAD
  198: 		pthread_mutex_lock(&root->root_mtx[taskWRITE]);
  199: #endif
  200: 		TAILQ_INSERT_TAIL(&root->root_write, TASK_ID(task), task_node);
  201: #ifdef HAVE_LIBPTHREAD
  202: 		pthread_mutex_unlock(&root->root_mtx[taskWRITE]);
  203: #endif
  204: 	} else
  205: 		task = _sched_unuseTask(task);
  206: 
  207: 	return task;
  208: }
  209: 
  210: /*
  211:  * schedNode() - Add NODE task to scheduler queue
  212:  *
  213:  * @root = root task
  214:  * @func = task execution function
  215:  * @arg = 1st func argument
  216:  * @fd = fd handle
  217:  * @opt_data = Optional data
  218:  * @opt_dlen = Optional data length
  219:  * return: NULL error or !=NULL new queued task
  220:  */
  221: sched_task_t *
  222: schedNode(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd, 
  223: 		void *opt_data, size_t opt_dlen)
  224: {
  225: 	sched_task_t *task;
  226: 	void *ptr;
  227: 
  228: 	if (!root || !func)
  229: 		return NULL;
  230: 
  231: 	/* get new task */
  232: 	if (!(task = _sched_useTask(root)))
  233: 		return NULL;
  234: 
  235: 	task->task_func = func;
  236: 	TASK_TYPE(task) = taskNODE;
  237: 	TASK_ROOT(task) = root;
  238: 
  239: 	TASK_ARG(task) = arg;
  240: 	TASK_FD(task) = fd;
  241: 
  242: 	TASK_DATA(task) = opt_data;
  243: 	TASK_DATLEN(task) = opt_dlen;
  244: 
  245: 	if (root->root_hooks.hook_add.node)
  246: 		ptr = root->root_hooks.hook_add.node(task, NULL);
  247: 	else
  248: 		ptr = NULL;
  249: 
  250: 	if (!ptr) {
  251: #ifdef HAVE_LIBPTHREAD
  252: 		pthread_mutex_lock(&root->root_mtx[taskNODE]);
  253: #endif
  254: 		TAILQ_INSERT_TAIL(&root->root_node, TASK_ID(task), task_node);
  255: #ifdef HAVE_LIBPTHREAD
  256: 		pthread_mutex_unlock(&root->root_mtx[taskNODE]);
  257: #endif
  258: 	} else
  259: 		task = _sched_unuseTask(task);
  260: 
  261: 	return task;
  262: }
  263: 
  264: /*
  265:  * schedProc() - Add PROC task to scheduler queue
  266:  *
  267:  * @root = root task
  268:  * @func = task execution function
  269:  * @arg = 1st func argument
  270:  * @pid = PID
  271:  * @opt_data = Optional data
  272:  * @opt_dlen = Optional data length
  273:  * return: NULL error or !=NULL new queued task
  274:  */
  275: sched_task_t *
  276: schedProc(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, u_long pid, 
  277: 		void *opt_data, size_t opt_dlen)
  278: {
  279: 	sched_task_t *task;
  280: 	void *ptr;
  281: 
  282: 	if (!root || !func)
  283: 		return NULL;
  284: 
  285: 	/* get new task */
  286: 	if (!(task = _sched_useTask(root)))
  287: 		return NULL;
  288: 
  289: 	task->task_func = func;
  290: 	TASK_TYPE(task) = taskPROC;
  291: 	TASK_ROOT(task) = root;
  292: 
  293: 	TASK_ARG(task) = arg;
  294: 	TASK_VAL(task) = pid;
  295: 
  296: 	TASK_DATA(task) = opt_data;
  297: 	TASK_DATLEN(task) = opt_dlen;
  298: 
  299: 	if (root->root_hooks.hook_add.proc)
  300: 		ptr = root->root_hooks.hook_add.proc(task, NULL);
  301: 	else
  302: 		ptr = NULL;
  303: 
  304: 	if (!ptr) {
  305: #ifdef HAVE_LIBPTHREAD
  306: 		pthread_mutex_lock(&root->root_mtx[taskPROC]);
  307: #endif
  308: 		TAILQ_INSERT_TAIL(&root->root_proc, TASK_ID(task), task_node);
  309: #ifdef HAVE_LIBPTHREAD
  310: 		pthread_mutex_unlock(&root->root_mtx[taskPROC]);
  311: #endif
  312: 	} else
  313: 		task = _sched_unuseTask(task);
  314: 
  315: 	return task;
  316: }
  317: 
  318: /*
  319:  * schedUser() - Add trigger USER task to scheduler queue
  320:  *
  321:  * @root = root task
  322:  * @func = task execution function
  323:  * @arg = 1st func argument
  324:  * @id = Trigger ID
  325:  * @opt_data = Optional data
  326:  * @opt_dlen = Optional user's trigger flags
  327:  * return: NULL error or !=NULL new queued task
  328:  */
  329: sched_task_t *
  330: schedUser(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, u_long id, 
  331: 		void *opt_data, size_t opt_dlen)
  332: {
  333: 	sched_task_t *task;
  334: 	void *ptr;
  335: 
  336: 	if (!root || !func)
  337: 		return NULL;
  338: 
  339: 	/* get new task */
  340: 	if (!(task = _sched_useTask(root)))
  341: 		return NULL;
  342: 
  343: 	task->task_func = func;
  344: 	TASK_TYPE(task) = taskUSER;
  345: 	TASK_ROOT(task) = root;
  346: 
  347: 	TASK_ARG(task) = arg;
  348: 	TASK_VAL(task) = id;
  349: 
  350: 	TASK_DATA(task) = opt_data;
  351: 	TASK_DATLEN(task) = opt_dlen;
  352: 
  353: 	if (root->root_hooks.hook_add.user)
  354: 		ptr = root->root_hooks.hook_add.user(task, NULL);
  355: 	else
  356: 		ptr = NULL;
  357: 
  358: 	if (!ptr) {
  359: #ifdef HAVE_LIBPTHREAD
  360: 		pthread_mutex_lock(&root->root_mtx[taskUSER]);
  361: #endif
  362: 		TAILQ_INSERT_TAIL(&root->root_user, TASK_ID(task), task_node);
  363: #ifdef HAVE_LIBPTHREAD
  364: 		pthread_mutex_unlock(&root->root_mtx[taskUSER]);
  365: #endif
  366: 	} else
  367: 		task = _sched_unuseTask(task);
  368: 
  369: 	return task;
  370: }
  371: 
  372: /*
  373:  * schedSignal() - Add SIGNAL task to scheduler queue
  374:  *
  375:  * @root = root task
  376:  * @func = task execution function
  377:  * @arg = 1st func argument
  378:  * @sig = Signal
  379:  * @opt_data = Optional data
  380:  * @opt_dlen = Optional data length
  381:  * return: NULL error or !=NULL new queued task
  382:  */
  383: sched_task_t *
  384: schedSignal(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, u_long sig, 
  385: 		void *opt_data, size_t opt_dlen)
  386: {
  387: 	sched_task_t *task;
  388: 	void *ptr;
  389: 
  390: 	if (!root || !func)
  391: 		return NULL;
  392: 
  393: 	/* get new task */
  394: 	if (!(task = _sched_useTask(root)))
  395: 		return NULL;
  396: 
  397: 	task->task_func = func;
  398: 	TASK_TYPE(task) = taskSIGNAL;
  399: 	TASK_ROOT(task) = root;
  400: 
  401: 	TASK_ARG(task) = arg;
  402: 	TASK_VAL(task) = sig;
  403: 
  404: 	TASK_DATA(task) = opt_data;
  405: 	TASK_DATLEN(task) = opt_dlen;
  406: 
  407: 	if (root->root_hooks.hook_add.signal)
  408: 		ptr = root->root_hooks.hook_add.signal(task, NULL);
  409: 	else
  410: 		ptr = NULL;
  411: 
  412: 	if (!ptr) {
  413: #ifdef HAVE_LIBPTHREAD
  414: 		pthread_mutex_lock(&root->root_mtx[taskSIGNAL]);
  415: #endif
  416: 		TAILQ_INSERT_TAIL(&root->root_signal, TASK_ID(task), task_node);
  417: #ifdef HAVE_LIBPTHREAD
  418: 		pthread_mutex_unlock(&root->root_mtx[taskSIGNAL]);
  419: #endif
  420: 	} else
  421: 		task = _sched_unuseTask(task);
  422: 
  423: 	return task;
  424: }
  425: 
  426: /*
  427:  * schedAlarm() - Add ALARM task to scheduler queue
  428:  *
  429:  * @root = root task
  430:  * @func = task execution function
  431:  * @arg = 1st func argument
  432:  * @ts = timeout argument structure, minimum alarm timer resolution is 1msec!
  433:  * @opt_data = Optional data
  434:  * @opt_dlen = Optional data length
  435:  * return: NULL error or !=NULL new queued task
  436:  */
  437: sched_task_t *
  438: schedAlarm(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, struct timespec ts, 
  439: 		void *opt_data, size_t opt_dlen)
  440: {
  441: 	sched_task_t *task;
  442: 	void *ptr;
  443: 
  444: 	if (!root || !func)
  445: 		return NULL;
  446: 
  447: 	/* get new task */
  448: 	if (!(task = _sched_useTask(root)))
  449: 		return NULL;
  450: 
  451: 	task->task_func = func;
  452: 	TASK_TYPE(task) = taskALARM;
  453: 	TASK_ROOT(task) = root;
  454: 
  455: 	TASK_ARG(task) = arg;
  456: 	TASK_TS(task) = ts;
  457: 
  458: 	TASK_DATA(task) = opt_data;
  459: 	TASK_DATLEN(task) = opt_dlen;
  460: 
  461: 	if (root->root_hooks.hook_add.alarm)
  462: 		ptr = root->root_hooks.hook_add.alarm(task, NULL);
  463: 	else
  464: 		ptr = NULL;
  465: 
  466: 	if (!ptr) {
  467: #ifdef HAVE_LIBPTHREAD
  468: 		pthread_mutex_lock(&root->root_mtx[taskALARM]);
  469: #endif
  470: 		TAILQ_INSERT_TAIL(&root->root_alarm, TASK_ID(task), task_node);
  471: #ifdef HAVE_LIBPTHREAD
  472: 		pthread_mutex_unlock(&root->root_mtx[taskALARM]);
  473: #endif
  474: 	} else
  475: 		task = _sched_unuseTask(task);
  476: 
  477: 	return task;
  478: }
  479: 
  480: /*
  481:  * schedTimer() - Add TIMER task to scheduler queue
  482:  *
  483:  * @root = root task
  484:  * @func = task execution function
  485:  * @arg = 1st func argument
  486:  * @ts = timeout argument structure
  487:  * @opt_data = Optional data
  488:  * @opt_dlen = Optional data length
  489:  * return: NULL error or !=NULL new queued task
  490:  */
  491: sched_task_t *
  492: schedTimer(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, struct timespec ts, 
  493: 		void *opt_data, size_t opt_dlen)
  494: {
  495: 	sched_task_t *task, *tmp, *t = NULL;
  496: 	void *ptr;
  497: 	struct timespec now;
  498: 
  499: 	if (!root || !func)
  500: 		return NULL;
  501: 
  502: 	/* get new task */
  503: 	if (!(task = _sched_useTask(root)))
  504: 		return NULL;
  505: 
  506: 	task->task_func = func;
  507: 	TASK_TYPE(task) = taskTIMER;
  508: 	TASK_ROOT(task) = root;
  509: 
  510: 	TASK_ARG(task) = arg;
  511: 
  512: 	TASK_DATA(task) = opt_data;
  513: 	TASK_DATLEN(task) = opt_dlen;
  514: 
  515: 	/* calculate timeval structure */
  516: 	clock_gettime(CLOCK_MONOTONIC, &now);
  517: 	now.tv_sec += ts.tv_sec;
  518: 	now.tv_nsec += ts.tv_nsec;
  519: 	if (now.tv_nsec >= 1000000000L) {
  520: 		now.tv_sec++;
  521: 		now.tv_nsec -= 1000000000L;
  522: 	} else if (now.tv_nsec < 0) {
  523: 		now.tv_sec--;
  524: 		now.tv_nsec += 1000000000L;
  525: 	}
  526: 	TASK_TS(task) = now;
  527: 
  528: 	if (root->root_hooks.hook_add.timer)
  529: 		ptr = root->root_hooks.hook_add.timer(task, NULL);
  530: 	else
  531: 		ptr = NULL;
  532: 
  533: 	if (!ptr) {
  534: #ifdef HAVE_LIBPTHREAD
  535: 		pthread_mutex_lock(&root->root_mtx[taskTIMER]);
  536: #endif
  537: #ifdef TIMER_WITHOUT_SORT
  538: 		TAILQ_INSERT_TAIL(&root->root_timer, TASK_ID(task), task_node);
  539: #else
  540: 		TAILQ_FOREACH_SAFE(t, &root->root_timer, task_node, tmp)
  541: 			if (sched_timespeccmp(&TASK_TS(task), &TASK_TS(t), -) < 1)
  542: 				break;
  543: 		if (!t)
  544: 			TAILQ_INSERT_TAIL(&root->root_timer, TASK_ID(task), task_node);
  545: 		else
  546: 			TAILQ_INSERT_BEFORE(t, TASK_ID(task), task_node);
  547: #endif
  548: #ifdef HAVE_LIBPTHREAD
  549: 		pthread_mutex_unlock(&root->root_mtx[taskTIMER]);
  550: #endif
  551: 	} else
  552: 		task = _sched_unuseTask(task);
  553: 
  554: 	return task;
  555: }
  556: 
  557: /*
  558:  * schedEvent() - Add EVENT task to scheduler queue
  559:  *
  560:  * @root = root task
  561:  * @func = task execution function
  562:  * @arg = 1st func argument
  563:  * @val = additional func argument
  564:  * @opt_data = Optional data
  565:  * @opt_dlen = Optional data length
  566:  * return: NULL error or !=NULL new queued task
  567:  */
  568: sched_task_t *
  569: schedEvent(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, u_long val, 
  570: 		void *opt_data, size_t opt_dlen)
  571: {
  572: 	sched_task_t *task;
  573: 	void *ptr;
  574: 
  575: 	if (!root || !func)
  576: 		return NULL;
  577: 
  578: 	/* get new task */
  579: 	if (!(task = _sched_useTask(root)))
  580: 		return NULL;
  581: 
  582: 	task->task_func = func;
  583: 	TASK_TYPE(task) = taskEVENT;
  584: 	TASK_ROOT(task) = root;
  585: 
  586: 	TASK_ARG(task) = arg;
  587: 	TASK_VAL(task) = val;
  588: 
  589: 	TASK_DATA(task) = opt_data;
  590: 	TASK_DATLEN(task) = opt_dlen;
  591: 
  592: 	if (root->root_hooks.hook_add.event)
  593: 		ptr = root->root_hooks.hook_add.event(task, NULL);
  594: 	else
  595: 		ptr = NULL;
  596: 
  597: 	if (!ptr) {
  598: #ifdef HAVE_LIBPTHREAD
  599: 		pthread_mutex_lock(&root->root_mtx[taskEVENT]);
  600: #endif
  601: 		TAILQ_INSERT_TAIL(&root->root_event, TASK_ID(task), task_node);
  602: #ifdef HAVE_LIBPTHREAD
  603: 		pthread_mutex_unlock(&root->root_mtx[taskEVENT]);
  604: #endif
  605: 	} else
  606: 		task = _sched_unuseTask(task);
  607: 
  608: 	return task;
  609: }
  610: 
  611: 
  612: /*
  613:  * schedEventLo() - Add EVENT_Lo task to scheduler queue
  614:  *
  615:  * @root = root task
  616:  * @func = task execution function
  617:  * @arg = 1st func argument
  618:  * @val = additional func argument
  619:  * @opt_data = Optional data
  620:  * @opt_dlen = Optional data length
  621:  * return: NULL error or !=NULL new queued task
  622:  */
  623: sched_task_t *
  624: schedEventLo(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, u_long val, 
  625: 		void *opt_data, size_t opt_dlen)
  626: {
  627: 	sched_task_t *task;
  628: 	void *ptr;
  629: 
  630: 	if (!root || !func)
  631: 		return NULL;
  632: 
  633: 	/* get new task */
  634: 	if (!(task = _sched_useTask(root)))
  635: 		return NULL;
  636: 
  637: 	task->task_func = func;
  638: 	TASK_TYPE(task) = taskEVENT;
  639: 	TASK_ROOT(task) = root;
  640: 
  641: 	TASK_ARG(task) = arg;
  642: 	TASK_VAL(task) = val;
  643: 
  644: 	TASK_DATA(task) = opt_data;
  645: 	TASK_DATLEN(task) = opt_dlen;
  646: 
  647: 	if (root->root_hooks.hook_add.eventlo)
  648: 		ptr = root->root_hooks.hook_add.eventlo(task, NULL);
  649: 	else
  650: 		ptr = NULL;
  651: 
  652: 	if (!ptr) {
  653: #ifdef HAVE_LIBPTHREAD
  654: 		pthread_mutex_lock(&root->root_mtx[taskEVENTLO]);
  655: #endif
  656: 		TAILQ_INSERT_TAIL(&root->root_eventlo, TASK_ID(task), task_node);
  657: #ifdef HAVE_LIBPTHREAD
  658: 		pthread_mutex_unlock(&root->root_mtx[taskEVENTLO]);
  659: #endif
  660: 	} else
  661: 		task = _sched_unuseTask(task);
  662: 
  663: 	return task;
  664: }
  665: 
  666: /*
  667:  * schedCallOnce() - Call once from scheduler
  668:  *
  669:  * @root = root task
  670:  * @func = task execution function
  671:  * @arg = 1st func argument
  672:  * @val = additional func argument
  673:  * @opt_data = Optional data
  674:  * @opt_dlen = Optional data length
  675:  * return: return value from called func
  676:  */
  677: sched_task_t *
  678: schedCallOnce(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, u_long val, 
  679: 		void *opt_data, size_t opt_dlen)
  680: {
  681: 	sched_task_t *task;
  682: 	void *ret;
  683: 
  684: 	if (!root || !func)
  685: 		return NULL;
  686: 
  687: 	/* get new task */
  688: 	if (!(task = _sched_useTask(root)))
  689: 		return NULL;
  690: 
  691: 	task->task_func = func;
  692: 	TASK_TYPE(task) = taskEVENT;
  693: 	TASK_ROOT(task) = root;
  694: 
  695: 	TASK_ARG(task) = arg;
  696: 	TASK_VAL(task) = val;
  697: 
  698: 	TASK_DATA(task) = opt_data;
  699: 	TASK_DATLEN(task) = opt_dlen;
  700: 
  701: 	ret = schedCall(task);
  702: 
  703: 	_sched_unuseTask(task);
  704: 	return ret;
  705: }

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