Annotation of libaitsched/src/hooks.c, revision 1.10.2.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.10.2.5! misho 6: * $Id: hooks.c,v 1.10.2.4 2012/08/01 14:49:37 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.10.2.3 misho 110: #ifdef EVFILT_AIO
111: struct aiocb *acb;
112: #endif
1.1 misho 113:
1.6 misho 114: if (!t || !TASK_ROOT(t))
1.1 misho 115: return (void*) -1;
116:
1.4 misho 117: switch (TASK_TYPE(t)) {
1.1 misho 118: case taskREAD:
1.2 misho 119: #ifdef __NetBSD__
120: EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_DELETE, 0, 0, (intptr_t) TASK_FD(t));
121: #else
122: EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_DELETE, 0, 0, (void*) TASK_FD(t));
123: #endif
1.1 misho 124: break;
125: case taskWRITE:
1.2 misho 126: #ifdef __NetBSD__
127: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_DELETE, 0, 0, (intptr_t) TASK_FD(t));
128: #else
129: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_DELETE, 0, 0, (void*) TASK_FD(t));
130: #endif
1.1 misho 131: break;
1.7 misho 132: case taskALARM:
133: #ifdef __NetBSD__
134: EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_DELETE,
135: 0, 0, (intptr_t) TASK_DATA(t));
136: #else
137: EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_DELETE,
138: 0, 0, (void*) TASK_DATA(t));
139: #endif
1.8 misho 140: break;
141: case taskNODE:
142: #ifdef __NetBSD__
143: EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_DELETE, 0, 0, (intptr_t) TASK_FD(t));
144: #else
145: EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_DELETE, 0, 0, (void*) TASK_FD(t));
146: #endif
147: break;
148: case taskPROC:
149: #ifdef __NetBSD__
150: EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));
151: #else
152: EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_DELETE, 0, 0, (void*) TASK_VAL(t));
153: #endif
154: break;
155: case taskSIGNAL:
156: #ifdef __NetBSD__
157: EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));
158: #else
159: EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_DELETE, 0, 0, (void*) TASK_VAL(t));
160: #endif
161: break;
1.10.2.1 misho 162: #ifdef EVFILT_AIO
163: case taskAIO:
164: #ifdef __NetBSD__
165: EV_SET(&chg[0], TASK_VAL(t), EVFILT_AIO, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));
166: #else
167: EV_SET(&chg[0], TASK_VAL(t), EVFILT_AIO, EV_DELETE, 0, 0, (void*) TASK_VAL(t));
168: #endif
1.10.2.3 misho 169: acb = (struct aiocb*) TASK_VAL(t);
170: if (acb) {
171: aio_cancel(acb->aio_fildes, acb);
172: free(acb);
1.10.2.2 misho 173: TASK_VAL(t) = 0;
174: }
1.10.2.1 misho 175: break;
176: #endif
1.8 misho 177: #ifdef EVFILT_USER
178: case taskUSER:
179: #ifdef __NetBSD__
180: EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_DELETE, 0, 0, (intptr_t) TASK_VAL(t));
181: #else
182: EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_DELETE, 0, 0, (void*) TASK_VAL(t));
183: #endif
1.10 misho 184: break;
1.8 misho 185: #endif
1.1 misho 186: default:
1.8 misho 187: return NULL;
1.1 misho 188: }
189:
1.8 misho 190: kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout);
1.1 misho 191: return NULL;
192: }
193:
194: /*
195: * sched_hook_read() - Default READ 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_read(void *task, void *arg __unused)
203: {
204: sched_task_t *t = task;
205: struct kevent chg[1];
1.2 misho 206: struct timespec timeout = { 0, 0 };
1.1 misho 207:
1.6 misho 208: if (!t || !TASK_ROOT(t))
1.1 misho 209: return (void*) -1;
210:
1.2 misho 211: #ifdef __NetBSD__
1.8 misho 212: EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, (intptr_t) TASK_FD(t));
1.2 misho 213: #else
1.8 misho 214: EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, (void*) TASK_FD(t));
1.2 misho 215: #endif
1.4 misho 216: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
217: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
218: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
1.3 misho 219: else
220: LOGERR;
1.1 misho 221: return (void*) -1;
222: }
223:
224: return NULL;
225: }
226:
227: /*
228: * sched_hook_write() - Default WRITE hook
1.5 misho 229: *
1.1 misho 230: * @task = current task
231: * @arg = unused
232: * return: <0 errors and 0 ok
233: */
234: void *
235: sched_hook_write(void *task, void *arg __unused)
236: {
237: sched_task_t *t = task;
238: struct kevent chg[1];
1.2 misho 239: struct timespec timeout = { 0, 0 };
1.1 misho 240:
1.6 misho 241: if (!t || !TASK_ROOT(t))
1.1 misho 242: return (void*) -1;
243:
1.2 misho 244: #ifdef __NetBSD__
1.8 misho 245: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, (intptr_t) TASK_FD(t));
1.2 misho 246: #else
1.8 misho 247: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, (void*) TASK_FD(t));
1.2 misho 248: #endif
1.4 misho 249: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
250: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
251: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
1.3 misho 252: else
253: LOGERR;
1.1 misho 254: return (void*) -1;
255: }
256:
257: return NULL;
258: }
259:
260: /*
1.7 misho 261: * sched_hook_alarm() - Default ALARM hook
262: *
263: * @task = current task
264: * @arg = unused
265: * return: <0 errors and 0 ok
266: */
267: void *
268: sched_hook_alarm(void *task, void *arg __unused)
269: {
270: sched_task_t *t = task;
271: struct kevent chg[1];
272: struct timespec timeout = { 0, 0 };
273:
274: if (!t || !TASK_ROOT(t))
275: return (void*) -1;
276:
277: #ifdef __NetBSD__
278: EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0,
279: t->task_val.ts.tv_sec * 1000 + t->task_val.ts.tv_nsec / 1000000,
280: (intptr_t) TASK_DATA(t));
281: #else
282: EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0,
283: t->task_val.ts.tv_sec * 1000 + t->task_val.ts.tv_nsec / 1000000,
284: (void*) TASK_DATA(t));
285: #endif
286: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
287: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
288: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
289: else
290: LOGERR;
291: return (void*) -1;
292: }
293:
294: return NULL;
295: }
296:
297: /*
1.8 misho 298: * sched_hook_node() - Default NODE hook
299: *
300: * @task = current task
301: * @arg = unused
302: * return: <0 errors and 0 ok
303: */
304: void *
305: sched_hook_node(void *task, void *arg __unused)
306: {
307: sched_task_t *t = task;
308: struct kevent chg[1];
309: struct timespec timeout = { 0, 0 };
310:
311: if (!t || !TASK_ROOT(t))
312: return (void*) -1;
313:
314: #ifdef __NetBSD__
315: EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_ADD | EV_CLEAR,
316: NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB |
317: NOTE_LINK | NOTE_RENAME | NOTE_REVOKE, 0, (intptr_t) TASK_FD(t));
318: #else
319: EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_ADD | EV_CLEAR,
320: NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB |
321: NOTE_LINK | NOTE_RENAME | NOTE_REVOKE, 0, (void*) TASK_FD(t));
322: #endif
323: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
324: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
325: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
326: else
327: LOGERR;
328: return (void*) -1;
329: }
330:
331: return NULL;
332: }
333:
334: /*
335: * sched_hook_proc() - Default PROC hook
336: *
337: * @task = current task
338: * @arg = unused
339: * return: <0 errors and 0 ok
340: */
341: void *
342: sched_hook_proc(void *task, void *arg __unused)
343: {
344: sched_task_t *t = task;
345: struct kevent chg[1];
346: struct timespec timeout = { 0, 0 };
347:
348: if (!t || !TASK_ROOT(t))
349: return (void*) -1;
350:
351: #ifdef __NetBSD__
352: EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_ADD | EV_CLEAR,
353: NOTE_EXIT | NOTE_FORK | NOTE_EXEC | NOTE_TRACK, 0, (intptr_t) TASK_VAL(t));
354: #else
355: EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_ADD | EV_CLEAR,
356: NOTE_EXIT | NOTE_FORK | NOTE_EXEC | NOTE_TRACK, 0, (void*) TASK_VAL(t));
357: #endif
358: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
359: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
360: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
361: else
362: LOGERR;
363: return (void*) -1;
364: }
365:
366: return NULL;
367: }
368:
369: /*
370: * sched_hook_signal() - Default SIGNAL hook
371: *
372: * @task = current task
373: * @arg = unused
374: * return: <0 errors and 0 ok
375: */
376: void *
377: sched_hook_signal(void *task, void *arg __unused)
378: {
379: sched_task_t *t = task;
380: struct kevent chg[1];
381: struct timespec timeout = { 0, 0 };
382:
383: if (!t || !TASK_ROOT(t))
384: return (void*) -1;
385:
386: #ifdef __NetBSD__
387: EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_ADD, 0, 0, (intptr_t) TASK_VAL(t));
388: #else
389: EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_ADD, 0, 0, (void*) TASK_VAL(t));
390: #endif
391: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
392: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
393: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
394: else
395: LOGERR;
396: return (void*) -1;
397: }
398:
399: return NULL;
400: }
401:
402: /*
403: * sched_hook_user() - Default USER hook
404: *
405: * @task = current task
406: * @arg = unused
407: * return: <0 errors and 0 ok
408: */
409: #ifdef EVFILT_USER
410: void *
411: sched_hook_user(void *task, void *arg __unused)
412: {
413: sched_task_t *t = task;
414: struct kevent chg[1];
415: struct timespec timeout = { 0, 0 };
416:
417: if (!t || !TASK_ROOT(t))
418: return (void*) -1;
419:
420: #ifdef __NetBSD__
421: EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_ADD | EV_CLEAR, TASK_DATLEN(t),
422: 0, (intptr_t) TASK_VAL(t));
423: #else
424: EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_ADD | EV_CLEAR, TASK_DATLEN(t),
425: 0, (void*) TASK_VAL(t));
426: #endif
427: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
428: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
429: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
430: else
431: LOGERR;
432: return (void*) -1;
433: }
434:
435: return NULL;
436: }
437: #endif
438:
439: /*
1.1 misho 440: * sched_hook_fetch() - Default FETCH hook
1.5 misho 441: *
1.1 misho 442: * @root = root task
443: * @arg = unused
444: * return: NULL error or !=NULL fetched task
445: */
446: void *
447: sched_hook_fetch(void *root, void *arg __unused)
448: {
449: sched_root_task_t *r = root;
1.6 misho 450: sched_task_t *task, *tmp;
1.4 misho 451: struct timespec now, m, mtmp;
452: struct timespec *timeout;
1.1 misho 453: struct kevent evt[1], res[KQ_EVENTS];
1.9 misho 454: register int i, flg;
1.1 misho 455: int en;
1.10.2.2 misho 456: #ifdef EVFILT_AIO
1.10.2.5! misho 457: int len, fd;
1.10.2.2 misho 458: struct aiocb *acb;
459: #endif
1.1 misho 460:
1.6 misho 461: if (!r)
1.1 misho 462: return NULL;
463:
464: /* get new task by queue priority */
465: while ((task = TAILQ_FIRST(&r->root_event))) {
1.4 misho 466: #ifdef HAVE_LIBPTHREAD
467: pthread_mutex_lock(&r->root_mtx[taskEVENT]);
468: #endif
1.1 misho 469: TAILQ_REMOVE(&r->root_event, task, task_node);
1.4 misho 470: #ifdef HAVE_LIBPTHREAD
471: pthread_mutex_unlock(&r->root_mtx[taskEVENT]);
472: #endif
1.1 misho 473: task->task_type = taskUNUSE;
1.4 misho 474: #ifdef HAVE_LIBPTHREAD
475: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
476: #endif
1.1 misho 477: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 478: #ifdef HAVE_LIBPTHREAD
479: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
480: #endif
1.1 misho 481: return task;
482: }
483: while ((task = TAILQ_FIRST(&r->root_ready))) {
1.4 misho 484: #ifdef HAVE_LIBPTHREAD
485: pthread_mutex_lock(&r->root_mtx[taskREADY]);
486: #endif
1.1 misho 487: TAILQ_REMOVE(&r->root_ready, task, task_node);
1.4 misho 488: #ifdef HAVE_LIBPTHREAD
489: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
490: #endif
1.1 misho 491: task->task_type = taskUNUSE;
1.4 misho 492: #ifdef HAVE_LIBPTHREAD
493: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
494: #endif
1.1 misho 495: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 496: #ifdef HAVE_LIBPTHREAD
497: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
498: #endif
1.1 misho 499: return task;
500: }
501:
502: #ifdef TIMER_WITHOUT_SORT
1.4 misho 503: clock_gettime(CLOCK_MONOTONIC, &now);
1.1 misho 504:
1.4 misho 505: sched_timespecclear(&r->root_wait);
1.1 misho 506: TAILQ_FOREACH(task, &r->root_timer, task_node) {
1.4 misho 507: if (!sched_timespecisset(&r->root_wait))
508: r->root_wait = TASK_TS(task);
509: else if (sched_timespeccmp(&TASK_TS(task), &r->root_wait, -) < 0)
510: r->root_wait = TASK_TS(task);
1.1 misho 511: }
512:
513: if (TAILQ_FIRST(&r->root_timer)) {
514: m = r->root_wait;
1.4 misho 515: sched_timespecsub(&m, &now, &mtmp);
1.1 misho 516: r->root_wait = mtmp;
517: } else {
518: /* set wait INFTIM */
1.4 misho 519: sched_timespecinf(&r->root_wait);
1.1 misho 520: }
521: #else
522: if (!TAILQ_FIRST(&r->root_eventlo) && (task = TAILQ_FIRST(&r->root_timer))) {
1.4 misho 523: clock_gettime(CLOCK_MONOTONIC, &now);
1.1 misho 524:
1.4 misho 525: m = TASK_TS(task);
526: sched_timespecsub(&m, &now, &mtmp);
1.1 misho 527: r->root_wait = mtmp;
528: } else {
529: /* set wait INFTIM */
1.4 misho 530: sched_timespecinf(&r->root_wait);
1.1 misho 531: }
532: #endif
533: /* if present member of eventLo, set NOWAIT */
534: if (TAILQ_FIRST(&r->root_eventlo))
1.4 misho 535: sched_timespecclear(&r->root_wait);
1.1 misho 536:
1.4 misho 537: if (r->root_wait.tv_sec != -1 && r->root_wait.tv_nsec != -1)
538: timeout = &r->root_wait;
539: else if (sched_timespecisinf(&r->root_poll))
1.1 misho 540: timeout = NULL;
1.4 misho 541: else
542: timeout = &r->root_poll;
1.1 misho 543: if ((en = kevent(r->root_kq, NULL, 0, res, KQ_EVENTS, timeout)) == -1) {
1.3 misho 544: if (r->root_hooks.hook_exec.exception) {
545: if (r->root_hooks.hook_exec.exception(r, NULL))
546: return NULL;
1.6 misho 547: } else if (errno != EINTR)
1.3 misho 548: LOGERR;
1.2 misho 549: return NULL;
1.1 misho 550: }
551:
1.4 misho 552: now.tv_sec = now.tv_nsec = 0;
1.1 misho 553: /* Go and catch the cat into pipes ... */
554: for (i = 0; i < en; i++) {
555: memcpy(evt, &res[i], sizeof evt);
556: evt->flags = EV_DELETE;
557: /* Put read/write task to ready queue */
558: switch (res[i].filter) {
559: case EVFILT_READ:
1.9 misho 560: flg = 0;
1.6 misho 561: TAILQ_FOREACH_SAFE(task, &r->root_read, task_node, tmp) {
1.3 misho 562: if (TASK_FD(task) != ((intptr_t) res[i].udata))
1.1 misho 563: continue;
1.9 misho 564: else
565: flg++;
1.1 misho 566: /* remove read handle */
1.4 misho 567: #ifdef HAVE_LIBPTHREAD
568: pthread_mutex_lock(&r->root_mtx[taskREAD]);
569: #endif
1.1 misho 570: TAILQ_REMOVE(&r->root_read, task, task_node);
1.4 misho 571: #ifdef HAVE_LIBPTHREAD
572: pthread_mutex_unlock(&r->root_mtx[taskREAD]);
573: #endif
1.3 misho 574: if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
575: if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
576: task->task_type = taskUNUSE;
1.4 misho 577: #ifdef HAVE_LIBPTHREAD
578: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
579: #endif
1.3 misho 580: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 581: #ifdef HAVE_LIBPTHREAD
582: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
583: #endif
1.3 misho 584: } else {
585: task->task_type = taskREADY;
1.4 misho 586: #ifdef HAVE_LIBPTHREAD
587: pthread_mutex_lock(&r->root_mtx[taskREADY]);
588: #endif
1.3 misho 589: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 590: #ifdef HAVE_LIBPTHREAD
591: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
592: #endif
1.3 misho 593: }
594: } else {
1.2 misho 595: task->task_type = taskREADY;
1.4 misho 596: #ifdef HAVE_LIBPTHREAD
597: pthread_mutex_lock(&r->root_mtx[taskREADY]);
598: #endif
1.2 misho 599: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 600: #ifdef HAVE_LIBPTHREAD
601: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
602: #endif
1.3 misho 603: }
1.1 misho 604: }
1.9 misho 605: /* if match at least 2, don't remove resouce of event */
606: if (flg > 1)
607: evt->flags ^= evt->flags;
1.1 misho 608: break;
609: case EVFILT_WRITE:
1.9 misho 610: flg = 0;
1.6 misho 611: TAILQ_FOREACH_SAFE(task, &r->root_write, task_node, tmp) {
1.3 misho 612: if (TASK_FD(task) != ((intptr_t) res[i].udata))
1.1 misho 613: continue;
1.9 misho 614: else
615: flg++;
1.1 misho 616: /* remove write handle */
1.4 misho 617: #ifdef HAVE_LIBPTHREAD
618: pthread_mutex_lock(&r->root_mtx[taskWRITE]);
619: #endif
1.1 misho 620: TAILQ_REMOVE(&r->root_write, task, task_node);
1.4 misho 621: #ifdef HAVE_LIBPTHREAD
622: pthread_mutex_unlock(&r->root_mtx[taskWRITE]);
623: #endif
1.3 misho 624: if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
625: if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
626: task->task_type = taskUNUSE;
1.4 misho 627: #ifdef HAVE_LIBPTHREAD
628: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
629: #endif
1.3 misho 630: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 631: #ifdef HAVE_LIBPTHREAD
632: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
633: #endif
1.3 misho 634: } else {
635: task->task_type = taskREADY;
1.4 misho 636: #ifdef HAVE_LIBPTHREAD
637: pthread_mutex_lock(&r->root_mtx[taskREADY]);
638: #endif
1.3 misho 639: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 640: #ifdef HAVE_LIBPTHREAD
641: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
642: #endif
1.3 misho 643: }
644: } else {
1.2 misho 645: task->task_type = taskREADY;
1.4 misho 646: #ifdef HAVE_LIBPTHREAD
647: pthread_mutex_lock(&r->root_mtx[taskREADY]);
648: #endif
1.2 misho 649: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 650: #ifdef HAVE_LIBPTHREAD
651: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
652: #endif
1.3 misho 653: }
1.1 misho 654: }
1.9 misho 655: /* if match at least 2, don't remove resouce of event */
656: if (flg > 1)
657: evt->flags ^= evt->flags;
1.1 misho 658: break;
1.7 misho 659: case EVFILT_TIMER:
1.9 misho 660: flg = 0;
1.7 misho 661: TAILQ_FOREACH_SAFE(task, &r->root_alarm, task_node, tmp) {
662: if ((uintptr_t) TASK_DATA(task) != ((uintptr_t) res[i].udata))
663: continue;
1.9 misho 664: else
665: flg++;
1.7 misho 666: /* remove alarm handle */
667: #ifdef HAVE_LIBPTHREAD
668: pthread_mutex_lock(&r->root_mtx[taskALARM]);
669: #endif
670: TAILQ_REMOVE(&r->root_alarm, task, task_node);
671: #ifdef HAVE_LIBPTHREAD
672: pthread_mutex_unlock(&r->root_mtx[taskALARM]);
673: #endif
674: task->task_type = taskREADY;
675: #ifdef HAVE_LIBPTHREAD
676: pthread_mutex_lock(&r->root_mtx[taskREADY]);
677: #endif
678: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
679: #ifdef HAVE_LIBPTHREAD
680: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
681: #endif
682: }
1.9 misho 683: /* if match at least 2, don't remove resouce of event */
684: if (flg > 1)
685: evt->flags ^= evt->flags;
1.7 misho 686: break;
1.8 misho 687: case EVFILT_VNODE:
1.9 misho 688: flg = 0;
1.8 misho 689: TAILQ_FOREACH_SAFE(task, &r->root_node, task_node, tmp) {
690: if (TASK_FD(task) != ((intptr_t) res[i].udata))
691: continue;
692: else {
1.9 misho 693: flg++;
1.8 misho 694: TASK_DATA(task) = (void*) (uintptr_t) res[i].data;
695: TASK_DATLEN(task) = res[i].fflags;
696: }
697: /* remove node handle */
698: #ifdef HAVE_LIBPTHREAD
699: pthread_mutex_lock(&r->root_mtx[taskNODE]);
700: #endif
701: TAILQ_REMOVE(&r->root_node, task, task_node);
702: #ifdef HAVE_LIBPTHREAD
703: pthread_mutex_unlock(&r->root_mtx[taskNODE]);
704: #endif
705: task->task_type = taskREADY;
706: #ifdef HAVE_LIBPTHREAD
707: pthread_mutex_lock(&r->root_mtx[taskREADY]);
708: #endif
709: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
710: #ifdef HAVE_LIBPTHREAD
711: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
712: #endif
713: }
1.9 misho 714: /* if match at least 2, don't remove resouce of event */
715: if (flg > 1)
716: evt->flags ^= evt->flags;
1.8 misho 717: break;
718: case EVFILT_PROC:
1.9 misho 719: flg = 0;
1.8 misho 720: TAILQ_FOREACH_SAFE(task, &r->root_proc, task_node, tmp) {
721: if (TASK_VAL(task) != ((uintptr_t) res[i].udata))
722: continue;
723: else {
1.9 misho 724: flg++;
1.8 misho 725: TASK_DATA(task) = (void*) (uintptr_t) res[i].data;
726: TASK_DATLEN(task) = res[i].fflags;
727: }
728: /* remove proc handle */
729: #ifdef HAVE_LIBPTHREAD
730: pthread_mutex_lock(&r->root_mtx[taskPROC]);
731: #endif
732: TAILQ_REMOVE(&r->root_proc, task, task_node);
733: #ifdef HAVE_LIBPTHREAD
734: pthread_mutex_unlock(&r->root_mtx[taskPROC]);
735: #endif
736: task->task_type = taskREADY;
737: #ifdef HAVE_LIBPTHREAD
738: pthread_mutex_lock(&r->root_mtx[taskREADY]);
739: #endif
740: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
741: #ifdef HAVE_LIBPTHREAD
742: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
743: #endif
744: }
1.9 misho 745: /* if match at least 2, don't remove resouce of event */
746: if (flg > 1)
747: evt->flags ^= evt->flags;
1.8 misho 748: break;
749: case EVFILT_SIGNAL:
1.9 misho 750: flg = 0;
1.8 misho 751: TAILQ_FOREACH_SAFE(task, &r->root_signal, task_node, tmp) {
752: if (TASK_VAL(task) != ((uintptr_t) res[i].udata))
753: continue;
1.9 misho 754: else
755: flg++;
1.8 misho 756: /* remove signal handle */
757: #ifdef HAVE_LIBPTHREAD
758: pthread_mutex_lock(&r->root_mtx[taskSIGNAL]);
759: #endif
760: TAILQ_REMOVE(&r->root_signal, task, task_node);
761: #ifdef HAVE_LIBPTHREAD
762: pthread_mutex_unlock(&r->root_mtx[taskSIGNAL]);
763: #endif
764: task->task_type = taskREADY;
765: #ifdef HAVE_LIBPTHREAD
766: pthread_mutex_lock(&r->root_mtx[taskREADY]);
767: #endif
768: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
769: #ifdef HAVE_LIBPTHREAD
770: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
771: #endif
772: }
1.9 misho 773: /* if match at least 2, don't remove resouce of event */
774: if (flg > 1)
775: evt->flags ^= evt->flags;
1.8 misho 776: break;
1.10.2.2 misho 777: #ifdef EVFILT_AIO
778: case EVFILT_AIO:
779: flg = 0;
780: TAILQ_FOREACH_SAFE(task, &r->root_aio, task_node, tmp) {
1.10.2.4 misho 781: acb = (struct aiocb*) TASK_VAL(task);
1.10.2.2 misho 782: if (acb != ((struct aiocb*) res[i].ident) ||
783: acb->aio_sigevent.sigev_value.sival_ptr != res[i].udata)
784: continue;
785: else
786: flg++;
787: /* remove user handle */
788: #ifdef HAVE_LIBPTHREAD
789: pthread_mutex_lock(&r->root_mtx[taskAIO]);
790: #endif
791: TAILQ_REMOVE(&r->root_aio, task, task_node);
792: #ifdef HAVE_LIBPTHREAD
793: pthread_mutex_unlock(&r->root_mtx[taskAIO]);
794: #endif
795: task->task_type = taskREADY;
796: #ifdef HAVE_LIBPTHREAD
797: pthread_mutex_lock(&r->root_mtx[taskREADY]);
798: #endif
799: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
800: #ifdef HAVE_LIBPTHREAD
801: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
802: #endif
1.10.2.5! misho 803: fd = acb->aio_fildes;
1.10.2.4 misho 804: if ((len = aio_return(acb)) != -1) {
1.10.2.5! misho 805: if (lseek(fd, acb->aio_offset + len, SEEK_CUR) == -1)
1.10.2.4 misho 806: LOGERR;
807: } else
808: LOGERR;
809:
810: free(acb);
1.10.2.5! misho 811: TASK_FD(task) = (u_long) fd;
! 812: TASK_DATLEN(task) = (u_long) len;
1.10.2.2 misho 813: }
814: /* if match at least 2, don't remove resouce of event */
815: if (flg > 1)
816: evt->flags ^= evt->flags;
817: break;
818: #endif /* EVFILT_AIO */
1.8 misho 819: #ifdef EVFILT_USER
820: case EVFILT_USER:
1.9 misho 821: flg = 0;
1.8 misho 822: TAILQ_FOREACH_SAFE(task, &r->root_user, task_node, tmp) {
823: if (TASK_VAL(task) != ((uintptr_t) res[i].udata))
824: continue;
825: else {
1.9 misho 826: flg++;
1.8 misho 827: TASK_DATA(task) = (void*) res[i].data;
828: TASK_DATLEN(task) = res[i].fflags;
829: }
830: /* remove user handle */
831: #ifdef HAVE_LIBPTHREAD
832: pthread_mutex_lock(&r->root_mtx[taskUSER]);
833: #endif
834: TAILQ_REMOVE(&r->root_user, task, task_node);
835: #ifdef HAVE_LIBPTHREAD
836: pthread_mutex_unlock(&r->root_mtx[taskUSER]);
837: #endif
838: task->task_type = taskREADY;
839: #ifdef HAVE_LIBPTHREAD
840: pthread_mutex_lock(&r->root_mtx[taskREADY]);
841: #endif
842: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
843: #ifdef HAVE_LIBPTHREAD
844: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
845: #endif
846: }
1.9 misho 847: /* if match at least 2, don't remove resouce of event */
848: if (flg > 1)
849: evt->flags ^= evt->flags;
1.8 misho 850: break;
1.10.2.2 misho 851: #endif /* EVFILT_USER */
1.1 misho 852: }
1.4 misho 853: if (kevent(r->root_kq, evt, 1, NULL, 0, &now) == -1) {
1.3 misho 854: if (r->root_hooks.hook_exec.exception) {
855: if (r->root_hooks.hook_exec.exception(r, NULL))
856: return NULL;
857: } else
858: LOGERR;
859: }
1.1 misho 860: }
861:
1.2 misho 862: /* timer update & put in ready queue */
1.4 misho 863: clock_gettime(CLOCK_MONOTONIC, &now);
1.1 misho 864:
1.6 misho 865: TAILQ_FOREACH_SAFE(task, &r->root_timer, task_node, tmp)
1.4 misho 866: if (sched_timespeccmp(&now, &TASK_TS(task), -) >= 0) {
867: #ifdef HAVE_LIBPTHREAD
868: pthread_mutex_lock(&r->root_mtx[taskTIMER]);
869: #endif
1.1 misho 870: TAILQ_REMOVE(&r->root_timer, task, task_node);
1.4 misho 871: #ifdef HAVE_LIBPTHREAD
872: pthread_mutex_unlock(&r->root_mtx[taskTIMER]);
873: #endif
1.1 misho 874: task->task_type = taskREADY;
1.4 misho 875: #ifdef HAVE_LIBPTHREAD
876: pthread_mutex_lock(&r->root_mtx[taskREADY]);
877: #endif
1.1 misho 878: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 879: #ifdef HAVE_LIBPTHREAD
880: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
881: #endif
1.1 misho 882: }
883:
884: /* put eventlo priority task to ready queue, if there is no ready task or
885: reach max missed fetch-rotate */
886: if ((task = TAILQ_FIRST(&r->root_eventlo))) {
887: if (!TAILQ_FIRST(&r->root_ready) || r->root_eventlo_miss > MAX_EVENTLO_MISS) {
888: r->root_eventlo_miss = 0;
889:
1.4 misho 890: #ifdef HAVE_LIBPTHREAD
891: pthread_mutex_lock(&r->root_mtx[taskEVENTLO]);
892: #endif
1.1 misho 893: TAILQ_REMOVE(&r->root_eventlo, task, task_node);
1.4 misho 894: #ifdef HAVE_LIBPTHREAD
895: pthread_mutex_unlock(&r->root_mtx[taskEVENTLO]);
896: #endif
1.1 misho 897: task->task_type = taskREADY;
1.4 misho 898: #ifdef HAVE_LIBPTHREAD
899: pthread_mutex_lock(&r->root_mtx[taskREADY]);
900: #endif
1.1 misho 901: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 902: #ifdef HAVE_LIBPTHREAD
903: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
904: #endif
1.1 misho 905: } else
906: r->root_eventlo_miss++;
907: } else
908: r->root_eventlo_miss = 0;
909:
910: /* OK, lets get ready task !!! */
1.6 misho 911: task = TAILQ_FIRST(&r->root_ready);
912: if (!(task))
913: return NULL;
914:
1.4 misho 915: #ifdef HAVE_LIBPTHREAD
916: pthread_mutex_lock(&r->root_mtx[taskREADY]);
917: #endif
1.1 misho 918: TAILQ_REMOVE(&r->root_ready, task, task_node);
1.4 misho 919: #ifdef HAVE_LIBPTHREAD
920: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
921: #endif
1.1 misho 922: task->task_type = taskUNUSE;
1.4 misho 923: #ifdef HAVE_LIBPTHREAD
924: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
925: #endif
1.1 misho 926: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 927: #ifdef HAVE_LIBPTHREAD
928: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
929: #endif
1.1 misho 930: return task;
931: }
1.3 misho 932:
933: /*
934: * sched_hook_exception() - Default EXCEPTION hook
1.5 misho 935: *
1.3 misho 936: * @root = root task
937: * @arg = custom handling: if arg == EV_EOF or other value; default: arg == NULL log errno
938: * return: <0 errors and 0 ok
939: */
940: void *
941: sched_hook_exception(void *root, void *arg)
942: {
943: sched_root_task_t *r = root;
944:
1.6 misho 945: if (!r)
1.3 misho 946: return NULL;
947:
948: /* custom exception handling ... */
949: if (arg) {
950: if (arg == (void*) EV_EOF)
951: return NULL;
952: return (void*) -1; /* raise scheduler error!!! */
953: }
954:
955: /* if error hook exists */
956: if (r->root_hooks.hook_root.error)
957: return (r->root_hooks.hook_root.error(root, (void*) ((intptr_t) errno)));
958:
959: /* default case! */
960: LOGERR;
961: return NULL;
962: }
1.5 misho 963:
964: /*
965: * sched_hook_condition() - Default CONDITION hook
966: *
967: * @root = root task
968: * @arg = killState from schedRun()
969: * return: NULL kill scheduler loop or !=NULL ok
970: */
971: void *
972: sched_hook_condition(void *root, void *arg)
973: {
974: sched_root_task_t *r = root;
975:
1.6 misho 976: if (!r)
1.5 misho 977: return NULL;
978:
979: return (void*) (r->root_cond - *(intptr_t*) arg);
980: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>