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