Annotation of libaitsched/src/hooks.c, revision 1.24.4.5
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.5! misho 6: * $Id: hooks.c,v 1.24.4.4 2014/01/28 10:08:18 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:
1.24.4.5! misho 532: #ifdef KQ_DISABLE
! 533: static void
! 534: _sched_sigHandler(int sig)
! 535: {
! 536: }
! 537: #endif /* KQ_DISABLE */
! 538:
1.8 misho 539: /*
540: * sched_hook_signal() - Default SIGNAL hook
541: *
542: * @task = current task
543: * @arg = unused
544: * return: <0 errors and 0 ok
545: */
546: void *
547: sched_hook_signal(void *task, void *arg __unused)
548: {
549: sched_task_t *t = task;
1.24.4.5! misho 550: #ifndef KQ_DISABLE
1.8 misho 551: struct kevent chg[1];
552: struct timespec timeout = { 0, 0 };
553:
554: if (!t || !TASK_ROOT(t))
555: return (void*) -1;
556:
1.18 misho 557: /* ignore signal */
558: signal(TASK_VAL(t), SIG_IGN);
559:
1.8 misho 560: #ifdef __NetBSD__
1.19 misho 561: EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_ADD | EV_CLEAR, 0, 0, (intptr_t) TASK_VAL(t));
1.8 misho 562: #else
1.19 misho 563: EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_ADD | EV_CLEAR, 0, 0, (void*) TASK_VAL(t));
1.8 misho 564: #endif
565: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
566: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
567: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
568: else
569: LOGERR;
570: return (void*) -1;
571: }
1.24.4.5! misho 572: #else
! 573: struct sigaction sa;
1.8 misho 574:
1.24.4.5! misho 575: memset(&sa, 0, sizeof sa);
! 576: sigemptyset(&sa.sa_mask);
! 577: sa.sa_handler = _sched_sigHandler;
! 578: sa.sa_flags = SA_RESETHAND | SA_RESTART;
! 579:
! 580: if (sigaction(TASK_VAL(t), &sa, NULL) == -1) {
! 581: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
! 582: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
! 583: else
! 584: LOGERR;
! 585: return (void*) -1;
! 586: }
1.24.4.1 misho 587: #endif
1.8 misho 588: return NULL;
589: }
590:
591: /*
592: * sched_hook_user() - Default USER hook
593: *
594: * @task = current task
595: * @arg = unused
596: * return: <0 errors and 0 ok
597: */
598: #ifdef EVFILT_USER
599: void *
600: sched_hook_user(void *task, void *arg __unused)
601: {
1.24.4.1 misho 602: #ifndef KQ_DISABLE
1.8 misho 603: sched_task_t *t = task;
604: struct kevent chg[1];
605: struct timespec timeout = { 0, 0 };
606:
607: if (!t || !TASK_ROOT(t))
608: return (void*) -1;
609:
610: #ifdef __NetBSD__
611: EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_ADD | EV_CLEAR, TASK_DATLEN(t),
612: 0, (intptr_t) TASK_VAL(t));
613: #else
614: EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_ADD | EV_CLEAR, TASK_DATLEN(t),
615: 0, (void*) TASK_VAL(t));
616: #endif
617: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
618: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
619: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
620: else
621: LOGERR;
622: return (void*) -1;
623: }
624:
1.24.4.1 misho 625: #endif
1.8 misho 626: return NULL;
627: }
628: #endif
629:
630: /*
1.1 misho 631: * sched_hook_fetch() - Default FETCH hook
1.5 misho 632: *
1.1 misho 633: * @root = root task
634: * @arg = unused
635: * return: NULL error or !=NULL fetched task
636: */
637: void *
638: sched_hook_fetch(void *root, void *arg __unused)
639: {
640: sched_root_task_t *r = root;
1.6 misho 641: sched_task_t *task, *tmp;
1.24.4.2 misho 642: struct timespec now, m, mtmp;
1.24.4.1 misho 643: #ifndef KQ_DISABLE
1.1 misho 644: struct kevent evt[1], res[KQ_EVENTS];
1.24.4.1 misho 645: struct timespec *timeout, m, mtmp;
646: #else
1.24.4.2 misho 647: struct timeval *timeout, tv;
1.24.4.1 misho 648: #endif
1.9 misho 649: register int i, flg;
1.1 misho 650: int en;
1.11 misho 651: #ifdef AIO_SUPPORT
652: int len, fd;
653: struct aiocb *acb;
654: #ifdef EVFILT_LIO
655: int l;
656: register int j;
657: off_t off;
658: struct aiocb **acbs;
659: struct iovec *iv;
660: #endif /* EVFILT_LIO */
661: #endif /* AIO_SUPPORT */
1.1 misho 662:
1.6 misho 663: if (!r)
1.1 misho 664: return NULL;
665:
666: /* get new task by queue priority */
667: while ((task = TAILQ_FIRST(&r->root_event))) {
1.4 misho 668: #ifdef HAVE_LIBPTHREAD
669: pthread_mutex_lock(&r->root_mtx[taskEVENT]);
670: #endif
1.1 misho 671: TAILQ_REMOVE(&r->root_event, task, task_node);
1.4 misho 672: #ifdef HAVE_LIBPTHREAD
673: pthread_mutex_unlock(&r->root_mtx[taskEVENT]);
674: #endif
1.1 misho 675: task->task_type = taskUNUSE;
1.4 misho 676: #ifdef HAVE_LIBPTHREAD
677: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
678: #endif
1.1 misho 679: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 680: #ifdef HAVE_LIBPTHREAD
681: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
682: #endif
1.1 misho 683: return task;
684: }
685: while ((task = TAILQ_FIRST(&r->root_ready))) {
1.4 misho 686: #ifdef HAVE_LIBPTHREAD
687: pthread_mutex_lock(&r->root_mtx[taskREADY]);
688: #endif
1.1 misho 689: TAILQ_REMOVE(&r->root_ready, task, task_node);
1.4 misho 690: #ifdef HAVE_LIBPTHREAD
691: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
692: #endif
1.1 misho 693: task->task_type = taskUNUSE;
1.4 misho 694: #ifdef HAVE_LIBPTHREAD
695: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
696: #endif
1.1 misho 697: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 698: #ifdef HAVE_LIBPTHREAD
699: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
700: #endif
1.1 misho 701: return task;
702: }
703:
704: #ifdef TIMER_WITHOUT_SORT
1.4 misho 705: clock_gettime(CLOCK_MONOTONIC, &now);
1.1 misho 706:
1.4 misho 707: sched_timespecclear(&r->root_wait);
1.1 misho 708: TAILQ_FOREACH(task, &r->root_timer, task_node) {
1.4 misho 709: if (!sched_timespecisset(&r->root_wait))
710: r->root_wait = TASK_TS(task);
711: else if (sched_timespeccmp(&TASK_TS(task), &r->root_wait, -) < 0)
712: r->root_wait = TASK_TS(task);
1.1 misho 713: }
714:
715: if (TAILQ_FIRST(&r->root_timer)) {
716: m = r->root_wait;
1.4 misho 717: sched_timespecsub(&m, &now, &mtmp);
1.1 misho 718: r->root_wait = mtmp;
719: } else {
720: /* set wait INFTIM */
1.4 misho 721: sched_timespecinf(&r->root_wait);
1.24.4.1 misho 722: }
723: #else /* ! TIMER_WITHOUT_SORT */
1.12 misho 724: if (!TAILQ_FIRST(&r->root_task) && (task = TAILQ_FIRST(&r->root_timer))) {
1.4 misho 725: clock_gettime(CLOCK_MONOTONIC, &now);
1.1 misho 726:
1.4 misho 727: m = TASK_TS(task);
728: sched_timespecsub(&m, &now, &mtmp);
1.1 misho 729: r->root_wait = mtmp;
730: } else {
731: /* set wait INFTIM */
1.4 misho 732: sched_timespecinf(&r->root_wait);
1.1 misho 733: }
1.24.4.1 misho 734: #endif /* TIMER_WITHOUT_SORT */
1.12 misho 735: /* if present member of task, set NOWAIT */
736: if (TAILQ_FIRST(&r->root_task))
1.4 misho 737: sched_timespecclear(&r->root_wait);
1.1 misho 738:
1.24.4.2 misho 739: if (r->root_wait.tv_sec != -1 && r->root_wait.tv_nsec != -1) {
1.24.4.1 misho 740: #ifndef KQ_DISABLE
1.4 misho 741: timeout = &r->root_wait;
1.24.4.1 misho 742: #else
1.24.4.2 misho 743: sched_timespec2val(&r->root_wait, &tv);
744: timeout = &tv;
1.24.4.1 misho 745: #endif /* KQ_DISABLE */
1.24.4.2 misho 746: } else if (sched_timespecisinf(&r->root_poll))
1.1 misho 747: timeout = NULL;
1.24.4.2 misho 748: else {
749: #ifndef KQ_DISABLE
1.4 misho 750: timeout = &r->root_poll;
1.24.4.2 misho 751: #else
752: sched_timespec2val(&r->root_poll, &tv);
753: timeout = &tv;
754: #endif /* KQ_DISABLE */
755: }
1.24.4.1 misho 756:
757: #ifndef KQ_DISABLE
1.1 misho 758: if ((en = kevent(r->root_kq, NULL, 0, res, KQ_EVENTS, timeout)) == -1) {
1.24.4.1 misho 759: #else
760: if ((en = select(r->root_kq, &r->root_fds[0], &r->root_fds[1],
761: &r->root_fds[0], timeout)) == -1) {
762: #endif /* KQ_DISABLE */
1.3 misho 763: if (r->root_hooks.hook_exec.exception) {
764: if (r->root_hooks.hook_exec.exception(r, NULL))
765: return NULL;
1.6 misho 766: } else if (errno != EINTR)
1.3 misho 767: LOGERR;
1.24 misho 768: goto skip_event;
1.1 misho 769: }
770:
1.24 misho 771: /* kevent dispatcher */
1.4 misho 772: now.tv_sec = now.tv_nsec = 0;
1.1 misho 773: /* Go and catch the cat into pipes ... */
1.24.4.1 misho 774: #ifndef KQ_DISABLE
1.24.4.3 misho 775: for (i = 0; i < en; i++) {
1.1 misho 776: memcpy(evt, &res[i], sizeof evt);
777: evt->flags = EV_DELETE;
778: /* Put read/write task to ready queue */
779: switch (res[i].filter) {
780: case EVFILT_READ:
1.9 misho 781: flg = 0;
1.6 misho 782: TAILQ_FOREACH_SAFE(task, &r->root_read, task_node, tmp) {
1.3 misho 783: if (TASK_FD(task) != ((intptr_t) res[i].udata))
1.1 misho 784: continue;
1.14 misho 785: else {
1.9 misho 786: flg++;
1.14 misho 787: TASK_RET(task) = res[i].data;
1.19 misho 788: TASK_FLAG(task) = (u_long) res[i].fflags;
1.14 misho 789: }
1.1 misho 790: /* remove read handle */
1.4 misho 791: #ifdef HAVE_LIBPTHREAD
792: pthread_mutex_lock(&r->root_mtx[taskREAD]);
793: #endif
1.1 misho 794: TAILQ_REMOVE(&r->root_read, task, task_node);
1.4 misho 795: #ifdef HAVE_LIBPTHREAD
796: pthread_mutex_unlock(&r->root_mtx[taskREAD]);
797: #endif
1.3 misho 798: if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
799: if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
800: task->task_type = taskUNUSE;
1.4 misho 801: #ifdef HAVE_LIBPTHREAD
802: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
803: #endif
1.3 misho 804: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 805: #ifdef HAVE_LIBPTHREAD
806: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
807: #endif
1.3 misho 808: } else {
809: task->task_type = taskREADY;
1.4 misho 810: #ifdef HAVE_LIBPTHREAD
811: pthread_mutex_lock(&r->root_mtx[taskREADY]);
812: #endif
1.3 misho 813: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 814: #ifdef HAVE_LIBPTHREAD
815: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
816: #endif
1.3 misho 817: }
818: } else {
1.2 misho 819: task->task_type = taskREADY;
1.4 misho 820: #ifdef HAVE_LIBPTHREAD
821: pthread_mutex_lock(&r->root_mtx[taskREADY]);
822: #endif
1.2 misho 823: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 824: #ifdef HAVE_LIBPTHREAD
825: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
826: #endif
1.3 misho 827: }
1.1 misho 828: }
1.9 misho 829: /* if match at least 2, don't remove resouce of event */
830: if (flg > 1)
831: evt->flags ^= evt->flags;
1.1 misho 832: break;
833: case EVFILT_WRITE:
1.9 misho 834: flg = 0;
1.6 misho 835: TAILQ_FOREACH_SAFE(task, &r->root_write, task_node, tmp) {
1.3 misho 836: if (TASK_FD(task) != ((intptr_t) res[i].udata))
1.1 misho 837: continue;
1.14 misho 838: else {
1.9 misho 839: flg++;
1.14 misho 840: TASK_RET(task) = res[i].data;
1.19 misho 841: TASK_FLAG(task) = (u_long) res[i].fflags;
1.14 misho 842: }
1.1 misho 843: /* remove write handle */
1.4 misho 844: #ifdef HAVE_LIBPTHREAD
845: pthread_mutex_lock(&r->root_mtx[taskWRITE]);
846: #endif
1.1 misho 847: TAILQ_REMOVE(&r->root_write, task, task_node);
1.4 misho 848: #ifdef HAVE_LIBPTHREAD
849: pthread_mutex_unlock(&r->root_mtx[taskWRITE]);
850: #endif
1.3 misho 851: if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
852: if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
853: task->task_type = taskUNUSE;
1.4 misho 854: #ifdef HAVE_LIBPTHREAD
855: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
856: #endif
1.3 misho 857: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 858: #ifdef HAVE_LIBPTHREAD
859: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
860: #endif
1.3 misho 861: } else {
862: task->task_type = taskREADY;
1.4 misho 863: #ifdef HAVE_LIBPTHREAD
864: pthread_mutex_lock(&r->root_mtx[taskREADY]);
865: #endif
1.3 misho 866: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 867: #ifdef HAVE_LIBPTHREAD
868: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
869: #endif
1.3 misho 870: }
871: } else {
1.2 misho 872: task->task_type = taskREADY;
1.4 misho 873: #ifdef HAVE_LIBPTHREAD
874: pthread_mutex_lock(&r->root_mtx[taskREADY]);
875: #endif
1.2 misho 876: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 877: #ifdef HAVE_LIBPTHREAD
878: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
879: #endif
1.3 misho 880: }
1.1 misho 881: }
1.9 misho 882: /* if match at least 2, don't remove resouce of event */
883: if (flg > 1)
884: evt->flags ^= evt->flags;
1.1 misho 885: break;
1.7 misho 886: case EVFILT_TIMER:
1.9 misho 887: flg = 0;
1.7 misho 888: TAILQ_FOREACH_SAFE(task, &r->root_alarm, task_node, tmp) {
889: if ((uintptr_t) TASK_DATA(task) != ((uintptr_t) res[i].udata))
890: continue;
1.14 misho 891: else {
1.9 misho 892: flg++;
1.14 misho 893: TASK_RET(task) = res[i].data;
1.19 misho 894: TASK_FLAG(task) = (u_long) res[i].fflags;
1.14 misho 895: }
1.7 misho 896: /* remove alarm handle */
897: #ifdef HAVE_LIBPTHREAD
898: pthread_mutex_lock(&r->root_mtx[taskALARM]);
899: #endif
900: TAILQ_REMOVE(&r->root_alarm, task, task_node);
901: #ifdef HAVE_LIBPTHREAD
902: pthread_mutex_unlock(&r->root_mtx[taskALARM]);
903: #endif
904: task->task_type = taskREADY;
905: #ifdef HAVE_LIBPTHREAD
906: pthread_mutex_lock(&r->root_mtx[taskREADY]);
907: #endif
908: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
909: #ifdef HAVE_LIBPTHREAD
910: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
911: #endif
912: }
1.9 misho 913: /* if match at least 2, don't remove resouce of event */
914: if (flg > 1)
915: evt->flags ^= evt->flags;
1.7 misho 916: break;
1.8 misho 917: case EVFILT_VNODE:
1.9 misho 918: flg = 0;
1.8 misho 919: TAILQ_FOREACH_SAFE(task, &r->root_node, task_node, tmp) {
920: if (TASK_FD(task) != ((intptr_t) res[i].udata))
921: continue;
922: else {
1.9 misho 923: flg++;
1.14 misho 924: TASK_RET(task) = res[i].data;
1.19 misho 925: TASK_FLAG(task) = (u_long) res[i].fflags;
1.8 misho 926: }
927: /* remove node handle */
928: #ifdef HAVE_LIBPTHREAD
929: pthread_mutex_lock(&r->root_mtx[taskNODE]);
930: #endif
931: TAILQ_REMOVE(&r->root_node, task, task_node);
932: #ifdef HAVE_LIBPTHREAD
933: pthread_mutex_unlock(&r->root_mtx[taskNODE]);
934: #endif
935: task->task_type = taskREADY;
936: #ifdef HAVE_LIBPTHREAD
937: pthread_mutex_lock(&r->root_mtx[taskREADY]);
938: #endif
939: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
940: #ifdef HAVE_LIBPTHREAD
941: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
942: #endif
943: }
1.9 misho 944: /* if match at least 2, don't remove resouce of event */
945: if (flg > 1)
946: evt->flags ^= evt->flags;
1.8 misho 947: break;
948: case EVFILT_PROC:
1.9 misho 949: flg = 0;
1.8 misho 950: TAILQ_FOREACH_SAFE(task, &r->root_proc, task_node, tmp) {
951: if (TASK_VAL(task) != ((uintptr_t) res[i].udata))
952: continue;
953: else {
1.9 misho 954: flg++;
1.14 misho 955: TASK_RET(task) = res[i].data;
1.19 misho 956: TASK_FLAG(task) = (u_long) res[i].fflags;
1.8 misho 957: }
958: /* remove proc handle */
959: #ifdef HAVE_LIBPTHREAD
960: pthread_mutex_lock(&r->root_mtx[taskPROC]);
961: #endif
962: TAILQ_REMOVE(&r->root_proc, task, task_node);
963: #ifdef HAVE_LIBPTHREAD
964: pthread_mutex_unlock(&r->root_mtx[taskPROC]);
965: #endif
966: task->task_type = taskREADY;
967: #ifdef HAVE_LIBPTHREAD
968: pthread_mutex_lock(&r->root_mtx[taskREADY]);
969: #endif
970: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
971: #ifdef HAVE_LIBPTHREAD
972: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
973: #endif
974: }
1.9 misho 975: /* if match at least 2, don't remove resouce of event */
976: if (flg > 1)
977: evt->flags ^= evt->flags;
1.8 misho 978: break;
979: case EVFILT_SIGNAL:
1.9 misho 980: flg = 0;
1.8 misho 981: TAILQ_FOREACH_SAFE(task, &r->root_signal, task_node, tmp) {
982: if (TASK_VAL(task) != ((uintptr_t) res[i].udata))
983: continue;
1.14 misho 984: else {
1.9 misho 985: flg++;
1.14 misho 986: TASK_RET(task) = res[i].data;
1.19 misho 987: TASK_FLAG(task) = (u_long) res[i].fflags;
1.14 misho 988: }
1.8 misho 989: /* remove signal handle */
990: #ifdef HAVE_LIBPTHREAD
991: pthread_mutex_lock(&r->root_mtx[taskSIGNAL]);
992: #endif
993: TAILQ_REMOVE(&r->root_signal, task, task_node);
994: #ifdef HAVE_LIBPTHREAD
995: pthread_mutex_unlock(&r->root_mtx[taskSIGNAL]);
996: #endif
997: task->task_type = taskREADY;
998: #ifdef HAVE_LIBPTHREAD
999: pthread_mutex_lock(&r->root_mtx[taskREADY]);
1000: #endif
1001: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1002: #ifdef HAVE_LIBPTHREAD
1003: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
1004: #endif
1005: }
1.9 misho 1006: /* if match at least 2, don't remove resouce of event */
1007: if (flg > 1)
1008: evt->flags ^= evt->flags;
1.8 misho 1009: break;
1.11 misho 1010: #ifdef AIO_SUPPORT
1011: case EVFILT_AIO:
1012: flg = 0;
1013: TAILQ_FOREACH_SAFE(task, &r->root_aio, task_node, tmp) {
1014: acb = (struct aiocb*) TASK_VAL(task);
1015: if (acb != ((struct aiocb*) res[i].udata))
1016: continue;
1.14 misho 1017: else {
1.11 misho 1018: flg++;
1.14 misho 1019: TASK_RET(task) = res[i].data;
1.19 misho 1020: TASK_FLAG(task) = (u_long) res[i].fflags;
1.14 misho 1021: }
1.11 misho 1022: /* remove user handle */
1023: #ifdef HAVE_LIBPTHREAD
1024: pthread_mutex_lock(&r->root_mtx[taskAIO]);
1025: #endif
1026: TAILQ_REMOVE(&r->root_aio, task, task_node);
1027: #ifdef HAVE_LIBPTHREAD
1028: pthread_mutex_unlock(&r->root_mtx[taskAIO]);
1029: #endif
1030: task->task_type = taskREADY;
1031: #ifdef HAVE_LIBPTHREAD
1032: pthread_mutex_lock(&r->root_mtx[taskREADY]);
1033: #endif
1034: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1035: #ifdef HAVE_LIBPTHREAD
1036: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
1037: #endif
1038: fd = acb->aio_fildes;
1039: if ((len = aio_return(acb)) != -1) {
1040: if (lseek(fd, acb->aio_offset + len, SEEK_CUR) == -1)
1041: LOGERR;
1042: } else
1043: LOGERR;
1044: free(acb);
1045: TASK_DATLEN(task) = (u_long) len;
1046: TASK_FD(task) = fd;
1047: }
1048: /* if match at least 2, don't remove resouce of event */
1049: if (flg > 1)
1050: evt->flags ^= evt->flags;
1051: break;
1052: #ifdef EVFILT_LIO
1053: case EVFILT_LIO:
1054: flg = 0;
1055: TAILQ_FOREACH_SAFE(task, &r->root_lio, task_node, tmp) {
1056: acbs = (struct aiocb**) TASK_VAL(task);
1057: if (acbs != ((struct aiocb**) res[i].udata))
1058: continue;
1.14 misho 1059: else {
1.11 misho 1060: flg++;
1.14 misho 1061: TASK_RET(task) = res[i].data;
1.19 misho 1062: TASK_FLAG(task) = (u_long) res[i].fflags;
1.14 misho 1063: }
1.11 misho 1064: /* remove user handle */
1065: #ifdef HAVE_LIBPTHREAD
1066: pthread_mutex_lock(&r->root_mtx[taskLIO]);
1067: #endif
1068: TAILQ_REMOVE(&r->root_lio, task, task_node);
1069: #ifdef HAVE_LIBPTHREAD
1070: pthread_mutex_unlock(&r->root_mtx[taskLIO]);
1071: #endif
1072: task->task_type = taskREADY;
1073: #ifdef HAVE_LIBPTHREAD
1074: pthread_mutex_lock(&r->root_mtx[taskREADY]);
1075: #endif
1076: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1077: #ifdef HAVE_LIBPTHREAD
1078: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
1079: #endif
1080: iv = (struct iovec*) TASK_DATA(task);
1081: fd = acbs[0]->aio_fildes;
1082: off = acbs[0]->aio_offset;
1083: for (j = len = 0; i < TASK_DATLEN(task); len += l, i++) {
1084: if ((iv[i].iov_len = aio_return(acbs[i])) == -1)
1085: l = 0;
1086: else
1087: l = iv[i].iov_len;
1088: free(acbs[i]);
1089: }
1090: free(acbs);
1091: TASK_DATLEN(task) = (u_long) len;
1092: TASK_FD(task) = fd;
1093:
1094: if (lseek(fd, off + len, SEEK_CUR) == -1)
1095: LOGERR;
1096: }
1097: /* if match at least 2, don't remove resouce of event */
1098: if (flg > 1)
1099: evt->flags ^= evt->flags;
1100: break;
1101: #endif /* EVFILT_LIO */
1102: #endif /* AIO_SUPPORT */
1.8 misho 1103: #ifdef EVFILT_USER
1104: case EVFILT_USER:
1.9 misho 1105: flg = 0;
1.8 misho 1106: TAILQ_FOREACH_SAFE(task, &r->root_user, task_node, tmp) {
1107: if (TASK_VAL(task) != ((uintptr_t) res[i].udata))
1108: continue;
1109: else {
1.9 misho 1110: flg++;
1.14 misho 1111: TASK_RET(task) = res[i].data;
1.19 misho 1112: TASK_FLAG(task) = (u_long) res[i].fflags;
1.8 misho 1113: }
1114: /* remove user handle */
1115: #ifdef HAVE_LIBPTHREAD
1116: pthread_mutex_lock(&r->root_mtx[taskUSER]);
1117: #endif
1118: TAILQ_REMOVE(&r->root_user, task, task_node);
1119: #ifdef HAVE_LIBPTHREAD
1120: pthread_mutex_unlock(&r->root_mtx[taskUSER]);
1121: #endif
1122: task->task_type = taskREADY;
1123: #ifdef HAVE_LIBPTHREAD
1124: pthread_mutex_lock(&r->root_mtx[taskREADY]);
1125: #endif
1126: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1127: #ifdef HAVE_LIBPTHREAD
1128: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
1129: #endif
1130: }
1.9 misho 1131: /* if match at least 2, don't remove resouce of event */
1132: if (flg > 1)
1133: evt->flags ^= evt->flags;
1.8 misho 1134: break;
1.11 misho 1135: #endif /* EVFILT_USER */
1.1 misho 1136: }
1.4 misho 1137: if (kevent(r->root_kq, evt, 1, NULL, 0, &now) == -1) {
1.3 misho 1138: if (r->root_hooks.hook_exec.exception) {
1139: if (r->root_hooks.hook_exec.exception(r, NULL))
1140: return NULL;
1141: } else
1142: LOGERR;
1143: }
1.24.4.3 misho 1144: }
1.24.4.1 misho 1145: #else /* end of kevent dispatcher */
1.24.4.3 misho 1146: for (i = 0; i < r->root_kq; i++) {
1147: if (FD_ISSET(i, &r->root_fds[0])) {
1148: flg = 0;
1149: TAILQ_FOREACH_SAFE(task, &r->root_read, task_node, tmp) {
1150: if (TASK_FD(task) != i)
1151: continue;
1152: else {
1153: flg++;
1154: TASK_RET(task) ^= TASK_RET(task);
1155: TASK_FLAG(task) ^= TASK_FLAG(task);
1156: }
1157: /* remove read handle */
1158: #ifdef HAVE_LIBPTHREAD
1159: pthread_mutex_lock(&r->root_mtx[taskREAD]);
1160: #endif
1161: TAILQ_REMOVE(&r->root_read, task, task_node);
1162: #ifdef HAVE_LIBPTHREAD
1163: pthread_mutex_unlock(&r->root_mtx[taskREAD]);
1164: #endif
1165: if (r->root_hooks.hook_exec.exception) {
1166: if (r->root_hooks.hook_exec.exception(r, NULL)) {
1167: task->task_type = taskUNUSE;
1168: #ifdef HAVE_LIBPTHREAD
1169: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
1170: #endif
1171: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1172: #ifdef HAVE_LIBPTHREAD
1173: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
1174: #endif
1175: } else {
1176: task->task_type = taskREADY;
1177: #ifdef HAVE_LIBPTHREAD
1178: pthread_mutex_lock(&r->root_mtx[taskREADY]);
1179: #endif
1180: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1181: #ifdef HAVE_LIBPTHREAD
1182: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
1183: #endif
1184: }
1185: } else {
1186: task->task_type = taskREADY;
1187: #ifdef HAVE_LIBPTHREAD
1188: pthread_mutex_lock(&r->root_mtx[taskREADY]);
1189: #endif
1190: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1191: #ifdef HAVE_LIBPTHREAD
1192: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
1193: #endif
1194: }
1195: }
1196: /* if match equal to 1, remove resouce */
1197: if (flg == 1)
1198: FD_CLR(i, &r->root_fds[0]);
1199: }
1200:
1201: if (FD_ISSET(i, &r->root_fds[1])) {
1202: flg = 0;
1203: TAILQ_FOREACH_SAFE(task, &r->root_write, task_node, tmp) {
1204: if (TASK_FD(task) != i)
1205: continue;
1206: else {
1207: flg++;
1208: TASK_RET(task) ^= TASK_RET(task);
1209: TASK_FLAG(task) ^= TASK_FLAG(task);
1210: }
1211: /* remove write handle */
1212: #ifdef HAVE_LIBPTHREAD
1213: pthread_mutex_lock(&r->root_mtx[taskWRITE]);
1214: #endif
1215: TAILQ_REMOVE(&r->root_write, task, task_node);
1216: #ifdef HAVE_LIBPTHREAD
1217: pthread_mutex_unlock(&r->root_mtx[taskWRITE]);
1218: #endif
1219: if (r->root_hooks.hook_exec.exception) {
1220: if (r->root_hooks.hook_exec.exception(r, NULL)) {
1221: task->task_type = taskUNUSE;
1222: #ifdef HAVE_LIBPTHREAD
1223: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
1224: #endif
1225: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1226: #ifdef HAVE_LIBPTHREAD
1227: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
1228: #endif
1229: } else {
1230: task->task_type = taskREADY;
1231: #ifdef HAVE_LIBPTHREAD
1232: pthread_mutex_lock(&r->root_mtx[taskREADY]);
1233: #endif
1234: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1235: #ifdef HAVE_LIBPTHREAD
1236: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
1237: #endif
1238: }
1239: } else {
1240: task->task_type = taskREADY;
1241: #ifdef HAVE_LIBPTHREAD
1242: pthread_mutex_lock(&r->root_mtx[taskREADY]);
1243: #endif
1244: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1245: #ifdef HAVE_LIBPTHREAD
1246: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
1247: #endif
1248: }
1249: }
1250: /* if match equal to 1, remove resouce */
1251: if (flg == 1)
1252: FD_CLR(i, &r->root_fds[1]);
1253: }
1.24.4.1 misho 1254: }
1.24.4.4 misho 1255:
1256: /* optimize select */
1257: for (i = r->root_kq - 1; i > 2; i--)
1258: if (FD_ISSET(i, &r->root_fds[0]) || FD_ISSET(i, &r->root_fds[1]))
1259: break;
1260: if (i > 2)
1261: r->root_kq = i + 1;
1.24.4.3 misho 1262: #endif /* KQ_DISABLE */
1.1 misho 1263:
1.24 misho 1264: skip_event:
1.2 misho 1265: /* timer update & put in ready queue */
1.4 misho 1266: clock_gettime(CLOCK_MONOTONIC, &now);
1.1 misho 1267:
1.6 misho 1268: TAILQ_FOREACH_SAFE(task, &r->root_timer, task_node, tmp)
1.4 misho 1269: if (sched_timespeccmp(&now, &TASK_TS(task), -) >= 0) {
1270: #ifdef HAVE_LIBPTHREAD
1271: pthread_mutex_lock(&r->root_mtx[taskTIMER]);
1272: #endif
1.1 misho 1273: TAILQ_REMOVE(&r->root_timer, task, task_node);
1.4 misho 1274: #ifdef HAVE_LIBPTHREAD
1275: pthread_mutex_unlock(&r->root_mtx[taskTIMER]);
1276: #endif
1.1 misho 1277: task->task_type = taskREADY;
1.4 misho 1278: #ifdef HAVE_LIBPTHREAD
1279: pthread_mutex_lock(&r->root_mtx[taskREADY]);
1280: #endif
1.1 misho 1281: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 1282: #ifdef HAVE_LIBPTHREAD
1283: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
1284: #endif
1.1 misho 1285: }
1286:
1.12 misho 1287: /* put regular task priority task to ready queue,
1.13 misho 1288: if there is no ready task or reach max missing hit for regular task */
1.12 misho 1289: if ((task = TAILQ_FIRST(&r->root_task))) {
1.13 misho 1290: if (!TAILQ_FIRST(&r->root_ready) || r->root_miss >= TASK_VAL(task)) {
1291: r->root_miss ^= r->root_miss;
1.1 misho 1292:
1.4 misho 1293: #ifdef HAVE_LIBPTHREAD
1.12 misho 1294: pthread_mutex_lock(&r->root_mtx[taskTASK]);
1.4 misho 1295: #endif
1.12 misho 1296: TAILQ_REMOVE(&r->root_task, task, task_node);
1.4 misho 1297: #ifdef HAVE_LIBPTHREAD
1.12 misho 1298: pthread_mutex_unlock(&r->root_mtx[taskTASK]);
1.4 misho 1299: #endif
1.1 misho 1300: task->task_type = taskREADY;
1.4 misho 1301: #ifdef HAVE_LIBPTHREAD
1302: pthread_mutex_lock(&r->root_mtx[taskREADY]);
1303: #endif
1.1 misho 1304: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 1305: #ifdef HAVE_LIBPTHREAD
1306: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
1307: #endif
1.1 misho 1308: } else
1.13 misho 1309: r->root_miss++;
1.1 misho 1310: } else
1.13 misho 1311: r->root_miss ^= r->root_miss;
1.1 misho 1312:
1313: /* OK, lets get ready task !!! */
1.6 misho 1314: task = TAILQ_FIRST(&r->root_ready);
1315: if (!(task))
1316: return NULL;
1317:
1.4 misho 1318: #ifdef HAVE_LIBPTHREAD
1319: pthread_mutex_lock(&r->root_mtx[taskREADY]);
1320: #endif
1.1 misho 1321: TAILQ_REMOVE(&r->root_ready, task, task_node);
1.4 misho 1322: #ifdef HAVE_LIBPTHREAD
1323: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
1324: #endif
1.1 misho 1325: task->task_type = taskUNUSE;
1.4 misho 1326: #ifdef HAVE_LIBPTHREAD
1327: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
1328: #endif
1.1 misho 1329: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 1330: #ifdef HAVE_LIBPTHREAD
1331: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
1332: #endif
1.1 misho 1333: return task;
1334: }
1.3 misho 1335:
1336: /*
1337: * sched_hook_exception() - Default EXCEPTION hook
1.5 misho 1338: *
1.3 misho 1339: * @root = root task
1340: * @arg = custom handling: if arg == EV_EOF or other value; default: arg == NULL log errno
1341: * return: <0 errors and 0 ok
1342: */
1343: void *
1344: sched_hook_exception(void *root, void *arg)
1345: {
1346: sched_root_task_t *r = root;
1347:
1.6 misho 1348: if (!r)
1.3 misho 1349: return NULL;
1350:
1351: /* custom exception handling ... */
1352: if (arg) {
1353: if (arg == (void*) EV_EOF)
1354: return NULL;
1355: return (void*) -1; /* raise scheduler error!!! */
1356: }
1357:
1358: /* if error hook exists */
1359: if (r->root_hooks.hook_root.error)
1360: return (r->root_hooks.hook_root.error(root, (void*) ((intptr_t) errno)));
1361:
1362: /* default case! */
1363: LOGERR;
1364: return NULL;
1365: }
1.5 misho 1366:
1367: /*
1368: * sched_hook_condition() - Default CONDITION hook
1369: *
1370: * @root = root task
1371: * @arg = killState from schedRun()
1372: * return: NULL kill scheduler loop or !=NULL ok
1373: */
1374: void *
1375: sched_hook_condition(void *root, void *arg)
1376: {
1377: sched_root_task_t *r = root;
1378:
1.6 misho 1379: if (!r)
1.5 misho 1380: return NULL;
1381:
1382: return (void*) (r->root_cond - *(intptr_t*) arg);
1383: }
1.19 misho 1384:
1385: /*
1386: * sched_hook_rtc() - Default RTC hook
1387: *
1388: * @task = current task
1389: * @arg = unused
1390: * return: <0 errors and 0 ok
1391: */
1392: #if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME)
1393: void *
1394: sched_hook_rtc(void *task, void *arg __unused)
1395: {
1396: sched_task_t *sigt = NULL, *t = task;
1397: struct itimerspec its;
1398: struct sigevent evt;
1399: timer_t tmr;
1400:
1401: if (!t || !TASK_ROOT(t))
1402: return (void*) -1;
1403:
1404: memset(&evt, 0, sizeof evt);
1405: evt.sigev_notify = SIGEV_SIGNAL;
1.20 misho 1406: evt.sigev_signo = (intptr_t) TASK_DATA(t) + SIGRTMIN;
1.19 misho 1407: evt.sigev_value.sival_ptr = TASK_DATA(t);
1408:
1409: if (timer_create(CLOCK_MONOTONIC, &evt, &tmr) == -1) {
1410: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
1411: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
1412: else
1413: LOGERR;
1414: return (void*) -1;
1415: } else
1416: TASK_FLAG(t) = (u_long) tmr;
1417:
1.21 misho 1418: if (!(sigt = schedSignal(TASK_ROOT(t), _sched_rtcWrapper, TASK_ARG(t), evt.sigev_signo,
1419: t, (size_t) tmr))) {
1.19 misho 1420: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
1421: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
1422: else
1423: LOGERR;
1424: timer_delete(tmr);
1425: return (void*) -1;
1426: } else
1427: TASK_RET(t) = (uintptr_t) sigt;
1428:
1429: memset(&its, 0, sizeof its);
1430: its.it_value.tv_sec = t->task_val.ts.tv_sec;
1431: its.it_value.tv_nsec = t->task_val.ts.tv_nsec;
1432:
1433: if (timer_settime(tmr, TIMER_RELTIME, &its, NULL) == -1) {
1434: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
1435: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
1436: else
1437: LOGERR;
1438: schedCancel(sigt);
1439: timer_delete(tmr);
1440: return (void*) -1;
1441: }
1442:
1443: return NULL;
1444: }
1445: #endif /* HAVE_TIMER_CREATE */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>