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