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