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