Annotation of libaitsched/src/hooks.c, revision 1.7
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 ! misho 6: * $Id: hooks.c,v 1.6.4.3 2012/05/30 08:51:49 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.4 misho 121: kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout);
1.1 misho 122: break;
123: case taskWRITE:
1.2 misho 124: #ifdef __NetBSD__
125: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_DELETE, 0, 0, (intptr_t) TASK_FD(t));
126: #else
127: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_DELETE, 0, 0, (void*) TASK_FD(t));
128: #endif
1.4 misho 129: kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout);
1.1 misho 130: break;
1.7 ! misho 131: case taskALARM:
! 132: #ifdef __NetBSD__
! 133: EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_DELETE,
! 134: 0, 0, (intptr_t) TASK_DATA(t));
! 135: #else
! 136: EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_DELETE,
! 137: 0, 0, (void*) TASK_DATA(t));
! 138: #endif
! 139: kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout);
! 140: break;
1.1 misho 141: default:
142: break;
143: }
144:
145: return NULL;
146: }
147:
148: /*
149: * sched_hook_read() - Default READ hook
1.5 misho 150: *
1.1 misho 151: * @task = current task
152: * @arg = unused
153: * return: <0 errors and 0 ok
154: */
155: void *
156: sched_hook_read(void *task, void *arg __unused)
157: {
158: sched_task_t *t = task;
159: struct kevent chg[1];
1.2 misho 160: struct timespec timeout = { 0, 0 };
1.1 misho 161:
1.6 misho 162: if (!t || !TASK_ROOT(t))
1.1 misho 163: return (void*) -1;
164:
1.2 misho 165: #ifdef __NetBSD__
166: EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD, 0, 0, (intptr_t) TASK_FD(t));
167: #else
168: EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD, 0, 0, (void*) TASK_FD(t));
169: #endif
1.4 misho 170: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
171: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
172: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
1.3 misho 173: else
174: LOGERR;
1.1 misho 175: return (void*) -1;
176: }
177:
178: return NULL;
179: }
180:
181: /*
182: * sched_hook_write() - Default WRITE hook
1.5 misho 183: *
1.1 misho 184: * @task = current task
185: * @arg = unused
186: * return: <0 errors and 0 ok
187: */
188: void *
189: sched_hook_write(void *task, void *arg __unused)
190: {
191: sched_task_t *t = task;
192: struct kevent chg[1];
1.2 misho 193: struct timespec timeout = { 0, 0 };
1.1 misho 194:
1.6 misho 195: if (!t || !TASK_ROOT(t))
1.1 misho 196: return (void*) -1;
197:
1.2 misho 198: #ifdef __NetBSD__
199: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD, 0, 0, (intptr_t) TASK_FD(t));
200: #else
201: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD, 0, 0, (void*) TASK_FD(t));
202: #endif
1.4 misho 203: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
204: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
205: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
1.3 misho 206: else
207: LOGERR;
1.1 misho 208: return (void*) -1;
209: }
210:
211: return NULL;
212: }
213:
214: /*
1.7 ! misho 215: * sched_hook_alarm() - Default ALARM hook
! 216: *
! 217: * @task = current task
! 218: * @arg = unused
! 219: * return: <0 errors and 0 ok
! 220: */
! 221: void *
! 222: sched_hook_alarm(void *task, void *arg __unused)
! 223: {
! 224: sched_task_t *t = task;
! 225: struct kevent chg[1];
! 226: struct timespec timeout = { 0, 0 };
! 227:
! 228: if (!t || !TASK_ROOT(t))
! 229: return (void*) -1;
! 230:
! 231: #ifdef __NetBSD__
! 232: EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0,
! 233: t->task_val.ts.tv_sec * 1000 + t->task_val.ts.tv_nsec / 1000000,
! 234: (intptr_t) TASK_DATA(t));
! 235: #else
! 236: EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0,
! 237: t->task_val.ts.tv_sec * 1000 + t->task_val.ts.tv_nsec / 1000000,
! 238: (void*) TASK_DATA(t));
! 239: #endif
! 240: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
! 241: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
! 242: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
! 243: else
! 244: LOGERR;
! 245: return (void*) -1;
! 246: }
! 247:
! 248: return NULL;
! 249: }
! 250:
! 251: /*
1.1 misho 252: * sched_hook_fetch() - Default FETCH hook
1.5 misho 253: *
1.1 misho 254: * @root = root task
255: * @arg = unused
256: * return: NULL error or !=NULL fetched task
257: */
258: void *
259: sched_hook_fetch(void *root, void *arg __unused)
260: {
261: sched_root_task_t *r = root;
1.6 misho 262: sched_task_t *task, *tmp;
1.4 misho 263: struct timespec now, m, mtmp;
264: struct timespec *timeout;
1.1 misho 265: struct kevent evt[1], res[KQ_EVENTS];
266: register int i;
267: int en;
268:
1.6 misho 269: if (!r)
1.1 misho 270: return NULL;
271:
272: /* get new task by queue priority */
273: while ((task = TAILQ_FIRST(&r->root_event))) {
1.4 misho 274: #ifdef HAVE_LIBPTHREAD
275: pthread_mutex_lock(&r->root_mtx[taskEVENT]);
276: #endif
1.1 misho 277: TAILQ_REMOVE(&r->root_event, task, task_node);
1.4 misho 278: #ifdef HAVE_LIBPTHREAD
279: pthread_mutex_unlock(&r->root_mtx[taskEVENT]);
280: #endif
1.1 misho 281: task->task_type = taskUNUSE;
1.4 misho 282: #ifdef HAVE_LIBPTHREAD
283: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
284: #endif
1.1 misho 285: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 286: #ifdef HAVE_LIBPTHREAD
287: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
288: #endif
1.1 misho 289: return task;
290: }
291: while ((task = TAILQ_FIRST(&r->root_ready))) {
1.4 misho 292: #ifdef HAVE_LIBPTHREAD
293: pthread_mutex_lock(&r->root_mtx[taskREADY]);
294: #endif
1.1 misho 295: TAILQ_REMOVE(&r->root_ready, task, task_node);
1.4 misho 296: #ifdef HAVE_LIBPTHREAD
297: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
298: #endif
1.1 misho 299: task->task_type = taskUNUSE;
1.4 misho 300: #ifdef HAVE_LIBPTHREAD
301: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
302: #endif
1.1 misho 303: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 304: #ifdef HAVE_LIBPTHREAD
305: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
306: #endif
1.1 misho 307: return task;
308: }
309:
310: #ifdef TIMER_WITHOUT_SORT
1.4 misho 311: clock_gettime(CLOCK_MONOTONIC, &now);
1.1 misho 312:
1.4 misho 313: sched_timespecclear(&r->root_wait);
1.1 misho 314: TAILQ_FOREACH(task, &r->root_timer, task_node) {
1.4 misho 315: if (!sched_timespecisset(&r->root_wait))
316: r->root_wait = TASK_TS(task);
317: else if (sched_timespeccmp(&TASK_TS(task), &r->root_wait, -) < 0)
318: r->root_wait = TASK_TS(task);
1.1 misho 319: }
320:
321: if (TAILQ_FIRST(&r->root_timer)) {
322: m = r->root_wait;
1.4 misho 323: sched_timespecsub(&m, &now, &mtmp);
1.1 misho 324: r->root_wait = mtmp;
325: } else {
326: /* set wait INFTIM */
1.4 misho 327: sched_timespecinf(&r->root_wait);
1.1 misho 328: }
329: #else
330: if (!TAILQ_FIRST(&r->root_eventlo) && (task = TAILQ_FIRST(&r->root_timer))) {
1.4 misho 331: clock_gettime(CLOCK_MONOTONIC, &now);
1.1 misho 332:
1.4 misho 333: m = TASK_TS(task);
334: sched_timespecsub(&m, &now, &mtmp);
1.1 misho 335: r->root_wait = mtmp;
336: } else {
337: /* set wait INFTIM */
1.4 misho 338: sched_timespecinf(&r->root_wait);
1.1 misho 339: }
340: #endif
341: /* if present member of eventLo, set NOWAIT */
342: if (TAILQ_FIRST(&r->root_eventlo))
1.4 misho 343: sched_timespecclear(&r->root_wait);
1.1 misho 344:
1.4 misho 345: if (r->root_wait.tv_sec != -1 && r->root_wait.tv_nsec != -1)
346: timeout = &r->root_wait;
347: else if (sched_timespecisinf(&r->root_poll))
1.1 misho 348: timeout = NULL;
1.4 misho 349: else
350: timeout = &r->root_poll;
1.1 misho 351: if ((en = kevent(r->root_kq, NULL, 0, res, KQ_EVENTS, timeout)) == -1) {
1.3 misho 352: if (r->root_hooks.hook_exec.exception) {
353: if (r->root_hooks.hook_exec.exception(r, NULL))
354: return NULL;
1.6 misho 355: } else if (errno != EINTR)
1.3 misho 356: LOGERR;
1.2 misho 357: return NULL;
1.1 misho 358: }
359:
1.4 misho 360: now.tv_sec = now.tv_nsec = 0;
1.1 misho 361: /* Go and catch the cat into pipes ... */
362: for (i = 0; i < en; i++) {
363: memcpy(evt, &res[i], sizeof evt);
364: evt->flags = EV_DELETE;
365: /* Put read/write task to ready queue */
366: switch (res[i].filter) {
367: case EVFILT_READ:
1.6 misho 368: TAILQ_FOREACH_SAFE(task, &r->root_read, task_node, tmp) {
1.3 misho 369: if (TASK_FD(task) != ((intptr_t) res[i].udata))
1.1 misho 370: continue;
371: /* remove read handle */
1.4 misho 372: #ifdef HAVE_LIBPTHREAD
373: pthread_mutex_lock(&r->root_mtx[taskREAD]);
374: #endif
1.1 misho 375: TAILQ_REMOVE(&r->root_read, task, task_node);
1.4 misho 376: #ifdef HAVE_LIBPTHREAD
377: pthread_mutex_unlock(&r->root_mtx[taskREAD]);
378: #endif
1.3 misho 379: if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
380: if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
381: task->task_type = taskUNUSE;
1.4 misho 382: #ifdef HAVE_LIBPTHREAD
383: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
384: #endif
1.3 misho 385: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 386: #ifdef HAVE_LIBPTHREAD
387: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
388: #endif
1.3 misho 389: } else {
390: task->task_type = taskREADY;
1.4 misho 391: #ifdef HAVE_LIBPTHREAD
392: pthread_mutex_lock(&r->root_mtx[taskREADY]);
393: #endif
1.3 misho 394: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 395: #ifdef HAVE_LIBPTHREAD
396: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
397: #endif
1.3 misho 398: }
399: } else {
1.2 misho 400: task->task_type = taskREADY;
1.4 misho 401: #ifdef HAVE_LIBPTHREAD
402: pthread_mutex_lock(&r->root_mtx[taskREADY]);
403: #endif
1.2 misho 404: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 405: #ifdef HAVE_LIBPTHREAD
406: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
407: #endif
1.3 misho 408: }
1.1 misho 409: break;
410: }
411: break;
412: case EVFILT_WRITE:
1.6 misho 413: TAILQ_FOREACH_SAFE(task, &r->root_write, task_node, tmp) {
1.3 misho 414: if (TASK_FD(task) != ((intptr_t) res[i].udata))
1.1 misho 415: continue;
416: /* remove write handle */
1.4 misho 417: #ifdef HAVE_LIBPTHREAD
418: pthread_mutex_lock(&r->root_mtx[taskWRITE]);
419: #endif
1.1 misho 420: TAILQ_REMOVE(&r->root_write, task, task_node);
1.4 misho 421: #ifdef HAVE_LIBPTHREAD
422: pthread_mutex_unlock(&r->root_mtx[taskWRITE]);
423: #endif
1.3 misho 424: if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
425: if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
426: task->task_type = taskUNUSE;
1.4 misho 427: #ifdef HAVE_LIBPTHREAD
428: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
429: #endif
1.3 misho 430: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 431: #ifdef HAVE_LIBPTHREAD
432: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
433: #endif
1.3 misho 434: } else {
435: task->task_type = taskREADY;
1.4 misho 436: #ifdef HAVE_LIBPTHREAD
437: pthread_mutex_lock(&r->root_mtx[taskREADY]);
438: #endif
1.3 misho 439: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 440: #ifdef HAVE_LIBPTHREAD
441: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
442: #endif
1.3 misho 443: }
444: } else {
1.2 misho 445: task->task_type = taskREADY;
1.4 misho 446: #ifdef HAVE_LIBPTHREAD
447: pthread_mutex_lock(&r->root_mtx[taskREADY]);
448: #endif
1.2 misho 449: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 450: #ifdef HAVE_LIBPTHREAD
451: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
452: #endif
1.3 misho 453: }
1.1 misho 454: break;
455: }
456: break;
1.7 ! misho 457: case EVFILT_TIMER:
! 458: TAILQ_FOREACH_SAFE(task, &r->root_alarm, task_node, tmp) {
! 459: if ((uintptr_t) TASK_DATA(task) != ((uintptr_t) res[i].udata))
! 460: continue;
! 461: /* remove alarm handle */
! 462: #ifdef HAVE_LIBPTHREAD
! 463: pthread_mutex_lock(&r->root_mtx[taskALARM]);
! 464: #endif
! 465: TAILQ_REMOVE(&r->root_alarm, task, task_node);
! 466: #ifdef HAVE_LIBPTHREAD
! 467: pthread_mutex_unlock(&r->root_mtx[taskALARM]);
! 468: #endif
! 469: task->task_type = taskREADY;
! 470: #ifdef HAVE_LIBPTHREAD
! 471: pthread_mutex_lock(&r->root_mtx[taskREADY]);
! 472: #endif
! 473: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
! 474: #ifdef HAVE_LIBPTHREAD
! 475: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
! 476: #endif
! 477: break;
! 478: }
! 479: break;
1.1 misho 480: }
1.4 misho 481: if (kevent(r->root_kq, evt, 1, NULL, 0, &now) == -1) {
1.3 misho 482: if (r->root_hooks.hook_exec.exception) {
483: if (r->root_hooks.hook_exec.exception(r, NULL))
484: return NULL;
485: } else
486: LOGERR;
487: }
1.1 misho 488: }
489:
1.2 misho 490: /* timer update & put in ready queue */
1.4 misho 491: clock_gettime(CLOCK_MONOTONIC, &now);
1.1 misho 492:
1.6 misho 493: TAILQ_FOREACH_SAFE(task, &r->root_timer, task_node, tmp)
1.4 misho 494: if (sched_timespeccmp(&now, &TASK_TS(task), -) >= 0) {
495: #ifdef HAVE_LIBPTHREAD
496: pthread_mutex_lock(&r->root_mtx[taskTIMER]);
497: #endif
1.1 misho 498: TAILQ_REMOVE(&r->root_timer, task, task_node);
1.4 misho 499: #ifdef HAVE_LIBPTHREAD
500: pthread_mutex_unlock(&r->root_mtx[taskTIMER]);
501: #endif
1.1 misho 502: task->task_type = taskREADY;
1.4 misho 503: #ifdef HAVE_LIBPTHREAD
504: pthread_mutex_lock(&r->root_mtx[taskREADY]);
505: #endif
1.1 misho 506: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 507: #ifdef HAVE_LIBPTHREAD
508: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
509: #endif
1.1 misho 510: }
511:
512: /* put eventlo priority task to ready queue, if there is no ready task or
513: reach max missed fetch-rotate */
514: if ((task = TAILQ_FIRST(&r->root_eventlo))) {
515: if (!TAILQ_FIRST(&r->root_ready) || r->root_eventlo_miss > MAX_EVENTLO_MISS) {
516: r->root_eventlo_miss = 0;
517:
1.4 misho 518: #ifdef HAVE_LIBPTHREAD
519: pthread_mutex_lock(&r->root_mtx[taskEVENTLO]);
520: #endif
1.1 misho 521: TAILQ_REMOVE(&r->root_eventlo, task, task_node);
1.4 misho 522: #ifdef HAVE_LIBPTHREAD
523: pthread_mutex_unlock(&r->root_mtx[taskEVENTLO]);
524: #endif
1.1 misho 525: task->task_type = taskREADY;
1.4 misho 526: #ifdef HAVE_LIBPTHREAD
527: pthread_mutex_lock(&r->root_mtx[taskREADY]);
528: #endif
1.1 misho 529: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
1.4 misho 530: #ifdef HAVE_LIBPTHREAD
531: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
532: #endif
1.1 misho 533: } else
534: r->root_eventlo_miss++;
535: } else
536: r->root_eventlo_miss = 0;
537:
538: /* OK, lets get ready task !!! */
1.6 misho 539: task = TAILQ_FIRST(&r->root_ready);
540: if (!(task))
541: return NULL;
542:
1.4 misho 543: #ifdef HAVE_LIBPTHREAD
544: pthread_mutex_lock(&r->root_mtx[taskREADY]);
545: #endif
1.1 misho 546: TAILQ_REMOVE(&r->root_ready, task, task_node);
1.4 misho 547: #ifdef HAVE_LIBPTHREAD
548: pthread_mutex_unlock(&r->root_mtx[taskREADY]);
549: #endif
1.1 misho 550: task->task_type = taskUNUSE;
1.4 misho 551: #ifdef HAVE_LIBPTHREAD
552: pthread_mutex_lock(&r->root_mtx[taskUNUSE]);
553: #endif
1.1 misho 554: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
1.4 misho 555: #ifdef HAVE_LIBPTHREAD
556: pthread_mutex_unlock(&r->root_mtx[taskUNUSE]);
557: #endif
1.1 misho 558: return task;
559: }
1.3 misho 560:
561: /*
562: * sched_hook_exception() - Default EXCEPTION hook
1.5 misho 563: *
1.3 misho 564: * @root = root task
565: * @arg = custom handling: if arg == EV_EOF or other value; default: arg == NULL log errno
566: * return: <0 errors and 0 ok
567: */
568: void *
569: sched_hook_exception(void *root, void *arg)
570: {
571: sched_root_task_t *r = root;
572:
1.6 misho 573: if (!r)
1.3 misho 574: return NULL;
575:
576: /* custom exception handling ... */
577: if (arg) {
578: if (arg == (void*) EV_EOF)
579: return NULL;
580: return (void*) -1; /* raise scheduler error!!! */
581: }
582:
583: /* if error hook exists */
584: if (r->root_hooks.hook_root.error)
585: return (r->root_hooks.hook_root.error(root, (void*) ((intptr_t) errno)));
586:
587: /* default case! */
588: LOGERR;
589: return NULL;
590: }
1.5 misho 591:
592: /*
593: * sched_hook_condition() - Default CONDITION hook
594: *
595: * @root = root task
596: * @arg = killState from schedRun()
597: * return: NULL kill scheduler loop or !=NULL ok
598: */
599: void *
600: sched_hook_condition(void *root, void *arg)
601: {
602: sched_root_task_t *r = root;
603:
1.6 misho 604: if (!r)
1.5 misho 605: return NULL;
606:
607: return (void*) (r->root_cond - *(intptr_t*) arg);
608: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>