Annotation of libaitsched/src/hooks.c, revision 1.14.2.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.14.2.4! misho 6: * $Id: hooks.c,v 1.14.2.3 2012/08/22 23:43:36 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:
1.5 misho 15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
1.1 misho 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: /*
51: * sched_hook_init() - Default INIT hook
1.5 misho 52: *
1.1 misho 53: * @root = root task
1.6 misho 54: * @arg = unused
1.1 misho 55: * return: <0 errors and 0 ok
56: */
57: void *
1.6 misho 58: sched_hook_init(void *root, void *arg __unused)
1.1 misho 59: {
60: sched_root_task_t *r = root;
61:
1.6 misho 62: if (!r)
1.1 misho 63: return (void*) -1;
64:
65: r->root_kq = kqueue();
66: if (r->root_kq == -1) {
67: LOGERR;
68: return (void*) -1;
69: }
70:
71: return NULL;
72: }
73:
74: /*
75: * sched_hook_fini() - Default FINI hook
1.5 misho 76: *
1.1 misho 77: * @root = root task
78: * @arg = unused
79: * return: <0 errors and 0 ok
80: */
81: void *
82: sched_hook_fini(void *root, void *arg __unused)
83: {
84: sched_root_task_t *r = root;
85:
86: if (!r)
87: return (void*) -1;
88:
89: if (r->root_kq > 2) {
90: close(r->root_kq);
91: r->root_kq = 0;
92: }
93:
94: return NULL;
95: }
96:
97: /*
98: * sched_hook_cancel() - Default CANCEL hook
1.5 misho 99: *
1.1 misho 100: * @task = current task
101: * @arg = unused
102: * return: <0 errors and 0 ok
103: */
104: void *
105: sched_hook_cancel(void *task, void *arg __unused)
106: {
107: sched_task_t *t = task;
108: struct kevent chg[1];
1.2 misho 109: struct timespec timeout = { 0, 0 };
1.14.2.4! misho 110: register int i = 0;
1.11 misho 111: #ifdef AIO_SUPPORT
112: struct aiocb *acb;
113: #ifdef EVFILT_LIO
114: struct aiocb **acbs;
115: #endif /* EVFILT_LIO */
116: #endif /* AIO_SUPPORT */
1.1 misho 117:
1.6 misho 118: if (!t || !TASK_ROOT(t))
1.1 misho 119: return (void*) -1;
120:
1.4 misho 121: switch (TASK_TYPE(t)) {
1.1 misho 122: case taskREAD:
1.2 misho 123: #ifdef __NetBSD__
124: EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_DELETE, 0, 0, (intptr_t) TASK_FD(t));
125: #else
126: EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_DELETE, 0, 0, (void*) TASK_FD(t));
127: #endif
1.1 misho 128: break;
129: case taskWRITE:
1.2 misho 130: #ifdef __NetBSD__
131: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_DELETE, 0, 0, (intptr_t) TASK_FD(t));
132: #else
133: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_DELETE, 0, 0, (void*) TASK_FD(t));
134: #endif
1.1 misho 135: break;
1.7 misho 136: case taskALARM:
137: #ifdef __NetBSD__
138: EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_DELETE,
139: 0, 0, (intptr_t) TASK_DATA(t));
140: #else
141: EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_DELETE,
142: 0, 0, (void*) TASK_DATA(t));
143: #endif
1.8 misho 144: break;
145: case taskNODE:
146: #ifdef __NetBSD__
147: EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_DELETE, 0, 0, (intptr_t) TASK_FD(t));
148: #else
149: EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_DELETE, 0, 0, (void*) TASK_FD(t));
150: #endif
151: break;
152: case taskPROC:
153: #ifdef __NetBSD__
154: EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));
155: #else
156: EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_DELETE, 0, 0, (void*) TASK_VAL(t));
157: #endif
158: break;
159: case taskSIGNAL:
160: #ifdef __NetBSD__
161: EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));
162: #else
163: EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_DELETE, 0, 0, (void*) TASK_VAL(t));
164: #endif
165: break;
1.11 misho 166: #ifdef AIO_SUPPORT
167: case taskAIO:
168: #ifdef __NetBSD__
169: EV_SET(&chg[0], TASK_VAL(t), EVFILT_AIO, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));
170: #else
171: EV_SET(&chg[0], TASK_VAL(t), EVFILT_AIO, EV_DELETE, 0, 0, (void*) TASK_VAL(t));
172: #endif
173: acb = (struct aiocb*) TASK_VAL(t);
174: if (acb) {
175: if (aio_cancel(acb->aio_fildes, acb) == AIO_CANCELED)
176: aio_return(acb);
177: free(acb);
178: TASK_VAL(t) = 0;
179: }
180: break;
181: #ifdef EVFILT_LIO
182: case taskLIO:
183: #ifdef __NetBSD__
184: EV_SET(&chg[0], TASK_VAL(t), EVFILT_LIO, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));
185: #else
186: EV_SET(&chg[0], TASK_VAL(t), EVFILT_LIO, EV_DELETE, 0, 0, (void*) TASK_VAL(t));
187: #endif
188: acbs = (struct aiocb**) TASK_VAL(t);
189: if (acbs) {
190: for (i = 0; i < TASK_DATLEN(t); i++) {
191: if (aio_cancel(acbs[i]->aio_fildes, acbs[i]) == AIO_CANCELED)
192: aio_return(acbs[i]);
193: free(acbs[i]);
194: }
195: free(acbs);
196: TASK_VAL(t) = 0;
197: }
198: break;
199: #endif /* EVFILT_LIO */
200: #endif /* AIO_SUPPORT */
1.8 misho 201: #ifdef EVFILT_USER
202: case taskUSER:
203: #ifdef __NetBSD__
204: EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));
205: #else
206: EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_DELETE, 0, 0, (void*) TASK_VAL(t));
207: #endif
1.10 misho 208: break;
1.8 misho 209: #endif
1.14 misho 210: case taskTHREAD:
211: #ifdef HAVE_LIBPTHREAD
1.14.2.3 misho 212: /* try to wait for valid thread id */
213: for (i = 0; i < MAX_TASK_MISS &&
214: pthread_kill((pthread_t) TASK_VAL(t), 0); i++)
215: usleep(10);
216: /* try to sure thread is cancelled */
217: for (i = 0; i < MAX_TASK_MISS &&
218: !pthread_kill((pthread_t) TASK_VAL(t), 0); i++)
219: pthread_cancel((pthread_t) TASK_VAL(t));
1.14.2.1 misho 220: if (TASK_FLAG(t) == PTHREAD_CREATE_JOINABLE) /* joinable thread */
221: schedTask(TASK_ROOT(t), _sched_threadJoin, TASK_ARG(t),
222: TASK_VAL(t), TASK_DATA(t), TASK_DATLEN(t));
1.14 misho 223: #endif
224: TASK_UNLOCK(t);
1.1 misho 225: default:
1.8 misho 226: return NULL;
1.1 misho 227: }
228:
1.8 misho 229: kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout);
1.1 misho 230: return NULL;
231: }
232:
1.14 misho 233: #ifdef HAVE_LIBPTHREAD
234: /*
235: * sched_hook_thread() - Default THREAD hook
236: *
237: * @task = current task
238: * @arg = pthread attributes
239: * return: <0 errors and 0 ok
240: */
241: void *
242: sched_hook_thread(void *task, void *arg)
243: {
244: sched_task_t *t = task;
245: pthread_t tid;
1.14.2.2 misho 246: sigset_t ns, os;
1.14 misho 247:
248: if (!t || !TASK_ROOT(t))
249: return (void*) -1;
250:
1.14.2.2 misho 251: sigfillset(&ns);
252: pthread_sigmask(SIG_BLOCK, &ns, &os);
1.14 misho 253: if (pthread_create(&tid, (pthread_attr_t*) arg,
254: (void *(*)(void*)) TASK_FUNC(t), t)) {
255: LOGERR;
1.14.2.2 misho 256: pthread_sigmask(SIG_SETMASK, &os, NULL);
1.14 misho 257: return (void*) -1;
258: }
259:
260: if (!TASK_ISLOCKED(t))
261: TASK_LOCK(t);
262:
263: TASK_VAL(t) = (u_long) tid;
1.14.2.3 misho 264: pthread_sigmask(SIG_SETMASK, &os, NULL);
1.14 misho 265: return NULL;
266: }
267: #endif
268:
1.1 misho 269: /*
270: * sched_hook_read() - Default READ hook
1.5 misho 271: *
1.1 misho 272: * @task = current task
273: * @arg = unused
274: * return: <0 errors and 0 ok
275: */
276: void *
277: sched_hook_read(void *task, void *arg __unused)
278: {
279: sched_task_t *t = task;
280: struct kevent chg[1];
1.2 misho 281: struct timespec timeout = { 0, 0 };
1.1 misho 282:
1.6 misho 283: if (!t || !TASK_ROOT(t))
1.1 misho 284: return (void*) -1;
285:
1.2 misho 286: #ifdef __NetBSD__
1.8 misho 287: EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, (intptr_t) TASK_FD(t));
1.2 misho 288: #else
1.8 misho 289: EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, (void*) TASK_FD(t));
1.2 misho 290: #endif
1.4 misho 291: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
292: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
293: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
1.3 misho 294: else
295: LOGERR;
1.1 misho 296: return (void*) -1;
297: }
298:
299: return NULL;
300: }
301:
302: /*
303: * sched_hook_write() - Default WRITE hook
1.5 misho 304: *
1.1 misho 305: * @task = current task
306: * @arg = unused
307: * return: <0 errors and 0 ok
308: */
309: void *
310: sched_hook_write(void *task, void *arg __unused)
311: {
312: sched_task_t *t = task;
313: struct kevent chg[1];
1.2 misho 314: struct timespec timeout = { 0, 0 };
1.1 misho 315:
1.6 misho 316: if (!t || !TASK_ROOT(t))
1.1 misho 317: return (void*) -1;
318:
1.2 misho 319: #ifdef __NetBSD__
1.8 misho 320: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, (intptr_t) TASK_FD(t));
1.2 misho 321: #else
1.8 misho 322: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, (void*) TASK_FD(t));
1.2 misho 323: #endif
1.4 misho 324: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
325: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
326: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
1.3 misho 327: else
328: LOGERR;
1.1 misho 329: return (void*) -1;
330: }
331:
332: return NULL;
333: }
334:
335: /*
1.7 misho 336: * sched_hook_alarm() - Default ALARM hook
337: *
338: * @task = current task
339: * @arg = unused
340: * return: <0 errors and 0 ok
341: */
342: void *
343: sched_hook_alarm(void *task, void *arg __unused)
344: {
345: sched_task_t *t = task;
346: struct kevent chg[1];
347: struct timespec timeout = { 0, 0 };
348:
349: if (!t || !TASK_ROOT(t))
350: return (void*) -1;
351:
352: #ifdef __NetBSD__
353: EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0,
354: t->task_val.ts.tv_sec * 1000 + t->task_val.ts.tv_nsec / 1000000,
355: (intptr_t) TASK_DATA(t));
356: #else
357: EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0,
358: t->task_val.ts.tv_sec * 1000 + t->task_val.ts.tv_nsec / 1000000,
359: (void*) TASK_DATA(t));
360: #endif
361: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
362: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
363: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
364: else
365: LOGERR;
366: return (void*) -1;
367: }
368:
369: return NULL;
370: }
371:
372: /*
1.8 misho 373: * sched_hook_node() - Default NODE hook
374: *
375: * @task = current task
376: * @arg = unused
377: * return: <0 errors and 0 ok
378: */
379: void *
380: sched_hook_node(void *task, void *arg __unused)
381: {
382: sched_task_t *t = task;
383: struct kevent chg[1];
384: struct timespec timeout = { 0, 0 };
385:
386: if (!t || !TASK_ROOT(t))
387: return (void*) -1;
388:
389: #ifdef __NetBSD__
390: EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_ADD | EV_CLEAR,
391: NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB |
392: NOTE_LINK | NOTE_RENAME | NOTE_REVOKE, 0, (intptr_t) TASK_FD(t));
393: #else
394: EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_ADD | EV_CLEAR,
395: NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB |
396: NOTE_LINK | NOTE_RENAME | NOTE_REVOKE, 0, (void*) TASK_FD(t));
397: #endif
398: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
399: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
400: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
401: else
402: LOGERR;
403: return (void*) -1;
404: }
405:
406: return NULL;
407: }
408:
409: /*
410: * sched_hook_proc() - Default PROC hook
411: *
412: * @task = current task
413: * @arg = unused
414: * return: <0 errors and 0 ok
415: */
416: void *
417: sched_hook_proc(void *task, void *arg __unused)
418: {
419: sched_task_t *t = task;
420: struct kevent chg[1];
421: struct timespec timeout = { 0, 0 };
422:
423: if (!t || !TASK_ROOT(t))
424: return (void*) -1;
425:
426: #ifdef __NetBSD__
427: EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_ADD | EV_CLEAR,
428: NOTE_EXIT | NOTE_FORK | NOTE_EXEC | NOTE_TRACK, 0, (intptr_t) TASK_VAL(t));
429: #else
430: EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_ADD | EV_CLEAR,
431: NOTE_EXIT | NOTE_FORK | NOTE_EXEC | NOTE_TRACK, 0, (void*) TASK_VAL(t));
432: #endif
433: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
434: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
435: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
436: else
437: LOGERR;
438: return (void*) -1;
439: }
440:
441: return NULL;
442: }
443:
444: /*
445: * sched_hook_signal() - Default SIGNAL hook
446: *
447: * @task = current task
448: * @arg = unused
449: * return: <0 errors and 0 ok
450: */
451: void *
452: sched_hook_signal(void *task, void *arg __unused)
453: {
454: sched_task_t *t = task;
455: struct kevent chg[1];
456: struct timespec timeout = { 0, 0 };
457:
458: if (!t || !TASK_ROOT(t))
459: return (void*) -1;
460:
461: #ifdef __NetBSD__
462: EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_ADD, 0, 0, (intptr_t) TASK_VAL(t));
463: #else
464: EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_ADD, 0, 0, (void*) TASK_VAL(t));
465: #endif
466: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
467: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
468: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
469: else
470: LOGERR;
471: return (void*) -1;
472: }
473:
474: return NULL;
475: }
476:
477: /*
478: * sched_hook_user() - Default USER hook
479: *
480: * @task = current task
481: * @arg = unused
482: * return: <0 errors and 0 ok
483: */
484: #ifdef EVFILT_USER
485: void *
486: sched_hook_user(void *task, void *arg __unused)
487: {
488: sched_task_t *t = task;
489: struct kevent chg[1];
490: struct timespec timeout = { 0, 0 };
491:
492: if (!t || !TASK_ROOT(t))
493: return (void*) -1;
494:
495: #ifdef __NetBSD__
496: EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_ADD | EV_CLEAR, TASK_DATLEN(t),
497: 0, (intptr_t) TASK_VAL(t));
498: #else
499: EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_ADD | EV_CLEAR, TASK_DATLEN(t),
500: 0, (void*) TASK_VAL(t));
501: #endif
502: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
503: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
504: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
505: else
506: LOGERR;
507: return (void*) -1;
508: }
509:
510: return NULL;
511: }
512: #endif
513:
514: /*
1.1 misho 515: * sched_hook_fetch() - Default FETCH hook
1.5 misho 516: *
1.1 misho 517: * @root = root task
518: * @arg = unused
519: * return: NULL error or !=NULL fetched task
520: */
521: void *
522: sched_hook_fetch(void *root, void *arg __unused)
523: {
524: sched_root_task_t *r = root;
1.6 misho 525: sched_task_t *task, *tmp;
1.4 misho 526: struct timespec now, m, mtmp;
527: struct timespec *timeout;
1.1 misho 528: struct kevent evt[1], res[KQ_EVENTS];
1.9 misho 529: register int i, flg;
1.1 misho 530: int en;
1.11 misho 531: #ifdef AIO_SUPPORT
532: int len, fd;
533: struct aiocb *acb;
534: #ifdef EVFILT_LIO
535: int l;
536: register int j;
537: off_t off;
538: struct aiocb **acbs;
539: struct iovec *iv;
540: #endif /* EVFILT_LIO */
541: #endif /* AIO_SUPPORT */
1.1 misho 542:
1.6 misho 543: if (!r)
1.1 misho 544: return NULL;
545:
546: /* get new task by queue priority */
547: while ((task = TAILQ_FIRST(&r->root_event))) {
1.4 misho 548: #ifdef HAVE_LIBPTHREAD
549: pthread_mutex_lock(&r->root_mtx[taskEVENT]);
550: #endif
1.1 misho 551: TAILQ_REMOVE(&r->root_event, task, task_node);
1.4 misho 552: #ifdef HAVE_LIBPTHREAD
553: pthread_mutex_unlock(&r->root_mtx[taskEVENT]);
554: #endif
1.1 misho 555: task->task_type = taskUNUSE;
1.4 misho 556: #ifdef HAVE_LIBPTHREAD
557: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
558: #endif
1.1 misho 559: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 560: #ifdef HAVE_LIBPTHREAD
561: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
562: #endif
1.1 misho 563: return task;
564: }
565: while ((task = TAILQ_FIRST(&r->root_ready))) {
1.4 misho 566: #ifdef HAVE_LIBPTHREAD
567: pthread_mutex_lock(&r->root_mtx[taskREADY]);
568: #endif
1.1 misho 569: TAILQ_REMOVE(&r->root_ready, task, task_node);
1.4 misho 570: #ifdef HAVE_LIBPTHREAD
571: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
572: #endif
1.1 misho 573: task->task_type = taskUNUSE;
1.4 misho 574: #ifdef HAVE_LIBPTHREAD
575: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
576: #endif
1.1 misho 577: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 578: #ifdef HAVE_LIBPTHREAD
579: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
580: #endif
1.1 misho 581: return task;
582: }
583:
584: #ifdef TIMER_WITHOUT_SORT
1.4 misho 585: clock_gettime(CLOCK_MONOTONIC, &now);
1.1 misho 586:
1.4 misho 587: sched_timespecclear(&r->root_wait);
1.1 misho 588: TAILQ_FOREACH(task, &r->root_timer, task_node) {
1.4 misho 589: if (!sched_timespecisset(&r->root_wait))
590: r->root_wait = TASK_TS(task);
591: else if (sched_timespeccmp(&TASK_TS(task), &r->root_wait, -) < 0)
592: r->root_wait = TASK_TS(task);
1.1 misho 593: }
594:
595: if (TAILQ_FIRST(&r->root_timer)) {
596: m = r->root_wait;
1.4 misho 597: sched_timespecsub(&m, &now, &mtmp);
1.1 misho 598: r->root_wait = mtmp;
599: } else {
600: /* set wait INFTIM */
1.4 misho 601: sched_timespecinf(&r->root_wait);
1.1 misho 602: }
603: #else
1.12 misho 604: if (!TAILQ_FIRST(&r->root_task) && (task = TAILQ_FIRST(&r->root_timer))) {
1.4 misho 605: clock_gettime(CLOCK_MONOTONIC, &now);
1.1 misho 606:
1.4 misho 607: m = TASK_TS(task);
608: sched_timespecsub(&m, &now, &mtmp);
1.1 misho 609: r->root_wait = mtmp;
610: } else {
611: /* set wait INFTIM */
1.4 misho 612: sched_timespecinf(&r->root_wait);
1.1 misho 613: }
614: #endif
1.12 misho 615: /* if present member of task, set NOWAIT */
616: if (TAILQ_FIRST(&r->root_task))
1.4 misho 617: sched_timespecclear(&r->root_wait);
1.1 misho 618:
1.4 misho 619: if (r->root_wait.tv_sec != -1 && r->root_wait.tv_nsec != -1)
620: timeout = &r->root_wait;
621: else if (sched_timespecisinf(&r->root_poll))
1.1 misho 622: timeout = NULL;
1.4 misho 623: else
624: timeout = &r->root_poll;
1.1 misho 625: if ((en = kevent(r->root_kq, NULL, 0, res, KQ_EVENTS, timeout)) == -1) {
1.3 misho 626: if (r->root_hooks.hook_exec.exception) {
627: if (r->root_hooks.hook_exec.exception(r, NULL))
628: return NULL;
1.6 misho 629: } else if (errno != EINTR)
1.3 misho 630: LOGERR;
1.2 misho 631: return NULL;
1.1 misho 632: }
633:
1.4 misho 634: now.tv_sec = now.tv_nsec = 0;
1.1 misho 635: /* Go and catch the cat into pipes ... */
636: for (i = 0; i < en; i++) {
637: memcpy(evt, &res[i], sizeof evt);
638: evt->flags = EV_DELETE;
639: /* Put read/write task to ready queue */
640: switch (res[i].filter) {
641: case EVFILT_READ:
1.9 misho 642: flg = 0;
1.6 misho 643: TAILQ_FOREACH_SAFE(task, &r->root_read, task_node, tmp) {
1.3 misho 644: if (TASK_FD(task) != ((intptr_t) res[i].udata))
1.1 misho 645: continue;
1.14 misho 646: else {
1.9 misho 647: flg++;
1.14 misho 648: TASK_RET(task) = res[i].data;
649: TASK_FLAG(task) = res[i].fflags;
650: }
1.1 misho 651: /* remove read handle */
1.4 misho 652: #ifdef HAVE_LIBPTHREAD
653: pthread_mutex_lock(&r->root_mtx[taskREAD]);
654: #endif
1.1 misho 655: TAILQ_REMOVE(&r->root_read, task, task_node);
1.4 misho 656: #ifdef HAVE_LIBPTHREAD
657: pthread_mutex_unlock(&r->root_mtx[taskREAD]);
658: #endif
1.3 misho 659: if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
660: if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
661: task->task_type = taskUNUSE;
1.4 misho 662: #ifdef HAVE_LIBPTHREAD
663: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
664: #endif
1.3 misho 665: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 666: #ifdef HAVE_LIBPTHREAD
667: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
668: #endif
1.3 misho 669: } else {
670: task->task_type = taskREADY;
1.4 misho 671: #ifdef HAVE_LIBPTHREAD
672: pthread_mutex_lock(&r->root_mtx[taskREADY]);
673: #endif
1.3 misho 674: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 675: #ifdef HAVE_LIBPTHREAD
676: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
677: #endif
1.3 misho 678: }
679: } else {
1.2 misho 680: task->task_type = taskREADY;
1.4 misho 681: #ifdef HAVE_LIBPTHREAD
682: pthread_mutex_lock(&r->root_mtx[taskREADY]);
683: #endif
1.2 misho 684: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 685: #ifdef HAVE_LIBPTHREAD
686: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
687: #endif
1.3 misho 688: }
1.1 misho 689: }
1.9 misho 690: /* if match at least 2, don't remove resouce of event */
691: if (flg > 1)
692: evt->flags ^= evt->flags;
1.1 misho 693: break;
694: case EVFILT_WRITE:
1.9 misho 695: flg = 0;
1.6 misho 696: TAILQ_FOREACH_SAFE(task, &r->root_write, task_node, tmp) {
1.3 misho 697: if (TASK_FD(task) != ((intptr_t) res[i].udata))
1.1 misho 698: continue;
1.14 misho 699: else {
1.9 misho 700: flg++;
1.14 misho 701: TASK_RET(task) = res[i].data;
702: TASK_FLAG(task) = res[i].fflags;
703: }
1.1 misho 704: /* remove write handle */
1.4 misho 705: #ifdef HAVE_LIBPTHREAD
706: pthread_mutex_lock(&r->root_mtx[taskWRITE]);
707: #endif
1.1 misho 708: TAILQ_REMOVE(&r->root_write, task, task_node);
1.4 misho 709: #ifdef HAVE_LIBPTHREAD
710: pthread_mutex_unlock(&r->root_mtx[taskWRITE]);
711: #endif
1.3 misho 712: if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
713: if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
714: task->task_type = taskUNUSE;
1.4 misho 715: #ifdef HAVE_LIBPTHREAD
716: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
717: #endif
1.3 misho 718: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 719: #ifdef HAVE_LIBPTHREAD
720: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
721: #endif
1.3 misho 722: } else {
723: task->task_type = taskREADY;
1.4 misho 724: #ifdef HAVE_LIBPTHREAD
725: pthread_mutex_lock(&r->root_mtx[taskREADY]);
726: #endif
1.3 misho 727: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 728: #ifdef HAVE_LIBPTHREAD
729: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
730: #endif
1.3 misho 731: }
732: } else {
1.2 misho 733: task->task_type = taskREADY;
1.4 misho 734: #ifdef HAVE_LIBPTHREAD
735: pthread_mutex_lock(&r->root_mtx[taskREADY]);
736: #endif
1.2 misho 737: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 738: #ifdef HAVE_LIBPTHREAD
739: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
740: #endif
1.3 misho 741: }
1.1 misho 742: }
1.9 misho 743: /* if match at least 2, don't remove resouce of event */
744: if (flg > 1)
745: evt->flags ^= evt->flags;
1.1 misho 746: break;
1.7 misho 747: case EVFILT_TIMER:
1.9 misho 748: flg = 0;
1.7 misho 749: TAILQ_FOREACH_SAFE(task, &r->root_alarm, task_node, tmp) {
750: if ((uintptr_t) TASK_DATA(task) != ((uintptr_t) res[i].udata))
751: continue;
1.14 misho 752: else {
1.9 misho 753: flg++;
1.14 misho 754: TASK_RET(task) = res[i].data;
755: TASK_FLAG(task) = res[i].fflags;
756: }
1.7 misho 757: /* remove alarm handle */
758: #ifdef HAVE_LIBPTHREAD
759: pthread_mutex_lock(&r->root_mtx[taskALARM]);
760: #endif
761: TAILQ_REMOVE(&r->root_alarm, task, task_node);
762: #ifdef HAVE_LIBPTHREAD
763: pthread_mutex_unlock(&r->root_mtx[taskALARM]);
764: #endif
765: task->task_type = taskREADY;
766: #ifdef HAVE_LIBPTHREAD
767: pthread_mutex_lock(&r->root_mtx[taskREADY]);
768: #endif
769: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
770: #ifdef HAVE_LIBPTHREAD
771: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
772: #endif
773: }
1.9 misho 774: /* if match at least 2, don't remove resouce of event */
775: if (flg > 1)
776: evt->flags ^= evt->flags;
1.7 misho 777: break;
1.8 misho 778: case EVFILT_VNODE:
1.9 misho 779: flg = 0;
1.8 misho 780: TAILQ_FOREACH_SAFE(task, &r->root_node, task_node, tmp) {
781: if (TASK_FD(task) != ((intptr_t) res[i].udata))
782: continue;
783: else {
1.9 misho 784: flg++;
1.14 misho 785: TASK_RET(task) = res[i].data;
786: TASK_FLAG(task) = res[i].fflags;
1.8 misho 787: }
788: /* remove node handle */
789: #ifdef HAVE_LIBPTHREAD
790: pthread_mutex_lock(&r->root_mtx[taskNODE]);
791: #endif
792: TAILQ_REMOVE(&r->root_node, task, task_node);
793: #ifdef HAVE_LIBPTHREAD
794: pthread_mutex_unlock(&r->root_mtx[taskNODE]);
795: #endif
796: task->task_type = taskREADY;
797: #ifdef HAVE_LIBPTHREAD
798: pthread_mutex_lock(&r->root_mtx[taskREADY]);
799: #endif
800: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
801: #ifdef HAVE_LIBPTHREAD
802: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
803: #endif
804: }
1.9 misho 805: /* if match at least 2, don't remove resouce of event */
806: if (flg > 1)
807: evt->flags ^= evt->flags;
1.8 misho 808: break;
809: case EVFILT_PROC:
1.9 misho 810: flg = 0;
1.8 misho 811: TAILQ_FOREACH_SAFE(task, &r->root_proc, task_node, tmp) {
812: if (TASK_VAL(task) != ((uintptr_t) res[i].udata))
813: continue;
814: else {
1.9 misho 815: flg++;
1.14 misho 816: TASK_RET(task) = res[i].data;
817: TASK_FLAG(task) = res[i].fflags;
1.8 misho 818: }
819: /* remove proc handle */
820: #ifdef HAVE_LIBPTHREAD
821: pthread_mutex_lock(&r->root_mtx[taskPROC]);
822: #endif
823: TAILQ_REMOVE(&r->root_proc, task, task_node);
824: #ifdef HAVE_LIBPTHREAD
825: pthread_mutex_unlock(&r->root_mtx[taskPROC]);
826: #endif
827: task->task_type = taskREADY;
828: #ifdef HAVE_LIBPTHREAD
829: pthread_mutex_lock(&r->root_mtx[taskREADY]);
830: #endif
831: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
832: #ifdef HAVE_LIBPTHREAD
833: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
834: #endif
835: }
1.9 misho 836: /* if match at least 2, don't remove resouce of event */
837: if (flg > 1)
838: evt->flags ^= evt->flags;
1.8 misho 839: break;
840: case EVFILT_SIGNAL:
1.9 misho 841: flg = 0;
1.8 misho 842: TAILQ_FOREACH_SAFE(task, &r->root_signal, task_node, tmp) {
843: if (TASK_VAL(task) != ((uintptr_t) res[i].udata))
844: continue;
1.14 misho 845: else {
1.9 misho 846: flg++;
1.14 misho 847: TASK_RET(task) = res[i].data;
848: TASK_FLAG(task) = res[i].fflags;
849: }
1.8 misho 850: /* remove signal handle */
851: #ifdef HAVE_LIBPTHREAD
852: pthread_mutex_lock(&r->root_mtx[taskSIGNAL]);
853: #endif
854: TAILQ_REMOVE(&r->root_signal, task, task_node);
855: #ifdef HAVE_LIBPTHREAD
856: pthread_mutex_unlock(&r->root_mtx[taskSIGNAL]);
857: #endif
858: task->task_type = taskREADY;
859: #ifdef HAVE_LIBPTHREAD
860: pthread_mutex_lock(&r->root_mtx[taskREADY]);
861: #endif
862: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
863: #ifdef HAVE_LIBPTHREAD
864: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
865: #endif
866: }
1.9 misho 867: /* if match at least 2, don't remove resouce of event */
868: if (flg > 1)
869: evt->flags ^= evt->flags;
1.8 misho 870: break;
1.11 misho 871: #ifdef AIO_SUPPORT
872: case EVFILT_AIO:
873: flg = 0;
874: TAILQ_FOREACH_SAFE(task, &r->root_aio, task_node, tmp) {
875: acb = (struct aiocb*) TASK_VAL(task);
876: if (acb != ((struct aiocb*) res[i].udata))
877: continue;
1.14 misho 878: else {
1.11 misho 879: flg++;
1.14 misho 880: TASK_RET(task) = res[i].data;
881: TASK_FLAG(task) = res[i].fflags;
882: }
1.11 misho 883: /* remove user handle */
884: #ifdef HAVE_LIBPTHREAD
885: pthread_mutex_lock(&r->root_mtx[taskAIO]);
886: #endif
887: TAILQ_REMOVE(&r->root_aio, task, task_node);
888: #ifdef HAVE_LIBPTHREAD
889: pthread_mutex_unlock(&r->root_mtx[taskAIO]);
890: #endif
891: task->task_type = taskREADY;
892: #ifdef HAVE_LIBPTHREAD
893: pthread_mutex_lock(&r->root_mtx[taskREADY]);
894: #endif
895: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
896: #ifdef HAVE_LIBPTHREAD
897: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
898: #endif
899: fd = acb->aio_fildes;
900: if ((len = aio_return(acb)) != -1) {
901: if (lseek(fd, acb->aio_offset + len, SEEK_CUR) == -1)
902: LOGERR;
903: } else
904: LOGERR;
905: free(acb);
906: TASK_DATLEN(task) = (u_long) len;
907: TASK_FD(task) = fd;
908: }
909: /* if match at least 2, don't remove resouce of event */
910: if (flg > 1)
911: evt->flags ^= evt->flags;
912: break;
913: #ifdef EVFILT_LIO
914: case EVFILT_LIO:
915: flg = 0;
916: TAILQ_FOREACH_SAFE(task, &r->root_lio, task_node, tmp) {
917: acbs = (struct aiocb**) TASK_VAL(task);
918: if (acbs != ((struct aiocb**) res[i].udata))
919: continue;
1.14 misho 920: else {
1.11 misho 921: flg++;
1.14 misho 922: TASK_RET(task) = res[i].data;
923: TASK_FLAG(task) = res[i].fflags;
924: }
1.11 misho 925: /* remove user handle */
926: #ifdef HAVE_LIBPTHREAD
927: pthread_mutex_lock(&r->root_mtx[taskLIO]);
928: #endif
929: TAILQ_REMOVE(&r->root_lio, task, task_node);
930: #ifdef HAVE_LIBPTHREAD
931: pthread_mutex_unlock(&r->root_mtx[taskLIO]);
932: #endif
933: task->task_type = taskREADY;
934: #ifdef HAVE_LIBPTHREAD
935: pthread_mutex_lock(&r->root_mtx[taskREADY]);
936: #endif
937: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
938: #ifdef HAVE_LIBPTHREAD
939: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
940: #endif
941: iv = (struct iovec*) TASK_DATA(task);
942: fd = acbs[0]->aio_fildes;
943: off = acbs[0]->aio_offset;
944: for (j = len = 0; i < TASK_DATLEN(task); len += l, i++) {
945: if ((iv[i].iov_len = aio_return(acbs[i])) == -1)
946: l = 0;
947: else
948: l = iv[i].iov_len;
949: free(acbs[i]);
950: }
951: free(acbs);
952: TASK_DATLEN(task) = (u_long) len;
953: TASK_FD(task) = fd;
954:
955: if (lseek(fd, off + len, SEEK_CUR) == -1)
956: LOGERR;
957: }
958: /* if match at least 2, don't remove resouce of event */
959: if (flg > 1)
960: evt->flags ^= evt->flags;
961: break;
962: #endif /* EVFILT_LIO */
963: #endif /* AIO_SUPPORT */
1.8 misho 964: #ifdef EVFILT_USER
965: case EVFILT_USER:
1.9 misho 966: flg = 0;
1.8 misho 967: TAILQ_FOREACH_SAFE(task, &r->root_user, task_node, tmp) {
968: if (TASK_VAL(task) != ((uintptr_t) res[i].udata))
969: continue;
970: else {
1.9 misho 971: flg++;
1.14 misho 972: TASK_RET(task) = res[i].data;
973: TASK_FLAG(task) = res[i].fflags;
1.8 misho 974: }
975: /* remove user handle */
976: #ifdef HAVE_LIBPTHREAD
977: pthread_mutex_lock(&r->root_mtx[taskUSER]);
978: #endif
979: TAILQ_REMOVE(&r->root_user, task, task_node);
980: #ifdef HAVE_LIBPTHREAD
981: pthread_mutex_unlock(&r->root_mtx[taskUSER]);
982: #endif
983: task->task_type = taskREADY;
984: #ifdef HAVE_LIBPTHREAD
985: pthread_mutex_lock(&r->root_mtx[taskREADY]);
986: #endif
987: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
988: #ifdef HAVE_LIBPTHREAD
989: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
990: #endif
991: }
1.9 misho 992: /* if match at least 2, don't remove resouce of event */
993: if (flg > 1)
994: evt->flags ^= evt->flags;
1.8 misho 995: break;
1.11 misho 996: #endif /* EVFILT_USER */
1.1 misho 997: }
1.4 misho 998: if (kevent(r->root_kq, evt, 1, NULL, 0, &now) == -1) {
1.3 misho 999: if (r->root_hooks.hook_exec.exception) {
1000: if (r->root_hooks.hook_exec.exception(r, NULL))
1001: return NULL;
1002: } else
1003: LOGERR;
1004: }
1.1 misho 1005: }
1006:
1.2 misho 1007: /* timer update & put in ready queue */
1.4 misho 1008: clock_gettime(CLOCK_MONOTONIC, &now);
1.1 misho 1009:
1.6 misho 1010: TAILQ_FOREACH_SAFE(task, &r->root_timer, task_node, tmp)
1.4 misho 1011: if (sched_timespeccmp(&now, &TASK_TS(task), -) >= 0) {
1012: #ifdef HAVE_LIBPTHREAD
1013: pthread_mutex_lock(&r->root_mtx[taskTIMER]);
1014: #endif
1.1 misho 1015: TAILQ_REMOVE(&r->root_timer, task, task_node);
1.4 misho 1016: #ifdef HAVE_LIBPTHREAD
1017: pthread_mutex_unlock(&r->root_mtx[taskTIMER]);
1018: #endif
1.1 misho 1019: task->task_type = taskREADY;
1.4 misho 1020: #ifdef HAVE_LIBPTHREAD
1021: pthread_mutex_lock(&r->root_mtx[taskREADY]);
1022: #endif
1.1 misho 1023: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 1024: #ifdef HAVE_LIBPTHREAD
1025: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
1026: #endif
1.1 misho 1027: }
1028:
1.12 misho 1029: /* put regular task priority task to ready queue,
1.13 misho 1030: if there is no ready task or reach max missing hit for regular task */
1.12 misho 1031: if ((task = TAILQ_FIRST(&r->root_task))) {
1.13 misho 1032: if (!TAILQ_FIRST(&r->root_ready) || r->root_miss >= TASK_VAL(task)) {
1033: r->root_miss ^= r->root_miss;
1.1 misho 1034:
1.4 misho 1035: #ifdef HAVE_LIBPTHREAD
1.12 misho 1036: pthread_mutex_lock(&r->root_mtx[taskTASK]);
1.4 misho 1037: #endif
1.12 misho 1038: TAILQ_REMOVE(&r->root_task, task, task_node);
1.4 misho 1039: #ifdef HAVE_LIBPTHREAD
1.12 misho 1040: pthread_mutex_unlock(&r->root_mtx[taskTASK]);
1.4 misho 1041: #endif
1.1 misho 1042: task->task_type = taskREADY;
1.4 misho 1043: #ifdef HAVE_LIBPTHREAD
1044: pthread_mutex_lock(&r->root_mtx[taskREADY]);
1045: #endif
1.1 misho 1046: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 1047: #ifdef HAVE_LIBPTHREAD
1048: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
1049: #endif
1.1 misho 1050: } else
1.13 misho 1051: r->root_miss++;
1.1 misho 1052: } else
1.13 misho 1053: r->root_miss ^= r->root_miss;
1.1 misho 1054:
1055: /* OK, lets get ready task !!! */
1.6 misho 1056: task = TAILQ_FIRST(&r->root_ready);
1057: if (!(task))
1058: return NULL;
1059:
1.4 misho 1060: #ifdef HAVE_LIBPTHREAD
1061: pthread_mutex_lock(&r->root_mtx[taskREADY]);
1062: #endif
1.1 misho 1063: TAILQ_REMOVE(&r->root_ready, task, task_node);
1.4 misho 1064: #ifdef HAVE_LIBPTHREAD
1065: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
1066: #endif
1.1 misho 1067: task->task_type = taskUNUSE;
1.4 misho 1068: #ifdef HAVE_LIBPTHREAD
1069: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
1070: #endif
1.1 misho 1071: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 1072: #ifdef HAVE_LIBPTHREAD
1073: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
1074: #endif
1.1 misho 1075: return task;
1076: }
1.3 misho 1077:
1078: /*
1079: * sched_hook_exception() - Default EXCEPTION hook
1.5 misho 1080: *
1.3 misho 1081: * @root = root task
1082: * @arg = custom handling: if arg == EV_EOF or other value; default: arg == NULL log errno
1083: * return: <0 errors and 0 ok
1084: */
1085: void *
1086: sched_hook_exception(void *root, void *arg)
1087: {
1088: sched_root_task_t *r = root;
1089:
1.6 misho 1090: if (!r)
1.3 misho 1091: return NULL;
1092:
1093: /* custom exception handling ... */
1094: if (arg) {
1095: if (arg == (void*) EV_EOF)
1096: return NULL;
1097: return (void*) -1; /* raise scheduler error!!! */
1098: }
1099:
1100: /* if error hook exists */
1101: if (r->root_hooks.hook_root.error)
1102: return (r->root_hooks.hook_root.error(root, (void*) ((intptr_t) errno)));
1103:
1104: /* default case! */
1105: LOGERR;
1106: return NULL;
1107: }
1.5 misho 1108:
1109: /*
1110: * sched_hook_condition() - Default CONDITION hook
1111: *
1112: * @root = root task
1113: * @arg = killState from schedRun()
1114: * return: NULL kill scheduler loop or !=NULL ok
1115: */
1116: void *
1117: sched_hook_condition(void *root, void *arg)
1118: {
1119: sched_root_task_t *r = root;
1120:
1.6 misho 1121: if (!r)
1.5 misho 1122: return NULL;
1123:
1124: return (void*) (r->root_cond - *(intptr_t*) arg);
1125: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>