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