Annotation of libaitsched/src/hooks.c, revision 1.7.2.1
1.1 misho 1: /*************************************************************************
2: * (C) 2011 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
3: * by Michael Pounov <misho@openbsd-bg.org>
4: *
5: * $Author: misho $
1.7.2.1 ! misho 6: * $Id: hooks.c,v 1.7 2012/05/30 08:52:45 misho Exp $
1.1 misho 7: *
8: **************************************************************************
9: The ELWIX and AITNET software is distributed under the following
10: terms:
11:
12: All of the documentation and software included in the ELWIX and AITNET
13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
14:
1.5 misho 15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
1.1 misho 16: by Michael Pounov <misho@elwix.org>. All rights reserved.
17:
18: Redistribution and use in source and binary forms, with or without
19: modification, are permitted provided that the following conditions
20: are met:
21: 1. Redistributions of source code must retain the above copyright
22: notice, this list of conditions and the following disclaimer.
23: 2. Redistributions in binary form must reproduce the above copyright
24: notice, this list of conditions and the following disclaimer in the
25: documentation and/or other materials provided with the distribution.
26: 3. All advertising materials mentioning features or use of this software
27: must display the following acknowledgement:
28: This product includes software developed by Michael Pounov <misho@elwix.org>
29: ELWIX - Embedded LightWeight unIX and its contributors.
30: 4. Neither the name of AITNET nor the names of its contributors
31: may be used to endorse or promote products derived from this software
32: without specific prior written permission.
33:
34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37: ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44: SUCH DAMAGE.
45: */
46: #include "global.h"
47: #include "hooks.h"
48:
49:
50: /*
51: * sched_hook_init() - Default INIT hook
1.5 misho 52: *
1.1 misho 53: * @root = root task
1.6 misho 54: * @arg = unused
1.1 misho 55: * return: <0 errors and 0 ok
56: */
57: void *
1.6 misho 58: sched_hook_init(void *root, void *arg __unused)
1.1 misho 59: {
60: sched_root_task_t *r = root;
61:
1.6 misho 62: if (!r)
1.1 misho 63: return (void*) -1;
64:
65: r->root_kq = kqueue();
66: if (r->root_kq == -1) {
67: LOGERR;
68: return (void*) -1;
69: }
70:
71: return NULL;
72: }
73:
74: /*
75: * sched_hook_fini() - Default FINI hook
1.5 misho 76: *
1.1 misho 77: * @root = root task
78: * @arg = unused
79: * return: <0 errors and 0 ok
80: */
81: void *
82: sched_hook_fini(void *root, void *arg __unused)
83: {
84: sched_root_task_t *r = root;
85:
86: if (!r)
87: return (void*) -1;
88:
89: if (r->root_kq > 2) {
90: close(r->root_kq);
91: r->root_kq = 0;
92: }
93:
94: return NULL;
95: }
96:
97: /*
98: * sched_hook_cancel() - Default CANCEL hook
1.5 misho 99: *
1.1 misho 100: * @task = current task
101: * @arg = unused
102: * return: <0 errors and 0 ok
103: */
104: void *
105: sched_hook_cancel(void *task, void *arg __unused)
106: {
107: sched_task_t *t = task;
108: struct kevent chg[1];
1.2 misho 109: struct timespec timeout = { 0, 0 };
1.1 misho 110:
1.6 misho 111: if (!t || !TASK_ROOT(t))
1.1 misho 112: return (void*) -1;
113:
1.4 misho 114: switch (TASK_TYPE(t)) {
1.1 misho 115: case taskREAD:
1.2 misho 116: #ifdef __NetBSD__
117: EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_DELETE, 0, 0, (intptr_t) TASK_FD(t));
118: #else
119: EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_DELETE, 0, 0, (void*) TASK_FD(t));
120: #endif
1.1 misho 121: break;
122: case taskWRITE:
1.2 misho 123: #ifdef __NetBSD__
124: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_DELETE, 0, 0, (intptr_t) TASK_FD(t));
125: #else
126: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_DELETE, 0, 0, (void*) TASK_FD(t));
127: #endif
1.1 misho 128: break;
1.7 misho 129: case taskALARM:
130: #ifdef __NetBSD__
131: EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_DELETE,
132: 0, 0, (intptr_t) TASK_DATA(t));
133: #else
134: EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_DELETE,
135: 0, 0, (void*) TASK_DATA(t));
136: #endif
137: break;
1.7.2.1 ! misho 138: case taskNODE:
! 139: #ifdef __NetBSD__
! 140: EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_DELETE, 0, 0, (intptr_t) TASK_FD(t));
! 141: #else
! 142: EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_DELETE, 0, 0, (void*) TASK_FD(t));
! 143: #endif
1.1 misho 144: break;
1.7.2.1 ! misho 145: case taskPROC:
! 146: #ifdef __NetBSD__
! 147: EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));
! 148: #else
! 149: EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_DELETE, 0, 0, (void*) TASK_VAL(t));
! 150: #endif
! 151: break;
! 152: case taskSIGNAL:
! 153: #ifdef __NetBSD__
! 154: EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));
! 155: #else
! 156: EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_DELETE, 0, 0, (void*) TASK_VAL(t));
! 157: #endif
! 158: break;
! 159: case taskUSER:
! 160: #ifdef __NetBSD__
! 161: EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));
! 162: #else
! 163: EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_DELETE, 0, 0, (void*) TASK_VAL(t));
! 164: #endif
! 165: break;
! 166: default:
! 167: return (void*) -1;
1.1 misho 168: }
169:
1.7.2.1 ! misho 170: kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout);
1.1 misho 171: return NULL;
172: }
173:
174: /*
175: * sched_hook_read() - Default READ hook
1.5 misho 176: *
1.1 misho 177: * @task = current task
178: * @arg = unused
179: * return: <0 errors and 0 ok
180: */
181: void *
182: sched_hook_read(void *task, void *arg __unused)
183: {
184: sched_task_t *t = task;
185: struct kevent chg[1];
1.2 misho 186: struct timespec timeout = { 0, 0 };
1.1 misho 187:
1.6 misho 188: if (!t || !TASK_ROOT(t))
1.1 misho 189: return (void*) -1;
190:
1.2 misho 191: #ifdef __NetBSD__
1.7.2.1 ! misho 192: EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, (intptr_t) TASK_FD(t));
1.2 misho 193: #else
1.7.2.1 ! misho 194: EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, (void*) TASK_FD(t));
1.2 misho 195: #endif
1.4 misho 196: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
197: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
198: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
1.3 misho 199: else
200: LOGERR;
1.1 misho 201: return (void*) -1;
202: }
203:
204: return NULL;
205: }
206:
207: /*
208: * sched_hook_write() - Default WRITE hook
1.5 misho 209: *
1.1 misho 210: * @task = current task
211: * @arg = unused
212: * return: <0 errors and 0 ok
213: */
214: void *
215: sched_hook_write(void *task, void *arg __unused)
216: {
217: sched_task_t *t = task;
218: struct kevent chg[1];
1.2 misho 219: struct timespec timeout = { 0, 0 };
1.1 misho 220:
1.6 misho 221: if (!t || !TASK_ROOT(t))
1.1 misho 222: return (void*) -1;
223:
1.2 misho 224: #ifdef __NetBSD__
1.7.2.1 ! misho 225: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, (intptr_t) TASK_FD(t));
1.2 misho 226: #else
1.7.2.1 ! misho 227: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, (void*) TASK_FD(t));
1.2 misho 228: #endif
1.4 misho 229: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
230: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
231: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
1.3 misho 232: else
233: LOGERR;
1.1 misho 234: return (void*) -1;
235: }
236:
237: return NULL;
238: }
239:
240: /*
1.7 misho 241: * sched_hook_alarm() - Default ALARM hook
242: *
243: * @task = current task
244: * @arg = unused
245: * return: <0 errors and 0 ok
246: */
247: void *
248: sched_hook_alarm(void *task, void *arg __unused)
249: {
250: sched_task_t *t = task;
251: struct kevent chg[1];
252: struct timespec timeout = { 0, 0 };
253:
254: if (!t || !TASK_ROOT(t))
255: return (void*) -1;
256:
257: #ifdef __NetBSD__
258: EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0,
259: t->task_val.ts.tv_sec * 1000 + t->task_val.ts.tv_nsec / 1000000,
260: (intptr_t) TASK_DATA(t));
261: #else
262: EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0,
263: t->task_val.ts.tv_sec * 1000 + t->task_val.ts.tv_nsec / 1000000,
264: (void*) TASK_DATA(t));
265: #endif
266: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
267: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
268: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
269: else
270: LOGERR;
271: return (void*) -1;
272: }
273:
274: return NULL;
275: }
276:
277: /*
1.7.2.1 ! misho 278: * sched_hook_node() - Default NODE hook
! 279: *
! 280: * @task = current task
! 281: * @arg = unused
! 282: * return: <0 errors and 0 ok
! 283: */
! 284: void *
! 285: sched_hook_node(void *task, void *arg __unused)
! 286: {
! 287: sched_task_t *t = task;
! 288: struct kevent chg[1];
! 289: struct timespec timeout = { 0, 0 };
! 290:
! 291: if (!t || !TASK_ROOT(t))
! 292: return (void*) -1;
! 293:
! 294: #ifdef __NetBSD__
! 295: EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_ADD | EV_CLEAR,
! 296: NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB |
! 297: NOTE_LINK | NOTE_RENAME | NOTE_REVOKE, 0, (intptr_t) TASK_FD(t));
! 298: #else
! 299: EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_ADD | EV_CLEAR,
! 300: NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB |
! 301: NOTE_LINK | NOTE_RENAME | NOTE_REVOKE, 0, (void*) TASK_FD(t));
! 302: #endif
! 303: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
! 304: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
! 305: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
! 306: else
! 307: LOGERR;
! 308: return (void*) -1;
! 309: }
! 310:
! 311: return NULL;
! 312: }
! 313:
! 314: /*
! 315: * sched_hook_proc() - Default PROC hook
! 316: *
! 317: * @task = current task
! 318: * @arg = unused
! 319: * return: <0 errors and 0 ok
! 320: */
! 321: void *
! 322: sched_hook_proc(void *task, void *arg __unused)
! 323: {
! 324: sched_task_t *t = task;
! 325: struct kevent chg[1];
! 326: struct timespec timeout = { 0, 0 };
! 327:
! 328: if (!t || !TASK_ROOT(t))
! 329: return (void*) -1;
! 330:
! 331: #ifdef __NetBSD__
! 332: EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_ADD | EV_CLEAR,
! 333: NOTE_EXIT | NOTE_FORK | NOTE_EXEC | NOTE_TRACK, 0, (intptr_t) TASK_VAL(t));
! 334: #else
! 335: EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_ADD | EV_CLEAR,
! 336: NOTE_EXIT | NOTE_FORK | NOTE_EXEC | NOTE_TRACK, 0, (void*) TASK_VAL(t));
! 337: #endif
! 338: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
! 339: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
! 340: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
! 341: else
! 342: LOGERR;
! 343: return (void*) -1;
! 344: }
! 345:
! 346: return NULL;
! 347: }
! 348:
! 349: /*
! 350: * sched_hook_signal() - Default SIGNAL hook
! 351: *
! 352: * @task = current task
! 353: * @arg = unused
! 354: * return: <0 errors and 0 ok
! 355: */
! 356: void *
! 357: sched_hook_signal(void *task, void *arg __unused)
! 358: {
! 359: sched_task_t *t = task;
! 360: struct kevent chg[1];
! 361: struct timespec timeout = { 0, 0 };
! 362:
! 363: if (!t || !TASK_ROOT(t))
! 364: return (void*) -1;
! 365:
! 366: #ifdef __NetBSD__
! 367: EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_ADD, 0, 0, (intptr_t) TASK_VAL(t));
! 368: #else
! 369: EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_ADD, 0, 0, (void*) TASK_VAL(t));
! 370: #endif
! 371: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
! 372: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
! 373: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
! 374: else
! 375: LOGERR;
! 376: return (void*) -1;
! 377: }
! 378:
! 379: return NULL;
! 380: }
! 381:
! 382: /*
! 383: * sched_hook_user() - Default USER hook
! 384: *
! 385: * @task = current task
! 386: * @arg = unused
! 387: * return: <0 errors and 0 ok
! 388: */
! 389: void *
! 390: sched_hook_user(void *task, void *arg __unused)
! 391: {
! 392: sched_task_t *t = task;
! 393: struct kevent chg[1];
! 394: struct timespec timeout = { 0, 0 };
! 395:
! 396: if (!t || !TASK_ROOT(t))
! 397: return (void*) -1;
! 398:
! 399: #ifdef __NetBSD__
! 400: EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_ADD | EV_CLEAR, NOTE_FFNOP, 0, (intptr_t) TASK_VAL(t));
! 401: #else
! 402: EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_ADD | EV_CLEAR, NOTE_FFNOP, 0, (void*) TASK_VAL(t));
! 403: #endif
! 404: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
! 405: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
! 406: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
! 407: else
! 408: LOGERR;
! 409: return (void*) -1;
! 410: }
! 411:
! 412: return NULL;
! 413: }
! 414:
! 415: /*
1.1 misho 416: * sched_hook_fetch() - Default FETCH hook
1.5 misho 417: *
1.1 misho 418: * @root = root task
419: * @arg = unused
420: * return: NULL error or !=NULL fetched task
421: */
422: void *
423: sched_hook_fetch(void *root, void *arg __unused)
424: {
425: sched_root_task_t *r = root;
1.6 misho 426: sched_task_t *task, *tmp;
1.4 misho 427: struct timespec now, m, mtmp;
428: struct timespec *timeout;
1.1 misho 429: struct kevent evt[1], res[KQ_EVENTS];
430: register int i;
431: int en;
432:
1.6 misho 433: if (!r)
1.1 misho 434: return NULL;
435:
436: /* get new task by queue priority */
437: while ((task = TAILQ_FIRST(&r->root_event))) {
1.4 misho 438: #ifdef HAVE_LIBPTHREAD
439: pthread_mutex_lock(&r->root_mtx[taskEVENT]);
440: #endif
1.1 misho 441: TAILQ_REMOVE(&r->root_event, task, task_node);
1.4 misho 442: #ifdef HAVE_LIBPTHREAD
443: pthread_mutex_unlock(&r->root_mtx[taskEVENT]);
444: #endif
1.1 misho 445: task->task_type = taskUNUSE;
1.4 misho 446: #ifdef HAVE_LIBPTHREAD
447: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
448: #endif
1.1 misho 449: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 450: #ifdef HAVE_LIBPTHREAD
451: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
452: #endif
1.1 misho 453: return task;
454: }
455: while ((task = TAILQ_FIRST(&r->root_ready))) {
1.4 misho 456: #ifdef HAVE_LIBPTHREAD
457: pthread_mutex_lock(&r->root_mtx[taskREADY]);
458: #endif
1.1 misho 459: TAILQ_REMOVE(&r->root_ready, task, task_node);
1.4 misho 460: #ifdef HAVE_LIBPTHREAD
461: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
462: #endif
1.1 misho 463: task->task_type = taskUNUSE;
1.4 misho 464: #ifdef HAVE_LIBPTHREAD
465: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
466: #endif
1.1 misho 467: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 468: #ifdef HAVE_LIBPTHREAD
469: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
470: #endif
1.1 misho 471: return task;
472: }
473:
474: #ifdef TIMER_WITHOUT_SORT
1.4 misho 475: clock_gettime(CLOCK_MONOTONIC, &now);
1.1 misho 476:
1.4 misho 477: sched_timespecclear(&r->root_wait);
1.1 misho 478: TAILQ_FOREACH(task, &r->root_timer, task_node) {
1.4 misho 479: if (!sched_timespecisset(&r->root_wait))
480: r->root_wait = TASK_TS(task);
481: else if (sched_timespeccmp(&TASK_TS(task), &r->root_wait, -) < 0)
482: r->root_wait = TASK_TS(task);
1.1 misho 483: }
484:
485: if (TAILQ_FIRST(&r->root_timer)) {
486: m = r->root_wait;
1.4 misho 487: sched_timespecsub(&m, &now, &mtmp);
1.1 misho 488: r->root_wait = mtmp;
489: } else {
490: /* set wait INFTIM */
1.4 misho 491: sched_timespecinf(&r->root_wait);
1.1 misho 492: }
493: #else
494: if (!TAILQ_FIRST(&r->root_eventlo) && (task = TAILQ_FIRST(&r->root_timer))) {
1.4 misho 495: clock_gettime(CLOCK_MONOTONIC, &now);
1.1 misho 496:
1.4 misho 497: m = TASK_TS(task);
498: sched_timespecsub(&m, &now, &mtmp);
1.1 misho 499: r->root_wait = mtmp;
500: } else {
501: /* set wait INFTIM */
1.4 misho 502: sched_timespecinf(&r->root_wait);
1.1 misho 503: }
504: #endif
505: /* if present member of eventLo, set NOWAIT */
506: if (TAILQ_FIRST(&r->root_eventlo))
1.4 misho 507: sched_timespecclear(&r->root_wait);
1.1 misho 508:
1.4 misho 509: if (r->root_wait.tv_sec != -1 && r->root_wait.tv_nsec != -1)
510: timeout = &r->root_wait;
511: else if (sched_timespecisinf(&r->root_poll))
1.1 misho 512: timeout = NULL;
1.4 misho 513: else
514: timeout = &r->root_poll;
1.1 misho 515: if ((en = kevent(r->root_kq, NULL, 0, res, KQ_EVENTS, timeout)) == -1) {
1.3 misho 516: if (r->root_hooks.hook_exec.exception) {
517: if (r->root_hooks.hook_exec.exception(r, NULL))
518: return NULL;
1.6 misho 519: } else if (errno != EINTR)
1.3 misho 520: LOGERR;
1.2 misho 521: return NULL;
1.1 misho 522: }
523:
1.4 misho 524: now.tv_sec = now.tv_nsec = 0;
1.1 misho 525: /* Go and catch the cat into pipes ... */
526: for (i = 0; i < en; i++) {
527: memcpy(evt, &res[i], sizeof evt);
528: evt->flags = EV_DELETE;
529: /* Put read/write task to ready queue */
530: switch (res[i].filter) {
531: case EVFILT_READ:
1.6 misho 532: TAILQ_FOREACH_SAFE(task, &r->root_read, task_node, tmp) {
1.3 misho 533: if (TASK_FD(task) != ((intptr_t) res[i].udata))
1.1 misho 534: continue;
535: /* remove read handle */
1.4 misho 536: #ifdef HAVE_LIBPTHREAD
537: pthread_mutex_lock(&r->root_mtx[taskREAD]);
538: #endif
1.1 misho 539: TAILQ_REMOVE(&r->root_read, task, task_node);
1.4 misho 540: #ifdef HAVE_LIBPTHREAD
541: pthread_mutex_unlock(&r->root_mtx[taskREAD]);
542: #endif
1.3 misho 543: if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
544: if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
545: task->task_type = taskUNUSE;
1.4 misho 546: #ifdef HAVE_LIBPTHREAD
547: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
548: #endif
1.3 misho 549: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 550: #ifdef HAVE_LIBPTHREAD
551: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
552: #endif
1.3 misho 553: } else {
554: task->task_type = taskREADY;
1.4 misho 555: #ifdef HAVE_LIBPTHREAD
556: pthread_mutex_lock(&r->root_mtx[taskREADY]);
557: #endif
1.3 misho 558: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 559: #ifdef HAVE_LIBPTHREAD
560: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
561: #endif
1.3 misho 562: }
563: } else {
1.2 misho 564: task->task_type = taskREADY;
1.4 misho 565: #ifdef HAVE_LIBPTHREAD
566: pthread_mutex_lock(&r->root_mtx[taskREADY]);
567: #endif
1.2 misho 568: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 569: #ifdef HAVE_LIBPTHREAD
570: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
571: #endif
1.3 misho 572: }
1.1 misho 573: break;
574: }
575: break;
576: case EVFILT_WRITE:
1.6 misho 577: TAILQ_FOREACH_SAFE(task, &r->root_write, task_node, tmp) {
1.3 misho 578: if (TASK_FD(task) != ((intptr_t) res[i].udata))
1.1 misho 579: continue;
580: /* remove write handle */
1.4 misho 581: #ifdef HAVE_LIBPTHREAD
582: pthread_mutex_lock(&r->root_mtx[taskWRITE]);
583: #endif
1.1 misho 584: TAILQ_REMOVE(&r->root_write, task, task_node);
1.4 misho 585: #ifdef HAVE_LIBPTHREAD
586: pthread_mutex_unlock(&r->root_mtx[taskWRITE]);
587: #endif
1.3 misho 588: if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
589: if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
590: task->task_type = taskUNUSE;
1.4 misho 591: #ifdef HAVE_LIBPTHREAD
592: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
593: #endif
1.3 misho 594: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 595: #ifdef HAVE_LIBPTHREAD
596: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
597: #endif
1.3 misho 598: } else {
599: task->task_type = taskREADY;
1.4 misho 600: #ifdef HAVE_LIBPTHREAD
601: pthread_mutex_lock(&r->root_mtx[taskREADY]);
602: #endif
1.3 misho 603: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 604: #ifdef HAVE_LIBPTHREAD
605: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
606: #endif
1.3 misho 607: }
608: } else {
1.2 misho 609: task->task_type = taskREADY;
1.4 misho 610: #ifdef HAVE_LIBPTHREAD
611: pthread_mutex_lock(&r->root_mtx[taskREADY]);
612: #endif
1.2 misho 613: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 614: #ifdef HAVE_LIBPTHREAD
615: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
616: #endif
1.3 misho 617: }
1.1 misho 618: break;
619: }
620: break;
1.7 misho 621: case EVFILT_TIMER:
622: TAILQ_FOREACH_SAFE(task, &r->root_alarm, task_node, tmp) {
623: if ((uintptr_t) TASK_DATA(task) != ((uintptr_t) res[i].udata))
624: continue;
625: /* remove alarm handle */
626: #ifdef HAVE_LIBPTHREAD
627: pthread_mutex_lock(&r->root_mtx[taskALARM]);
628: #endif
629: TAILQ_REMOVE(&r->root_alarm, task, task_node);
630: #ifdef HAVE_LIBPTHREAD
631: pthread_mutex_unlock(&r->root_mtx[taskALARM]);
632: #endif
633: task->task_type = taskREADY;
634: #ifdef HAVE_LIBPTHREAD
635: pthread_mutex_lock(&r->root_mtx[taskREADY]);
636: #endif
637: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
638: #ifdef HAVE_LIBPTHREAD
639: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
640: #endif
641: break;
642: }
643: break;
1.7.2.1 ! misho 644: case EVFILT_VNODE:
! 645: TAILQ_FOREACH_SAFE(task, &r->root_node, task_node, tmp) {
! 646: if (TASK_FD(task) != ((intptr_t) res[i].udata))
! 647: continue;
! 648: /* remove node handle */
! 649: #ifdef HAVE_LIBPTHREAD
! 650: pthread_mutex_lock(&r->root_mtx[taskNODE]);
! 651: #endif
! 652: TAILQ_REMOVE(&r->root_node, task, task_node);
! 653: #ifdef HAVE_LIBPTHREAD
! 654: pthread_mutex_unlock(&r->root_mtx[taskNODE]);
! 655: #endif
! 656: task->task_type = taskREADY;
! 657: #ifdef HAVE_LIBPTHREAD
! 658: pthread_mutex_lock(&r->root_mtx[taskREADY]);
! 659: #endif
! 660: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
! 661: #ifdef HAVE_LIBPTHREAD
! 662: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
! 663: #endif
! 664: break;
! 665: }
! 666: break;
! 667: case EVFILT_PROC:
! 668: TAILQ_FOREACH_SAFE(task, &r->root_proc, task_node, tmp) {
! 669: if (TASK_VAL(task) != ((uintptr_t) res[i].udata))
! 670: continue;
! 671: /* remove proc handle */
! 672: #ifdef HAVE_LIBPTHREAD
! 673: pthread_mutex_lock(&r->root_mtx[taskPROC]);
! 674: #endif
! 675: TAILQ_REMOVE(&r->root_proc, task, task_node);
! 676: #ifdef HAVE_LIBPTHREAD
! 677: pthread_mutex_unlock(&r->root_mtx[taskPROC]);
! 678: #endif
! 679: task->task_type = taskREADY;
! 680: #ifdef HAVE_LIBPTHREAD
! 681: pthread_mutex_lock(&r->root_mtx[taskREADY]);
! 682: #endif
! 683: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
! 684: #ifdef HAVE_LIBPTHREAD
! 685: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
! 686: #endif
! 687: break;
! 688: }
! 689: break;
! 690: case EVFILT_SIGNAL:
! 691: TAILQ_FOREACH_SAFE(task, &r->root_signal, task_node, tmp) {
! 692: if (TASK_VAL(task) != ((uintptr_t) res[i].udata))
! 693: continue;
! 694: /* remove signal handle */
! 695: #ifdef HAVE_LIBPTHREAD
! 696: pthread_mutex_lock(&r->root_mtx[taskSIGNAL]);
! 697: #endif
! 698: TAILQ_REMOVE(&r->root_signal, task, task_node);
! 699: #ifdef HAVE_LIBPTHREAD
! 700: pthread_mutex_unlock(&r->root_mtx[taskSIGNAL]);
! 701: #endif
! 702: task->task_type = taskREADY;
! 703: #ifdef HAVE_LIBPTHREAD
! 704: pthread_mutex_lock(&r->root_mtx[taskREADY]);
! 705: #endif
! 706: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
! 707: #ifdef HAVE_LIBPTHREAD
! 708: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
! 709: #endif
! 710: break;
! 711: }
! 712: break;
! 713: case EVFILT_USER:
! 714: TAILQ_FOREACH_SAFE(task, &r->root_user, task_node, tmp) {
! 715: if (TASK_VAL(task) != ((uintptr_t) res[i].udata))
! 716: continue;
! 717: /* remove user handle */
! 718: #ifdef HAVE_LIBPTHREAD
! 719: pthread_mutex_lock(&r->root_mtx[taskUSER]);
! 720: #endif
! 721: TAILQ_REMOVE(&r->root_user, task, task_node);
! 722: #ifdef HAVE_LIBPTHREAD
! 723: pthread_mutex_unlock(&r->root_mtx[taskUSER]);
! 724: #endif
! 725: task->task_type = taskREADY;
! 726: #ifdef HAVE_LIBPTHREAD
! 727: pthread_mutex_lock(&r->root_mtx[taskREADY]);
! 728: #endif
! 729: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
! 730: #ifdef HAVE_LIBPTHREAD
! 731: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
! 732: #endif
! 733: break;
! 734: }
! 735: break;
1.1 misho 736: }
1.4 misho 737: if (kevent(r->root_kq, evt, 1, NULL, 0, &now) == -1) {
1.3 misho 738: if (r->root_hooks.hook_exec.exception) {
739: if (r->root_hooks.hook_exec.exception(r, NULL))
740: return NULL;
741: } else
742: LOGERR;
743: }
1.1 misho 744: }
745:
1.2 misho 746: /* timer update & put in ready queue */
1.4 misho 747: clock_gettime(CLOCK_MONOTONIC, &now);
1.1 misho 748:
1.6 misho 749: TAILQ_FOREACH_SAFE(task, &r->root_timer, task_node, tmp)
1.4 misho 750: if (sched_timespeccmp(&now, &TASK_TS(task), -) >= 0) {
751: #ifdef HAVE_LIBPTHREAD
752: pthread_mutex_lock(&r->root_mtx[taskTIMER]);
753: #endif
1.1 misho 754: TAILQ_REMOVE(&r->root_timer, task, task_node);
1.4 misho 755: #ifdef HAVE_LIBPTHREAD
756: pthread_mutex_unlock(&r->root_mtx[taskTIMER]);
757: #endif
1.1 misho 758: task->task_type = taskREADY;
1.4 misho 759: #ifdef HAVE_LIBPTHREAD
760: pthread_mutex_lock(&r->root_mtx[taskREADY]);
761: #endif
1.1 misho 762: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 763: #ifdef HAVE_LIBPTHREAD
764: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
765: #endif
1.1 misho 766: }
767:
768: /* put eventlo priority task to ready queue, if there is no ready task or
769: reach max missed fetch-rotate */
770: if ((task = TAILQ_FIRST(&r->root_eventlo))) {
771: if (!TAILQ_FIRST(&r->root_ready) || r->root_eventlo_miss > MAX_EVENTLO_MISS) {
772: r->root_eventlo_miss = 0;
773:
1.4 misho 774: #ifdef HAVE_LIBPTHREAD
775: pthread_mutex_lock(&r->root_mtx[taskEVENTLO]);
776: #endif
1.1 misho 777: TAILQ_REMOVE(&r->root_eventlo, task, task_node);
1.4 misho 778: #ifdef HAVE_LIBPTHREAD
779: pthread_mutex_unlock(&r->root_mtx[taskEVENTLO]);
780: #endif
1.1 misho 781: task->task_type = taskREADY;
1.4 misho 782: #ifdef HAVE_LIBPTHREAD
783: pthread_mutex_lock(&r->root_mtx[taskREADY]);
784: #endif
1.1 misho 785: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 786: #ifdef HAVE_LIBPTHREAD
787: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
788: #endif
1.1 misho 789: } else
790: r->root_eventlo_miss++;
791: } else
792: r->root_eventlo_miss = 0;
793:
794: /* OK, lets get ready task !!! */
1.6 misho 795: task = TAILQ_FIRST(&r->root_ready);
796: if (!(task))
797: return NULL;
798:
1.4 misho 799: #ifdef HAVE_LIBPTHREAD
800: pthread_mutex_lock(&r->root_mtx[taskREADY]);
801: #endif
1.1 misho 802: TAILQ_REMOVE(&r->root_ready, task, task_node);
1.4 misho 803: #ifdef HAVE_LIBPTHREAD
804: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
805: #endif
1.1 misho 806: task->task_type = taskUNUSE;
1.4 misho 807: #ifdef HAVE_LIBPTHREAD
808: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
809: #endif
1.1 misho 810: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 811: #ifdef HAVE_LIBPTHREAD
812: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
813: #endif
1.1 misho 814: return task;
815: }
1.3 misho 816:
817: /*
818: * sched_hook_exception() - Default EXCEPTION hook
1.5 misho 819: *
1.3 misho 820: * @root = root task
821: * @arg = custom handling: if arg == EV_EOF or other value; default: arg == NULL log errno
822: * return: <0 errors and 0 ok
823: */
824: void *
825: sched_hook_exception(void *root, void *arg)
826: {
827: sched_root_task_t *r = root;
828:
1.6 misho 829: if (!r)
1.3 misho 830: return NULL;
831:
832: /* custom exception handling ... */
833: if (arg) {
834: if (arg == (void*) EV_EOF)
835: return NULL;
836: return (void*) -1; /* raise scheduler error!!! */
837: }
838:
839: /* if error hook exists */
840: if (r->root_hooks.hook_root.error)
841: return (r->root_hooks.hook_root.error(root, (void*) ((intptr_t) errno)));
842:
843: /* default case! */
844: LOGERR;
845: return NULL;
846: }
1.5 misho 847:
848: /*
849: * sched_hook_condition() - Default CONDITION hook
850: *
851: * @root = root task
852: * @arg = killState from schedRun()
853: * return: NULL kill scheduler loop or !=NULL ok
854: */
855: void *
856: sched_hook_condition(void *root, void *arg)
857: {
858: sched_root_task_t *r = root;
859:
1.6 misho 860: if (!r)
1.5 misho 861: return NULL;
862:
863: return (void*) (r->root_cond - *(intptr_t*) arg);
864: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>