Annotation of libaitsched/src/tasks.c, revision 1.4
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.4 ! misho 6: * $Id: tasks.c,v 1.3.2.1 2011/12/08 09:17:34 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:
15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
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:
1.4 ! misho 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;
! 55:
! 56: TAILQ_FOREACH(task, &root->root_unuse, task_node) {
! 57: if (!TASK_ISLOCKED(task)) {
! 58: TAILQ_REMOVE(&root->root_unuse, task, task_node);
! 59: break;
! 60: }
! 61: }
! 62:
! 63: if (!task) {
! 64: task = malloc(sizeof(sched_task_t));
! 65: if (!task) {
! 66: LOGERR;
! 67: return NULL;
! 68: }
! 69: }
! 70:
! 71: return task;
! 72: }
! 73:
! 74: inline sched_task_t *
! 75: _sched_unuseTask(sched_task_t * __restrict task)
! 76: {
! 77: TASK_UNLOCK(task);
! 78: task->task_type = taskUNUSE;
! 79: TAILQ_INSERT_TAIL(&task->task_root->root_unuse, task, task_node);
! 80: task = NULL;
! 81:
! 82: return task;
! 83: }
! 84:
! 85: #pragma GCC visibility pop
! 86:
! 87:
1.1 misho 88: /*
1.2 misho 89: * schedRead() - Add READ I/O task to scheduler queue
1.1 misho 90: * @root = root task
91: * @func = task execution function
92: * @arg = 1st func argument
1.2 misho 93: * @fd = fd handle
1.1 misho 94: * return: NULL error or !=NULL new queued task
95: */
96: sched_task_t *
1.2 misho 97: schedRead(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd)
1.1 misho 98: {
99: sched_task_t *task;
100: void *ptr;
101:
102: if (!root || !func)
103: return NULL;
104:
105: /* get new task */
1.4 ! misho 106: if (!(task = _sched_useTask(root)))
! 107: return NULL;
1.1 misho 108:
109: memset(task, 0, sizeof(sched_task_t));
110: task->task_id = 0;
1.4 ! misho 111: task->task_lock = 0;
1.1 misho 112: task->task_type = taskREAD;
113: task->task_root = root;
114: task->task_func = func;
115:
116: TASK_ARG(task) = arg;
1.2 misho 117: TASK_FD(task) = fd;
1.1 misho 118:
119: if (root->root_hooks.hook_add.read)
120: ptr = root->root_hooks.hook_add.read(task, NULL);
121: else
122: ptr = NULL;
123:
124: if (!ptr)
125: TAILQ_INSERT_TAIL(&root->root_read, task, task_node);
1.4 ! misho 126: else
! 127: task = _sched_unuseTask(task);
1.1 misho 128:
129: return task;
130: }
131:
132: /*
1.2 misho 133: * schedWrite() - Add WRITE I/O task to scheduler queue
1.1 misho 134: * @root = root task
135: * @func = task execution function
136: * @arg = 1st func argument
1.2 misho 137: * @fd = fd handle
1.1 misho 138: * return: NULL error or !=NULL new queued task
139: */
140: sched_task_t *
1.2 misho 141: schedWrite(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, int fd)
1.1 misho 142: {
143: sched_task_t *task;
144: void *ptr;
145:
146: if (!root || !func)
147: return NULL;
148:
149: /* get new task */
1.4 ! misho 150: if (!(task = _sched_useTask(root)))
! 151: return NULL;
1.1 misho 152:
153: memset(task, 0, sizeof(sched_task_t));
154: task->task_id = 0;
1.4 ! misho 155: task->task_lock = 0;
1.1 misho 156: task->task_type = taskWRITE;
157: task->task_root = root;
158: task->task_func = func;
159:
160: TASK_ARG(task) = arg;
1.2 misho 161: TASK_FD(task) = fd;
1.1 misho 162:
163: if (root->root_hooks.hook_add.write)
164: ptr = root->root_hooks.hook_add.write(task, NULL);
165: else
166: ptr = NULL;
167:
168: if (!ptr)
169: TAILQ_INSERT_TAIL(&root->root_write, task, task_node);
1.4 ! misho 170: else
! 171: task = _sched_unuseTask(task);
1.1 misho 172:
173: return task;
174: }
175:
176: /*
177: * schedTimer() - Add TIMER task to scheduler queue
178: * @root = root task
179: * @func = task execution function
180: * @arg = 1st func argument
1.3 misho 181: * @tv = timeout argument structure
1.1 misho 182: * return: NULL error or !=NULL new queued task
183: */
184: sched_task_t *
1.3 misho 185: schedTimer(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, struct timeval tv)
1.1 misho 186: {
187: sched_task_t *task, *t = NULL;
188: void *ptr;
189: struct timeval now;
190: struct timespec nw;
191:
192: if (!root || !func)
193: return NULL;
194:
195: /* get new task */
1.4 ! misho 196: if (!(task = _sched_useTask(root)))
! 197: return NULL;
1.1 misho 198:
199: memset(task, 0, sizeof(sched_task_t));
200: task->task_id = 0;
1.4 ! misho 201: task->task_lock = 0;
1.1 misho 202: task->task_type = taskTIMER;
203: task->task_root = root;
204: task->task_func = func;
205:
206: TASK_ARG(task) = arg;
207:
208: /* calculate timeval structure */
209: clock_gettime(CLOCK_MONOTONIC, &nw);
1.3 misho 210: now.tv_sec = nw.tv_sec + tv.tv_sec;
211: now.tv_usec = nw.tv_nsec / 1000 + tv.tv_usec;
1.1 misho 212: if (now.tv_usec >= 1000000) {
213: now.tv_sec++;
214: now.tv_usec -= 1000000;
215: } else if (now.tv_usec < 0) {
216: now.tv_sec--;
217: now.tv_usec += 1000000;
218: }
219: TASK_TV(task) = now;
220:
221: if (root->root_hooks.hook_add.timer)
222: ptr = root->root_hooks.hook_add.timer(task, NULL);
223: else
224: ptr = NULL;
225:
226: if (!ptr) {
227: #ifdef TIMER_WITHOUT_SORT
228: TAILQ_INSERT_TAIL(&root->root_timer, task, task_node);
229: #else
230: TAILQ_FOREACH(t, &root->root_timer, task_node)
231: if (timercmp(&TASK_TV(task), &TASK_TV(t), -) < 1)
232: break;
233: if (!t)
234: TAILQ_INSERT_TAIL(&root->root_timer, task, task_node);
235: else
236: TAILQ_INSERT_BEFORE(t, task, task_node);
237: #endif
1.4 ! misho 238: } else
! 239: task = _sched_unuseTask(task);
1.1 misho 240:
241: return task;
242: }
243:
244: /*
245: * schedEvent() - Add EVENT task to scheduler queue
246: * @root = root task
247: * @func = task execution function
248: * @arg = 1st func argument
1.2 misho 249: * @val = additional func argument
1.1 misho 250: * return: NULL error or !=NULL new queued task
251: */
252: sched_task_t *
1.2 misho 253: schedEvent(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, u_long val)
1.1 misho 254: {
255: sched_task_t *task;
256: void *ptr;
257:
258: if (!root || !func)
259: return NULL;
260:
261: /* get new task */
1.4 ! misho 262: if (!(task = _sched_useTask(root)))
! 263: return NULL;
1.1 misho 264:
265: memset(task, 0, sizeof(sched_task_t));
266: task->task_id = 0;
1.4 ! misho 267: task->task_lock = 0;
1.1 misho 268: task->task_type = taskEVENT;
269: task->task_root = root;
270: task->task_func = func;
271:
272: TASK_ARG(task) = arg;
1.2 misho 273: TASK_VAL(task) = val;
1.1 misho 274:
275: if (root->root_hooks.hook_add.event)
276: ptr = root->root_hooks.hook_add.event(task, NULL);
277: else
278: ptr = NULL;
279:
280: if (!ptr)
281: TAILQ_INSERT_TAIL(&root->root_event, task, task_node);
1.4 ! misho 282: else
! 283: task = _sched_unuseTask(task);
1.1 misho 284:
285: return task;
286: }
287:
288:
289: /*
290: * schedEventLo() - Add EVENT_Lo task to scheduler queue
291: * @root = root task
292: * @func = task execution function
293: * @arg = 1st func argument
1.2 misho 294: * @val = additional func argument
1.1 misho 295: * return: NULL error or !=NULL new queued task
296: */
297: sched_task_t *
1.2 misho 298: schedEventLo(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, u_long val)
1.1 misho 299: {
300: sched_task_t *task;
301: void *ptr;
302:
303: if (!root || !func)
304: return NULL;
305:
306: /* get new task */
1.4 ! misho 307: if (!(task = _sched_useTask(root)))
! 308: return NULL;
1.1 misho 309:
310: memset(task, 0, sizeof(sched_task_t));
311: task->task_id = 0;
1.4 ! misho 312: task->task_lock = 0;
1.1 misho 313: task->task_type = taskEVENT;
314: task->task_root = root;
315: task->task_func = func;
316:
317: TASK_ARG(task) = arg;
1.2 misho 318: TASK_VAL(task) = val;
1.1 misho 319:
320: if (root->root_hooks.hook_add.eventlo)
321: ptr = root->root_hooks.hook_add.eventlo(task, NULL);
322: else
323: ptr = NULL;
324:
325: if (!ptr)
326: TAILQ_INSERT_TAIL(&root->root_eventlo, task, task_node);
1.4 ! misho 327: else
! 328: task = _sched_unuseTask(task);
1.1 misho 329:
330: return task;
331: }
332:
333: /*
334: * schedCallOnce() - Call once from scheduler
335: * @root = root task
336: * @func = task execution function
337: * @arg = 1st func argument
1.2 misho 338: * @val = additional func argument
339: * return: return value from called func
1.1 misho 340: */
341: sched_task_t *
1.2 misho 342: schedCallOnce(sched_root_task_t * __restrict root, sched_task_func_t func, void *arg, u_long val)
1.1 misho 343: {
344: sched_task_t *task;
1.2 misho 345: void *ret;
1.1 misho 346:
347: if (!root || !func)
348: return NULL;
349:
350: /* get new task */
1.4 ! misho 351: if (!(task = _sched_useTask(root)))
! 352: return NULL;
1.1 misho 353:
354: memset(task, 0, sizeof(sched_task_t));
355: task->task_id = 0;
1.4 ! misho 356: task->task_lock = 0;
1.1 misho 357: task->task_type = taskEVENT;
358: task->task_root = root;
359: task->task_func = func;
360:
361: TASK_ARG(task) = arg;
1.2 misho 362: TASK_VAL(task) = val;
1.1 misho 363:
1.2 misho 364: ret = schedCall(task);
1.1 misho 365:
1.4 ! misho 366: _sched_unuseTask(task);
1.2 misho 367: return ret;
1.1 misho 368: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>