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