Annotation of libaitsched/src/hooks.c, revision 1.7.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.7.2.2 ! misho 6: * $Id: hooks.c,v 1.7.2.1 2012/05/31 14:17:59 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__
1.7.2.2 ! misho 400: EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_ADD | EV_CLEAR, TASK_DATLEN(t),
! 401: 0, (intptr_t) TASK_VAL(t));
1.7.2.1 misho 402: #else
1.7.2.2 ! misho 403: EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_ADD | EV_CLEAR, TASK_DATLEN(t),
! 404: 0, (void*) TASK_VAL(t));
1.7.2.1 misho 405: #endif
406: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
407: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
408: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
409: else
410: LOGERR;
411: return (void*) -1;
412: }
413:
414: return NULL;
415: }
416:
417: /*
1.1 misho 418: * sched_hook_fetch() - Default FETCH hook
1.5 misho 419: *
1.1 misho 420: * @root = root task
421: * @arg = unused
422: * return: NULL error or !=NULL fetched task
423: */
424: void *
425: sched_hook_fetch(void *root, void *arg __unused)
426: {
427: sched_root_task_t *r = root;
1.6 misho 428: sched_task_t *task, *tmp;
1.4 misho 429: struct timespec now, m, mtmp;
430: struct timespec *timeout;
1.1 misho 431: struct kevent evt[1], res[KQ_EVENTS];
432: register int i;
433: int en;
434:
1.6 misho 435: if (!r)
1.1 misho 436: return NULL;
437:
438: /* get new task by queue priority */
439: while ((task = TAILQ_FIRST(&r->root_event))) {
1.4 misho 440: #ifdef HAVE_LIBPTHREAD
441: pthread_mutex_lock(&r->root_mtx[taskEVENT]);
442: #endif
1.1 misho 443: TAILQ_REMOVE(&r->root_event, task, task_node);
1.4 misho 444: #ifdef HAVE_LIBPTHREAD
445: pthread_mutex_unlock(&r->root_mtx[taskEVENT]);
446: #endif
1.1 misho 447: task->task_type = taskUNUSE;
1.4 misho 448: #ifdef HAVE_LIBPTHREAD
449: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
450: #endif
1.1 misho 451: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 452: #ifdef HAVE_LIBPTHREAD
453: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
454: #endif
1.1 misho 455: return task;
456: }
457: while ((task = TAILQ_FIRST(&r->root_ready))) {
1.4 misho 458: #ifdef HAVE_LIBPTHREAD
459: pthread_mutex_lock(&r->root_mtx[taskREADY]);
460: #endif
1.1 misho 461: TAILQ_REMOVE(&r->root_ready, task, task_node);
1.4 misho 462: #ifdef HAVE_LIBPTHREAD
463: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
464: #endif
1.1 misho 465: task->task_type = taskUNUSE;
1.4 misho 466: #ifdef HAVE_LIBPTHREAD
467: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
468: #endif
1.1 misho 469: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 470: #ifdef HAVE_LIBPTHREAD
471: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
472: #endif
1.1 misho 473: return task;
474: }
475:
476: #ifdef TIMER_WITHOUT_SORT
1.4 misho 477: clock_gettime(CLOCK_MONOTONIC, &now);
1.1 misho 478:
1.4 misho 479: sched_timespecclear(&r->root_wait);
1.1 misho 480: TAILQ_FOREACH(task, &r->root_timer, task_node) {
1.4 misho 481: if (!sched_timespecisset(&r->root_wait))
482: r->root_wait = TASK_TS(task);
483: else if (sched_timespeccmp(&TASK_TS(task), &r->root_wait, -) < 0)
484: r->root_wait = TASK_TS(task);
1.1 misho 485: }
486:
487: if (TAILQ_FIRST(&r->root_timer)) {
488: m = r->root_wait;
1.4 misho 489: sched_timespecsub(&m, &now, &mtmp);
1.1 misho 490: r->root_wait = mtmp;
491: } else {
492: /* set wait INFTIM */
1.4 misho 493: sched_timespecinf(&r->root_wait);
1.1 misho 494: }
495: #else
496: if (!TAILQ_FIRST(&r->root_eventlo) && (task = TAILQ_FIRST(&r->root_timer))) {
1.4 misho 497: clock_gettime(CLOCK_MONOTONIC, &now);
1.1 misho 498:
1.4 misho 499: m = TASK_TS(task);
500: sched_timespecsub(&m, &now, &mtmp);
1.1 misho 501: r->root_wait = mtmp;
502: } else {
503: /* set wait INFTIM */
1.4 misho 504: sched_timespecinf(&r->root_wait);
1.1 misho 505: }
506: #endif
507: /* if present member of eventLo, set NOWAIT */
508: if (TAILQ_FIRST(&r->root_eventlo))
1.4 misho 509: sched_timespecclear(&r->root_wait);
1.1 misho 510:
1.4 misho 511: if (r->root_wait.tv_sec != -1 && r->root_wait.tv_nsec != -1)
512: timeout = &r->root_wait;
513: else if (sched_timespecisinf(&r->root_poll))
1.1 misho 514: timeout = NULL;
1.4 misho 515: else
516: timeout = &r->root_poll;
1.1 misho 517: if ((en = kevent(r->root_kq, NULL, 0, res, KQ_EVENTS, timeout)) == -1) {
1.3 misho 518: if (r->root_hooks.hook_exec.exception) {
519: if (r->root_hooks.hook_exec.exception(r, NULL))
520: return NULL;
1.6 misho 521: } else if (errno != EINTR)
1.3 misho 522: LOGERR;
1.2 misho 523: return NULL;
1.1 misho 524: }
525:
1.4 misho 526: now.tv_sec = now.tv_nsec = 0;
1.1 misho 527: /* Go and catch the cat into pipes ... */
528: for (i = 0; i < en; i++) {
529: memcpy(evt, &res[i], sizeof evt);
530: evt->flags = EV_DELETE;
531: /* Put read/write task to ready queue */
532: switch (res[i].filter) {
533: case EVFILT_READ:
1.6 misho 534: TAILQ_FOREACH_SAFE(task, &r->root_read, task_node, tmp) {
1.3 misho 535: if (TASK_FD(task) != ((intptr_t) res[i].udata))
1.1 misho 536: continue;
537: /* remove read handle */
1.4 misho 538: #ifdef HAVE_LIBPTHREAD
539: pthread_mutex_lock(&r->root_mtx[taskREAD]);
540: #endif
1.1 misho 541: TAILQ_REMOVE(&r->root_read, task, task_node);
1.4 misho 542: #ifdef HAVE_LIBPTHREAD
543: pthread_mutex_unlock(&r->root_mtx[taskREAD]);
544: #endif
1.3 misho 545: if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
546: if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
547: task->task_type = taskUNUSE;
1.4 misho 548: #ifdef HAVE_LIBPTHREAD
549: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
550: #endif
1.3 misho 551: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 552: #ifdef HAVE_LIBPTHREAD
553: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
554: #endif
1.3 misho 555: } else {
556: task->task_type = taskREADY;
1.4 misho 557: #ifdef HAVE_LIBPTHREAD
558: pthread_mutex_lock(&r->root_mtx[taskREADY]);
559: #endif
1.3 misho 560: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 561: #ifdef HAVE_LIBPTHREAD
562: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
563: #endif
1.3 misho 564: }
565: } else {
1.2 misho 566: task->task_type = taskREADY;
1.4 misho 567: #ifdef HAVE_LIBPTHREAD
568: pthread_mutex_lock(&r->root_mtx[taskREADY]);
569: #endif
1.2 misho 570: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 571: #ifdef HAVE_LIBPTHREAD
572: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
573: #endif
1.3 misho 574: }
1.1 misho 575: break;
576: }
577: break;
578: case EVFILT_WRITE:
1.6 misho 579: TAILQ_FOREACH_SAFE(task, &r->root_write, task_node, tmp) {
1.3 misho 580: if (TASK_FD(task) != ((intptr_t) res[i].udata))
1.1 misho 581: continue;
582: /* remove write handle */
1.4 misho 583: #ifdef HAVE_LIBPTHREAD
584: pthread_mutex_lock(&r->root_mtx[taskWRITE]);
585: #endif
1.1 misho 586: TAILQ_REMOVE(&r->root_write, task, task_node);
1.4 misho 587: #ifdef HAVE_LIBPTHREAD
588: pthread_mutex_unlock(&r->root_mtx[taskWRITE]);
589: #endif
1.3 misho 590: if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
591: if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
592: task->task_type = taskUNUSE;
1.4 misho 593: #ifdef HAVE_LIBPTHREAD
594: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
595: #endif
1.3 misho 596: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 597: #ifdef HAVE_LIBPTHREAD
598: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
599: #endif
1.3 misho 600: } else {
601: task->task_type = taskREADY;
1.4 misho 602: #ifdef HAVE_LIBPTHREAD
603: pthread_mutex_lock(&r->root_mtx[taskREADY]);
604: #endif
1.3 misho 605: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 606: #ifdef HAVE_LIBPTHREAD
607: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
608: #endif
1.3 misho 609: }
610: } else {
1.2 misho 611: task->task_type = taskREADY;
1.4 misho 612: #ifdef HAVE_LIBPTHREAD
613: pthread_mutex_lock(&r->root_mtx[taskREADY]);
614: #endif
1.2 misho 615: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 616: #ifdef HAVE_LIBPTHREAD
617: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
618: #endif
1.3 misho 619: }
1.1 misho 620: break;
621: }
622: break;
1.7 misho 623: case EVFILT_TIMER:
624: TAILQ_FOREACH_SAFE(task, &r->root_alarm, task_node, tmp) {
625: if ((uintptr_t) TASK_DATA(task) != ((uintptr_t) res[i].udata))
626: continue;
627: /* remove alarm handle */
628: #ifdef HAVE_LIBPTHREAD
629: pthread_mutex_lock(&r->root_mtx[taskALARM]);
630: #endif
631: TAILQ_REMOVE(&r->root_alarm, task, task_node);
632: #ifdef HAVE_LIBPTHREAD
633: pthread_mutex_unlock(&r->root_mtx[taskALARM]);
634: #endif
635: task->task_type = taskREADY;
636: #ifdef HAVE_LIBPTHREAD
637: pthread_mutex_lock(&r->root_mtx[taskREADY]);
638: #endif
639: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
640: #ifdef HAVE_LIBPTHREAD
641: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
642: #endif
643: break;
644: }
645: break;
1.7.2.1 misho 646: case EVFILT_VNODE:
647: TAILQ_FOREACH_SAFE(task, &r->root_node, task_node, tmp) {
648: if (TASK_FD(task) != ((intptr_t) res[i].udata))
649: continue;
1.7.2.2 ! misho 650: else {
! 651: TASK_DATA(task) = (void*) res[i].data;
! 652: TASK_DATLEN(task) = res[i].fflags;
! 653: }
1.7.2.1 misho 654: /* remove node handle */
655: #ifdef HAVE_LIBPTHREAD
656: pthread_mutex_lock(&r->root_mtx[taskNODE]);
657: #endif
658: TAILQ_REMOVE(&r->root_node, task, task_node);
659: #ifdef HAVE_LIBPTHREAD
660: pthread_mutex_unlock(&r->root_mtx[taskNODE]);
661: #endif
662: task->task_type = taskREADY;
663: #ifdef HAVE_LIBPTHREAD
664: pthread_mutex_lock(&r->root_mtx[taskREADY]);
665: #endif
666: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
667: #ifdef HAVE_LIBPTHREAD
668: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
669: #endif
670: break;
671: }
672: break;
673: case EVFILT_PROC:
674: TAILQ_FOREACH_SAFE(task, &r->root_proc, task_node, tmp) {
675: if (TASK_VAL(task) != ((uintptr_t) res[i].udata))
676: continue;
1.7.2.2 ! misho 677: else {
! 678: TASK_DATA(task) = (void*) res[i].data;
! 679: TASK_DATLEN(task) = res[i].fflags;
! 680: }
1.7.2.1 misho 681: /* remove proc handle */
682: #ifdef HAVE_LIBPTHREAD
683: pthread_mutex_lock(&r->root_mtx[taskPROC]);
684: #endif
685: TAILQ_REMOVE(&r->root_proc, task, task_node);
686: #ifdef HAVE_LIBPTHREAD
687: pthread_mutex_unlock(&r->root_mtx[taskPROC]);
688: #endif
689: task->task_type = taskREADY;
690: #ifdef HAVE_LIBPTHREAD
691: pthread_mutex_lock(&r->root_mtx[taskREADY]);
692: #endif
693: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
694: #ifdef HAVE_LIBPTHREAD
695: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
696: #endif
697: break;
698: }
699: break;
700: case EVFILT_SIGNAL:
701: TAILQ_FOREACH_SAFE(task, &r->root_signal, task_node, tmp) {
702: if (TASK_VAL(task) != ((uintptr_t) res[i].udata))
703: continue;
704: /* remove signal handle */
705: #ifdef HAVE_LIBPTHREAD
706: pthread_mutex_lock(&r->root_mtx[taskSIGNAL]);
707: #endif
708: TAILQ_REMOVE(&r->root_signal, task, task_node);
709: #ifdef HAVE_LIBPTHREAD
710: pthread_mutex_unlock(&r->root_mtx[taskSIGNAL]);
711: #endif
712: task->task_type = taskREADY;
713: #ifdef HAVE_LIBPTHREAD
714: pthread_mutex_lock(&r->root_mtx[taskREADY]);
715: #endif
716: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
717: #ifdef HAVE_LIBPTHREAD
718: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
719: #endif
720: break;
721: }
722: break;
723: case EVFILT_USER:
724: TAILQ_FOREACH_SAFE(task, &r->root_user, task_node, tmp) {
725: if (TASK_VAL(task) != ((uintptr_t) res[i].udata))
726: continue;
1.7.2.2 ! misho 727: else {
! 728: TASK_DATA(task) = (void*) res[i].data;
! 729: TASK_DATLEN(task) = res[i].fflags;
! 730: }
1.7.2.1 misho 731: /* remove user handle */
732: #ifdef HAVE_LIBPTHREAD
733: pthread_mutex_lock(&r->root_mtx[taskUSER]);
734: #endif
735: TAILQ_REMOVE(&r->root_user, task, task_node);
736: #ifdef HAVE_LIBPTHREAD
737: pthread_mutex_unlock(&r->root_mtx[taskUSER]);
738: #endif
739: task->task_type = taskREADY;
740: #ifdef HAVE_LIBPTHREAD
741: pthread_mutex_lock(&r->root_mtx[taskREADY]);
742: #endif
743: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
744: #ifdef HAVE_LIBPTHREAD
745: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
746: #endif
747: break;
748: }
749: break;
1.1 misho 750: }
1.4 misho 751: if (kevent(r->root_kq, evt, 1, NULL, 0, &now) == -1) {
1.3 misho 752: if (r->root_hooks.hook_exec.exception) {
753: if (r->root_hooks.hook_exec.exception(r, NULL))
754: return NULL;
755: } else
756: LOGERR;
757: }
1.1 misho 758: }
759:
1.2 misho 760: /* timer update & put in ready queue */
1.4 misho 761: clock_gettime(CLOCK_MONOTONIC, &now);
1.1 misho 762:
1.6 misho 763: TAILQ_FOREACH_SAFE(task, &r->root_timer, task_node, tmp)
1.4 misho 764: if (sched_timespeccmp(&now, &TASK_TS(task), -) >= 0) {
765: #ifdef HAVE_LIBPTHREAD
766: pthread_mutex_lock(&r->root_mtx[taskTIMER]);
767: #endif
1.1 misho 768: TAILQ_REMOVE(&r->root_timer, task, task_node);
1.4 misho 769: #ifdef HAVE_LIBPTHREAD
770: pthread_mutex_unlock(&r->root_mtx[taskTIMER]);
771: #endif
1.1 misho 772: task->task_type = taskREADY;
1.4 misho 773: #ifdef HAVE_LIBPTHREAD
774: pthread_mutex_lock(&r->root_mtx[taskREADY]);
775: #endif
1.1 misho 776: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 777: #ifdef HAVE_LIBPTHREAD
778: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
779: #endif
1.1 misho 780: }
781:
782: /* put eventlo priority task to ready queue, if there is no ready task or
783: reach max missed fetch-rotate */
784: if ((task = TAILQ_FIRST(&r->root_eventlo))) {
785: if (!TAILQ_FIRST(&r->root_ready) || r->root_eventlo_miss > MAX_EVENTLO_MISS) {
786: r->root_eventlo_miss = 0;
787:
1.4 misho 788: #ifdef HAVE_LIBPTHREAD
789: pthread_mutex_lock(&r->root_mtx[taskEVENTLO]);
790: #endif
1.1 misho 791: TAILQ_REMOVE(&r->root_eventlo, task, task_node);
1.4 misho 792: #ifdef HAVE_LIBPTHREAD
793: pthread_mutex_unlock(&r->root_mtx[taskEVENTLO]);
794: #endif
1.1 misho 795: task->task_type = taskREADY;
1.4 misho 796: #ifdef HAVE_LIBPTHREAD
797: pthread_mutex_lock(&r->root_mtx[taskREADY]);
798: #endif
1.1 misho 799: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 800: #ifdef HAVE_LIBPTHREAD
801: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
802: #endif
1.1 misho 803: } else
804: r->root_eventlo_miss++;
805: } else
806: r->root_eventlo_miss = 0;
807:
808: /* OK, lets get ready task !!! */
1.6 misho 809: task = TAILQ_FIRST(&r->root_ready);
810: if (!(task))
811: return NULL;
812:
1.4 misho 813: #ifdef HAVE_LIBPTHREAD
814: pthread_mutex_lock(&r->root_mtx[taskREADY]);
815: #endif
1.1 misho 816: TAILQ_REMOVE(&r->root_ready, task, task_node);
1.4 misho 817: #ifdef HAVE_LIBPTHREAD
818: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
819: #endif
1.1 misho 820: task->task_type = taskUNUSE;
1.4 misho 821: #ifdef HAVE_LIBPTHREAD
822: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
823: #endif
1.1 misho 824: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 825: #ifdef HAVE_LIBPTHREAD
826: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
827: #endif
1.1 misho 828: return task;
829: }
1.3 misho 830:
831: /*
832: * sched_hook_exception() - Default EXCEPTION hook
1.5 misho 833: *
1.3 misho 834: * @root = root task
835: * @arg = custom handling: if arg == EV_EOF or other value; default: arg == NULL log errno
836: * return: <0 errors and 0 ok
837: */
838: void *
839: sched_hook_exception(void *root, void *arg)
840: {
841: sched_root_task_t *r = root;
842:
1.6 misho 843: if (!r)
1.3 misho 844: return NULL;
845:
846: /* custom exception handling ... */
847: if (arg) {
848: if (arg == (void*) EV_EOF)
849: return NULL;
850: return (void*) -1; /* raise scheduler error!!! */
851: }
852:
853: /* if error hook exists */
854: if (r->root_hooks.hook_root.error)
855: return (r->root_hooks.hook_root.error(root, (void*) ((intptr_t) errno)));
856:
857: /* default case! */
858: LOGERR;
859: return NULL;
860: }
1.5 misho 861:
862: /*
863: * sched_hook_condition() - Default CONDITION hook
864: *
865: * @root = root task
866: * @arg = killState from schedRun()
867: * return: NULL kill scheduler loop or !=NULL ok
868: */
869: void *
870: sched_hook_condition(void *root, void *arg)
871: {
872: sched_root_task_t *r = root;
873:
1.6 misho 874: if (!r)
1.5 misho 875: return NULL;
876:
877: return (void*) (r->root_cond - *(intptr_t*) arg);
878: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>