Annotation of libaitsched/src/hooks.c, revision 1.39.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.39.4.1! misho 6: * $Id: hooks.c,v 1.39 2022/12/20 22:40:32 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.39.4.1! misho 15: Copyright 2004 - 2023
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:
1.28 misho 50: #ifdef HAVE_LIBPTHREAD
51: static void *
52: _sched_threadWrapper(sched_task_t *t)
53: {
54: void *ret = NULL;
55: sched_root_task_t *r;
56:
57: if (!t || !TASK_ROOT(t))
58: pthread_exit(ret);
59: else
60: r = (sched_root_task_t*) TASK_ROOT(t);
61:
62: pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
63: /*
64: pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
65: */
66:
67: /* notify parent, thread is ready for execution */
68: pthread_testcancel();
69:
70: ret = schedCall(t);
71: r->root_ret = ret;
72:
73: if (TASK_VAL(t)) {
74: transit_task2unuse(t, &r->root_thread);
75: TASK_VAL(t) = 0;
76: }
77:
78: pthread_exit(ret);
79: }
80: #endif
81:
1.29 misho 82: #if defined(HAVE_LIBRT) && defined(HAVE_TIMER_CREATE) && \
83: defined(HAVE_TIMER_SETTIME) && defined(HAVE_TIMER_DELETE)
1.28 misho 84: #if SUP_ENABLE == KQ_SUPPORT
85: static void *
86: _sched_rtcWrapper(sched_task_t *t)
87: {
88: sched_task_t *task;
89: void *ret;
90:
91: if (!t || !TASK_ROOT(t) || !TASK_DATA(t))
92: return NULL;
93: else {
94: task = (sched_task_t*) TASK_DATA(t);
95: timer_delete((timer_t) TASK_DATLEN(t));
96: }
97:
98: ret = schedCall(task);
99:
100: transit_task2unuse(task, &(TASK_ROOT(task))->root_rtc);
101: return ret;
102: }
103: #else
104: static void
105: _sched_rtcSigWrapper(int sig, siginfo_t *si, void *uc)
106: {
107: sched_task_t *task;
108:
109: if (si && si->si_value.sival_ptr) {
110: task = (sched_task_t*) si->si_value.sival_ptr;
111: timer_delete((timer_t) TASK_FLAG(task));
112:
113: TASK_RET(task) = (intptr_t) schedCall(task);
114:
115: transit_task2unuse(task, &(TASK_ROOT(task))->root_rtc);
116: }
117: }
118: #endif
119: #endif
120:
1.1 misho 121: /*
122: * sched_hook_init() - Default INIT hook
1.5 misho 123: *
1.1 misho 124: * @root = root task
1.6 misho 125: * @arg = unused
1.1 misho 126: * return: <0 errors and 0 ok
127: */
128: void *
1.6 misho 129: sched_hook_init(void *root, void *arg __unused)
1.1 misho 130: {
131: sched_root_task_t *r = root;
132:
1.6 misho 133: if (!r)
1.1 misho 134: return (void*) -1;
135:
1.28 misho 136: #if SUP_ENABLE == KQ_SUPPORT
1.1 misho 137: r->root_kq = kqueue();
138: if (r->root_kq == -1) {
139: LOGERR;
140: return (void*) -1;
141: }
1.28 misho 142: #elif SUP_ENABLE == EP_SUPPORT
143: r->root_kq = epoll_create(KQ_EVENTS);
144: if (r->root_kq == -1) {
145: LOGERR;
146: return (void*) -1;
147: }
1.25 misho 148: #else
149: r->root_kq ^= r->root_kq;
1.38 misho 150: #endif
151:
1.25 misho 152: FD_ZERO(&r->root_fds[0]);
153: FD_ZERO(&r->root_fds[1]);
1.38 misho 154: FD_ZERO(&r->root_fds[2]);
1.1 misho 155:
156: return NULL;
157: }
158:
159: /*
160: * sched_hook_fini() - Default FINI hook
1.5 misho 161: *
1.1 misho 162: * @root = root task
163: * @arg = unused
164: * return: <0 errors and 0 ok
165: */
166: void *
167: sched_hook_fini(void *root, void *arg __unused)
168: {
169: sched_root_task_t *r = root;
170:
171: if (!r)
172: return (void*) -1;
173:
1.28 misho 174: #if SUP_ENABLE == KQ_SUPPORT || SUP_ENABLE == EP_SUPPORT
1.1 misho 175: if (r->root_kq > 2) {
176: close(r->root_kq);
177: r->root_kq = 0;
178: }
1.25 misho 179: #else
1.38 misho 180: r->root_kq ^= r->root_kq;
181: #endif
182:
183: FD_ZERO(&r->root_fds[2]);
1.25 misho 184: FD_ZERO(&r->root_fds[1]);
185: FD_ZERO(&r->root_fds[0]);
1.1 misho 186:
187: return NULL;
188: }
189:
190: /*
191: * sched_hook_cancel() - Default CANCEL hook
1.5 misho 192: *
1.1 misho 193: * @task = current task
194: * @arg = unused
195: * return: <0 errors and 0 ok
196: */
197: void *
198: sched_hook_cancel(void *task, void *arg __unused)
199: {
1.28 misho 200: sched_task_t *t = task, *tmp, *tt;
201: sched_root_task_t *r = NULL;
1.37 misho 202: int flg = 0;
1.28 misho 203: #if SUP_ENABLE == KQ_SUPPORT
1.1 misho 204: struct kevent chg[1];
1.2 misho 205: struct timespec timeout = { 0, 0 };
1.28 misho 206: #elif SUP_ENABLE == EP_SUPPORT
1.39 misho 207: struct epoll_event ee = { .events = 0, .data.u64 = 0l };
1.25 misho 208: #else
209: register int i;
210: #endif
1.11 misho 211: #ifdef AIO_SUPPORT
212: struct aiocb *acb;
213: #ifdef EVFILT_LIO
1.15 misho 214: register int i = 0;
1.11 misho 215: struct aiocb **acbs;
216: #endif /* EVFILT_LIO */
217: #endif /* AIO_SUPPORT */
1.1 misho 218:
1.6 misho 219: if (!t || !TASK_ROOT(t))
1.1 misho 220: return (void*) -1;
1.28 misho 221: else
222: r = TASK_ROOT(t);
1.1 misho 223:
1.4 misho 224: switch (TASK_TYPE(t)) {
1.1 misho 225: case taskREAD:
1.28 misho 226: /* check for multi subscribers */
227: TAILQ_FOREACH_SAFE(tt, &r->root_read, task_node, tmp)
1.37 misho 228: if (TASK_FD(tt) == TASK_FD(t))
1.28 misho 229: flg++;
230: #if SUP_ENABLE == KQ_SUPPORT
1.2 misho 231: #ifdef __NetBSD__
1.28 misho 232: EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, flg < 2 ? EV_DELETE : 0,
233: 0, 0, (intptr_t) TASK_FD(t));
1.2 misho 234: #else
1.28 misho 235: EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, flg < 2 ? EV_DELETE : 0,
236: 0, 0, (void*) TASK_FD(t));
1.2 misho 237: #endif
1.28 misho 238: #elif SUP_ENABLE == EP_SUPPORT
239: ee.data.fd = TASK_FD(t);
1.32 misho 240: ee.events ^= ee.events;
1.28 misho 241: if (FD_ISSET(TASK_FD(t), &r->root_fds[1]))
1.38 misho 242: ee.events |= EPOLLOUT;
1.28 misho 243:
1.38 misho 244: if (flg < 2) {
1.28 misho 245: FD_CLR(TASK_FD(t), &r->root_fds[0]);
1.38 misho 246: FD_CLR(TASK_FD(t), &r->root_fds[2]);
247: } else {
248: if (FD_ISSET(TASK_FD(t), &r->root_fds[0]))
249: ee.events |= EPOLLIN;
250: if (FD_ISSET(TASK_FD(t), &r->root_fds[2]))
251: ee.events |= EPOLLPRI;
252: }
1.28 misho 253: #else
254: if (flg < 2) {
255: FD_CLR(TASK_FD(t), &r->root_fds[0]);
1.38 misho 256: FD_CLR(TASK_FD(t), &r->root_fds[2]);
1.28 misho 257:
258: /* optimize select */
1.37 misho 259: for (i = r->root_kq - 1; i >= 0; i--)
1.38 misho 260: if (FD_ISSET(i, &r->root_fds[0]) ||
261: FD_ISSET(i, &r->root_fds[1]) ||
262: FD_ISSET(i, &r->root_fds[2]))
1.28 misho 263: break;
1.37 misho 264: r->root_kq = i + 1;
1.28 misho 265: }
1.25 misho 266: #endif
1.1 misho 267: break;
268: case taskWRITE:
1.28 misho 269: /* check for multi subscribers */
270: TAILQ_FOREACH_SAFE(tt, &r->root_write, task_node, tmp)
1.37 misho 271: if (TASK_FD(tt) == TASK_FD(t))
1.28 misho 272: flg++;
273: #if SUP_ENABLE == KQ_SUPPORT
1.2 misho 274: #ifdef __NetBSD__
1.28 misho 275: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, flg < 2 ? EV_DELETE : 0,
276: 0, 0, (intptr_t) TASK_FD(t));
1.2 misho 277: #else
1.28 misho 278: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, flg < 2 ? EV_DELETE : 0,
279: 0, 0, (void*) TASK_FD(t));
1.2 misho 280: #endif
1.28 misho 281: #elif SUP_ENABLE == EP_SUPPORT
282: ee.data.fd = TASK_FD(t);
1.32 misho 283: ee.events ^= ee.events;
1.28 misho 284: if (FD_ISSET(TASK_FD(t), &r->root_fds[0]))
1.38 misho 285: ee.events |= EPOLLIN;
286: if (FD_ISSET(TASK_FD(t), &r->root_fds[2]))
287: ee.events |= EPOLLPRI;
1.28 misho 288:
289: if (flg < 2)
290: FD_CLR(TASK_FD(t), &r->root_fds[1]);
291: else
292: ee.events |= EPOLLOUT;
293: #else
294: if (flg < 2) {
295: FD_CLR(TASK_FD(t), &r->root_fds[1]);
296:
297: /* optimize select */
1.37 misho 298: for (i = r->root_kq - 1; i >= 0; i--)
1.38 misho 299: if (FD_ISSET(i, &r->root_fds[0]) ||
300: FD_ISSET(i, &r->root_fds[1]) ||
301: FD_ISSET(i, &r->root_fds[2]))
1.28 misho 302: break;
1.37 misho 303: r->root_kq = i + 1;
1.28 misho 304: }
1.25 misho 305: #endif
1.1 misho 306: break;
1.7 misho 307: case taskALARM:
1.28 misho 308: #if SUP_ENABLE == KQ_SUPPORT
309: /* check for multi subscribers */
310: TAILQ_FOREACH_SAFE(tt, &r->root_alarm, task_node, tmp)
1.37 misho 311: if (TASK_DATA(tt) == TASK_DATA(t))
1.28 misho 312: flg++;
1.7 misho 313: #ifdef __NetBSD__
1.28 misho 314: EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, flg < 2 ? EV_DELETE : 0,
1.7 misho 315: 0, 0, (intptr_t) TASK_DATA(t));
316: #else
1.28 misho 317: EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, flg < 2 ? EV_DELETE : 0,
1.7 misho 318: 0, 0, (void*) TASK_DATA(t));
319: #endif
1.25 misho 320: #endif
1.8 misho 321: break;
322: case taskNODE:
1.28 misho 323: #if SUP_ENABLE == KQ_SUPPORT
324: /* check for multi subscribers */
325: TAILQ_FOREACH_SAFE(tt, &r->root_node, task_node, tmp)
1.37 misho 326: if (TASK_FD(tt) == TASK_FD(t))
1.28 misho 327: flg++;
1.8 misho 328: #ifdef __NetBSD__
1.28 misho 329: EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, flg < 2 ? EV_DELETE : 0,
330: 0, 0, (intptr_t) TASK_FD(t));
1.8 misho 331: #else
1.28 misho 332: EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, flg < 2 ? EV_DELETE : 0,
333: 0, 0, (void*) TASK_FD(t));
1.8 misho 334: #endif
1.25 misho 335: #endif
1.8 misho 336: break;
337: case taskPROC:
1.28 misho 338: #if SUP_ENABLE == KQ_SUPPORT
339: /* check for multi subscribers */
340: TAILQ_FOREACH_SAFE(tt, &r->root_proc, task_node, tmp)
1.37 misho 341: if (TASK_VAL(tt) == TASK_VAL(t))
1.28 misho 342: flg++;
1.8 misho 343: #ifdef __NetBSD__
1.28 misho 344: EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, flg < 2 ? EV_DELETE : 0,
345: 0, 0, (intptr_t) TASK_VAL(t));
1.8 misho 346: #else
1.28 misho 347: EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, flg < 2 ? EV_DELETE : 0,
348: 0, 0, (void*) TASK_VAL(t));
1.8 misho 349: #endif
1.25 misho 350: #endif
1.8 misho 351: break;
352: case taskSIGNAL:
1.28 misho 353: /* check for multi subscribers */
354: TAILQ_FOREACH_SAFE(tt, &r->root_signal, task_node, tmp)
1.37 misho 355: if (TASK_VAL(tt) == TASK_VAL(t))
1.28 misho 356: flg++;
1.39.4.1! misho 357: #if SUP_ENABLE == KQ_SUPPORT
1.8 misho 358: #ifdef __NetBSD__
1.28 misho 359: EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, flg < 2 ? EV_DELETE : 0,
360: 0, 0, (intptr_t) TASK_VAL(t));
1.8 misho 361: #else
1.28 misho 362: EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, flg < 2 ? EV_DELETE : 0,
363: 0, 0, (void*) TASK_VAL(t));
1.8 misho 364: #endif
1.18 misho 365: /* restore signal */
1.28 misho 366: if (flg < 2)
367: signal(TASK_VAL(t), SIG_DFL);
1.39.4.1! misho 368: #else
! 369: if (flg < 2)
! 370: sigdelset(&TASK_ROOT(t)->root_sigset, TASK_VAL(t));
1.25 misho 371: #endif
1.8 misho 372: break;
1.11 misho 373: #ifdef AIO_SUPPORT
374: case taskAIO:
1.28 misho 375: #if SUP_ENABLE == KQ_SUPPORT
376: /* check for multi subscribers */
377: TAILQ_FOREACH_SAFE(tt, &r->root_aio, task_node, tmp)
1.37 misho 378: if (TASK_VAL(tt) == TASK_VAL(t))
1.28 misho 379: flg++;
1.11 misho 380: #ifdef __NetBSD__
1.28 misho 381: EV_SET(&chg[0], TASK_VAL(t), EVFILT_AIO, flg < 2 ? EV_DELETE : 0,
382: 0, 0, (intptr_t) TASK_VAL(t));
1.11 misho 383: #else
1.28 misho 384: EV_SET(&chg[0], TASK_VAL(t), EVFILT_AIO, flg < 2 ? EV_DELETE : 0,
385: 0, 0, (void*) TASK_VAL(t));
1.11 misho 386: #endif
387: acb = (struct aiocb*) TASK_VAL(t);
388: if (acb) {
389: if (aio_cancel(acb->aio_fildes, acb) == AIO_CANCELED)
390: aio_return(acb);
1.37 misho 391: e_free(acb);
1.11 misho 392: TASK_VAL(t) = 0;
393: }
1.25 misho 394: #endif
1.11 misho 395: break;
396: #ifdef EVFILT_LIO
397: case taskLIO:
1.28 misho 398: #if SUP_ENABLE == KQ_SUPPORT
399: /* check for multi subscribers */
400: TAILQ_FOREACH_SAFE(tt, &r->root_lio, task_node, tmp)
1.37 misho 401: if (TASK_VAL(tt) == TASK_VAL(t))
1.28 misho 402: flg++;
1.11 misho 403: #ifdef __NetBSD__
1.28 misho 404: EV_SET(&chg[0], TASK_VAL(t), EVFILT_LIO, flg < 2 ? EV_DELETE : 0,
405: 0, 0, (intptr_t) TASK_VAL(t));
1.11 misho 406: #else
1.28 misho 407: EV_SET(&chg[0], TASK_VAL(t), EVFILT_LIO, flg < 2 ? EV_DELETE : 0,
408: 0, 0, (void*) TASK_VAL(t));
1.11 misho 409: #endif
410: acbs = (struct aiocb**) TASK_VAL(t);
411: if (acbs) {
412: for (i = 0; i < TASK_DATLEN(t); i++) {
413: if (aio_cancel(acbs[i]->aio_fildes, acbs[i]) == AIO_CANCELED)
414: aio_return(acbs[i]);
1.37 misho 415: e_free(acbs[i]);
1.11 misho 416: }
1.37 misho 417: e_free(acbs);
1.11 misho 418: TASK_VAL(t) = 0;
419: }
1.25 misho 420: #endif
1.11 misho 421: break;
422: #endif /* EVFILT_LIO */
423: #endif /* AIO_SUPPORT */
1.8 misho 424: #ifdef EVFILT_USER
425: case taskUSER:
1.28 misho 426: #if SUP_ENABLE == KQ_SUPPORT
427: /* check for multi subscribers */
428: TAILQ_FOREACH_SAFE(tt, &r->root_user, task_node, tmp)
1.37 misho 429: if (TASK_VAL(tt) == TASK_VAL(t))
1.28 misho 430: flg++;
1.8 misho 431: #ifdef __NetBSD__
1.28 misho 432: EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, flg < 2 ? EV_DELETE : 0,
433: 0, 0, (intptr_t) TASK_VAL(t));
1.8 misho 434: #else
1.28 misho 435: EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, flg < 2 ? EV_DELETE : 0,
436: 0, 0, (void*) TASK_VAL(t));
1.8 misho 437: #endif
1.25 misho 438: #endif
1.10 misho 439: break;
1.19 misho 440: #endif /* EVFILT_USER */
1.14 misho 441: case taskTHREAD:
442: #ifdef HAVE_LIBPTHREAD
1.28 misho 443: if (TASK_VAL(t)) {
444: pthread_cancel((pthread_t) TASK_VAL(t));
445: pthread_join((pthread_t) TASK_VAL(t), NULL);
446: if (TASK_VAL(t)) {
447: transit_task2unuse(t, &(TASK_ROOT(t))->root_thread);
448: TASK_VAL(t) = 0;
449: }
450: }
1.14 misho 451: #endif
1.19 misho 452: return NULL;
1.29 misho 453: #if defined(HAVE_LIBRT) && defined(HAVE_TIMER_CREATE) && \
454: defined(HAVE_TIMER_SETTIME) && defined(HAVE_TIMER_DELETE)
1.19 misho 455: case taskRTC:
456: timer_delete((timer_t) TASK_FLAG(t));
1.28 misho 457: #if SUP_ENABLE == KQ_SUPPORT
1.19 misho 458: schedCancel((sched_task_t*) TASK_RET(t));
1.28 misho 459: #else
460: /* check for multi subscribers */
461: TAILQ_FOREACH_SAFE(tt, &r->root_rtc, task_node, tmp)
1.37 misho 462: if (TASK_DATA(tt) == TASK_DATA(t))
1.28 misho 463: flg++;
464:
465: /* restore signal */
466: if (flg < 2)
467: signal((intptr_t) TASK_DATA(t) + SIGRTMIN, SIG_DFL);
468: #endif
1.19 misho 469: return NULL;
470: #endif /* HAVE_TIMER_CREATE */
1.1 misho 471: default:
1.8 misho 472: return NULL;
1.1 misho 473: }
474:
1.28 misho 475: #if SUP_ENABLE == KQ_SUPPORT
476: kevent(r->root_kq, chg, 1, NULL, 0, &timeout);
477: #elif SUP_ENABLE == EP_SUPPORT
1.37 misho 478: if (TASK_TYPE(t) == taskREAD || TASK_TYPE(t) == taskWRITE) {
479: epoll_ctl(r->root_kq, ee.events ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, ee.data.fd, &ee);
480: }
1.25 misho 481: #endif
1.1 misho 482: return NULL;
483: }
484:
1.14 misho 485: #ifdef HAVE_LIBPTHREAD
486: /*
487: * sched_hook_thread() - Default THREAD hook
488: *
489: * @task = current task
490: * @arg = pthread attributes
491: * return: <0 errors and 0 ok
492: */
493: void *
494: sched_hook_thread(void *task, void *arg)
495: {
496: sched_task_t *t = task;
497: pthread_t tid;
1.15 misho 498: sigset_t s, o;
1.14 misho 499:
500: if (!t || !TASK_ROOT(t))
501: return (void*) -1;
502:
1.15 misho 503: sigfillset(&s);
504: pthread_sigmask(SIG_BLOCK, &s, &o);
1.28 misho 505: errno = pthread_create(&tid, (pthread_attr_t*) arg,
506: (void *(*)(void*)) _sched_threadWrapper, t);
507: pthread_sigmask(SIG_SETMASK, &o, NULL);
508:
509: if (errno) {
1.14 misho 510: LOGERR;
511: return (void*) -1;
1.15 misho 512: } else
513: TASK_VAL(t) = (u_long) tid;
1.14 misho 514:
515: if (!TASK_ISLOCKED(t))
516: TASK_LOCK(t);
517:
518: return NULL;
519: }
520: #endif
521:
1.1 misho 522: /*
523: * sched_hook_read() - Default READ hook
1.5 misho 524: *
1.1 misho 525: * @task = current task
526: * @arg = unused
527: * return: <0 errors and 0 ok
528: */
529: void *
1.38 misho 530: sched_hook_read(void *task, void *arg)
1.1 misho 531: {
532: sched_task_t *t = task;
1.28 misho 533: sched_root_task_t *r = NULL;
1.38 misho 534: uintptr_t mask = (uintptr_t) arg;
1.28 misho 535: #if SUP_ENABLE == KQ_SUPPORT
1.1 misho 536: struct kevent chg[1];
1.2 misho 537: struct timespec timeout = { 0, 0 };
1.28 misho 538: #elif SUP_ENABLE == EP_SUPPORT
1.39 misho 539: struct epoll_event ee = { 0 };
1.28 misho 540: int flg = 0;
1.25 misho 541: #endif
1.1 misho 542:
1.6 misho 543: if (!t || !TASK_ROOT(t))
1.1 misho 544: return (void*) -1;
1.28 misho 545: else
546: r = TASK_ROOT(t);
1.1 misho 547:
1.28 misho 548: #if SUP_ENABLE == KQ_SUPPORT
1.2 misho 549: #ifdef __NetBSD__
1.38 misho 550: EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD | EV_CLEAR | mask,
551: 0, 0, (intptr_t) TASK_FD(t));
1.2 misho 552: #else
1.38 misho 553: EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD | EV_CLEAR | mask,
554: 0, 0, (void*) TASK_FD(t));
1.2 misho 555: #endif
1.28 misho 556: if (kevent(r->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
557: if (r->root_hooks.hook_exec.exception)
558: r->root_hooks.hook_exec.exception(r, NULL);
1.3 misho 559: else
560: LOGERR;
1.1 misho 561: return (void*) -1;
562: }
1.28 misho 563: #elif SUP_ENABLE == EP_SUPPORT
1.38 misho 564: if (!mask)
565: mask = EPOLLIN | EPOLLPRI;
1.32 misho 566: ee.data.fd = TASK_FD(t);
1.38 misho 567: ee.events = mask;
568: if (FD_ISSET(TASK_FD(t), &r->root_fds[2])) {
569: flg |= 4;
570: ee.events |= EPOLLPRI;
571: }
572: if (FD_ISSET(TASK_FD(t), &r->root_fds[0])) {
1.28 misho 573: flg |= 1;
1.38 misho 574: ee.events |= EPOLLIN;
575: }
1.28 misho 576: if (FD_ISSET(TASK_FD(t), &r->root_fds[1])) {
577: flg |= 2;
578: ee.events |= EPOLLOUT;
579: }
580:
581: if (epoll_ctl(r->root_kq, flg ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, TASK_FD(t), &ee) == -1) {
582: if (r->root_hooks.hook_exec.exception)
583: r->root_hooks.hook_exec.exception(r, NULL);
584: else
585: LOGERR;
586: return (void*) -1;
1.38 misho 587: } else {
588: if (mask & EPOLLIN)
589: FD_SET(TASK_FD(t), &r->root_fds[0]);
590: if (mask & EPOLLPRI)
591: FD_SET(TASK_FD(t), &r->root_fds[2]);
592: }
593: #else
594: if (!mask) {
1.28 misho 595: FD_SET(TASK_FD(t), &r->root_fds[0]);
1.38 misho 596: FD_SET(TASK_FD(t), &r->root_fds[2]);
597: } else {
598: if (mask & 1)
599: FD_SET(TASK_FD(t), &r->root_fds[0]);
600: if (mask & 2)
601: FD_SET(TASK_FD(t), &r->root_fds[2]);
602: }
603:
1.25 misho 604: if (TASK_FD(t) >= r->root_kq)
605: r->root_kq = TASK_FD(t) + 1;
606: #endif
1.1 misho 607:
608: return NULL;
609: }
610:
611: /*
612: * sched_hook_write() - Default WRITE hook
1.5 misho 613: *
1.1 misho 614: * @task = current task
615: * @arg = unused
616: * return: <0 errors and 0 ok
617: */
618: void *
1.38 misho 619: sched_hook_write(void *task, void *arg)
1.1 misho 620: {
621: sched_task_t *t = task;
1.28 misho 622: sched_root_task_t *r = NULL;
1.38 misho 623: uintptr_t mask = (uintptr_t) arg;
1.28 misho 624: #if SUP_ENABLE == KQ_SUPPORT
1.1 misho 625: struct kevent chg[1];
1.2 misho 626: struct timespec timeout = { 0, 0 };
1.28 misho 627: #elif SUP_ENABLE == EP_SUPPORT
1.39 misho 628: struct epoll_event ee = { 0 };
1.28 misho 629: int flg = 0;
1.25 misho 630: #endif
1.1 misho 631:
1.6 misho 632: if (!t || !TASK_ROOT(t))
1.1 misho 633: return (void*) -1;
1.28 misho 634: else
635: r = TASK_ROOT(t);
1.1 misho 636:
1.28 misho 637: #if SUP_ENABLE == KQ_SUPPORT
1.2 misho 638: #ifdef __NetBSD__
1.38 misho 639: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD | EV_CLEAR | mask,
640: 0, 0, (intptr_t) TASK_FD(t));
1.2 misho 641: #else
1.38 misho 642: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD | EV_CLEAR | mask,
643: 0, 0, (void*) TASK_FD(t));
1.2 misho 644: #endif
1.28 misho 645: if (kevent(r->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
646: if (r->root_hooks.hook_exec.exception)
647: r->root_hooks.hook_exec.exception(r, NULL);
1.3 misho 648: else
649: LOGERR;
1.1 misho 650: return (void*) -1;
651: }
1.28 misho 652: #elif SUP_ENABLE == EP_SUPPORT
1.38 misho 653: if (!mask)
654: mask = EPOLLOUT;
1.32 misho 655: ee.data.fd = TASK_FD(t);
1.38 misho 656: ee.events = mask;
1.32 misho 657:
1.38 misho 658: if (FD_ISSET(TASK_FD(t), &r->root_fds[2])) {
659: flg |= 4;
660: ee.events |= EPOLLPRI;
661: }
1.28 misho 662: if (FD_ISSET(TASK_FD(t), &r->root_fds[0])) {
663: flg |= 1;
1.38 misho 664: ee.events |= EPOLLIN;
1.28 misho 665: }
1.37 misho 666: if (FD_ISSET(TASK_FD(t), &r->root_fds[1])) {
1.28 misho 667: flg |= 2;
1.38 misho 668: ee.events |= EPOLLOUT;
1.37 misho 669: }
1.28 misho 670:
671: if (epoll_ctl(r->root_kq, flg ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, TASK_FD(t), &ee) == -1) {
672: if (r->root_hooks.hook_exec.exception)
673: r->root_hooks.hook_exec.exception(r, NULL);
674: else
675: LOGERR;
676: return (void*) -1;
677: } else
1.38 misho 678: if (mask & EPOLLOUT)
679: FD_SET(TASK_FD(t), &r->root_fds[1]);
680: #else
681: if (!mask)
1.28 misho 682: FD_SET(TASK_FD(t), &r->root_fds[1]);
1.38 misho 683: else
684: if (mask & 1)
685: FD_SET(TASK_FD(t), &r->root_fds[1]);
686:
1.25 misho 687: if (TASK_FD(t) >= r->root_kq)
688: r->root_kq = TASK_FD(t) + 1;
689: #endif
1.1 misho 690:
691: return NULL;
692: }
693:
694: /*
1.7 misho 695: * sched_hook_alarm() - Default ALARM hook
696: *
697: * @task = current task
698: * @arg = unused
699: * return: <0 errors and 0 ok
700: */
701: void *
702: sched_hook_alarm(void *task, void *arg __unused)
703: {
1.28 misho 704: #if SUP_ENABLE == KQ_SUPPORT
1.7 misho 705: sched_task_t *t = task;
706: struct kevent chg[1];
707: struct timespec timeout = { 0, 0 };
708:
709: if (!t || !TASK_ROOT(t))
710: return (void*) -1;
711:
712: #ifdef __NetBSD__
1.19 misho 713: EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_ADD | EV_CLEAR, 0,
1.7 misho 714: t->task_val.ts.tv_sec * 1000 + t->task_val.ts.tv_nsec / 1000000,
715: (intptr_t) TASK_DATA(t));
716: #else
1.19 misho 717: EV_SET(&chg[0], (uintptr_t) TASK_DATA(t), EVFILT_TIMER, EV_ADD | EV_CLEAR, 0,
1.7 misho 718: t->task_val.ts.tv_sec * 1000 + t->task_val.ts.tv_nsec / 1000000,
719: (void*) TASK_DATA(t));
720: #endif
721: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
722: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
723: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
724: else
725: LOGERR;
726: return (void*) -1;
727: }
728:
1.25 misho 729: #endif
1.7 misho 730: return NULL;
731: }
732:
733: /*
1.8 misho 734: * sched_hook_node() - Default NODE hook
735: *
736: * @task = current task
1.34 misho 737: * @arg = if arg == 42 then waiting for all events
1.8 misho 738: * return: <0 errors and 0 ok
739: */
740: void *
1.34 misho 741: sched_hook_node(void *task, void *arg)
1.8 misho 742: {
1.28 misho 743: #if SUP_ENABLE == KQ_SUPPORT
1.8 misho 744: sched_task_t *t = task;
745: struct kevent chg[1];
746: struct timespec timeout = { 0, 0 };
1.35 misho 747: u_int addflags = (u_int) (uintptr_t) arg;
1.8 misho 748:
749: if (!t || !TASK_ROOT(t))
750: return (void*) -1;
751:
752: #ifdef __NetBSD__
753: EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_ADD | EV_CLEAR,
754: NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB |
1.34 misho 755: NOTE_LINK | NOTE_RENAME | NOTE_REVOKE | addflags, 0, (intptr_t) TASK_FD(t));
1.8 misho 756: #else
757: EV_SET(&chg[0], TASK_FD(t), EVFILT_VNODE, EV_ADD | EV_CLEAR,
758: NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB |
1.34 misho 759: NOTE_LINK | NOTE_RENAME | NOTE_REVOKE | addflags, 0, (void*) TASK_FD(t));
1.8 misho 760: #endif
761: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
762: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
763: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
764: else
765: LOGERR;
766: return (void*) -1;
767: }
768:
1.25 misho 769: #endif
1.8 misho 770: return NULL;
771: }
772:
773: /*
774: * sched_hook_proc() - Default PROC hook
775: *
776: * @task = current task
777: * @arg = unused
778: * return: <0 errors and 0 ok
779: */
780: void *
781: sched_hook_proc(void *task, void *arg __unused)
782: {
1.28 misho 783: #if SUP_ENABLE == KQ_SUPPORT
1.8 misho 784: sched_task_t *t = task;
785: struct kevent chg[1];
786: struct timespec timeout = { 0, 0 };
787:
788: if (!t || !TASK_ROOT(t))
789: return (void*) -1;
790:
791: #ifdef __NetBSD__
792: EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_ADD | EV_CLEAR,
793: NOTE_EXIT | NOTE_FORK | NOTE_EXEC | NOTE_TRACK, 0, (intptr_t) TASK_VAL(t));
794: #else
795: EV_SET(&chg[0], TASK_VAL(t), EVFILT_PROC, EV_ADD | EV_CLEAR,
796: NOTE_EXIT | NOTE_FORK | NOTE_EXEC | NOTE_TRACK, 0, (void*) TASK_VAL(t));
797: #endif
798: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
799: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
800: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
801: else
802: LOGERR;
803: return (void*) -1;
804: }
805:
1.25 misho 806: #endif
1.8 misho 807: return NULL;
808: }
809:
810: /*
811: * sched_hook_signal() - Default SIGNAL hook
812: *
813: * @task = current task
814: * @arg = unused
815: * return: <0 errors and 0 ok
816: */
817: void *
818: sched_hook_signal(void *task, void *arg __unused)
819: {
820: sched_task_t *t = task;
1.39.4.1! misho 821:
! 822: #if SUP_ENABLE == KQ_SUPPORT
1.8 misho 823: struct kevent chg[1];
824: struct timespec timeout = { 0, 0 };
825:
826: if (!t || !TASK_ROOT(t))
827: return (void*) -1;
828:
1.18 misho 829: /* ignore signal */
830: signal(TASK_VAL(t), SIG_IGN);
831:
1.8 misho 832: #ifdef __NetBSD__
1.19 misho 833: EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_ADD | EV_CLEAR, 0, 0, (intptr_t) TASK_VAL(t));
1.8 misho 834: #else
1.19 misho 835: EV_SET(&chg[0], TASK_VAL(t), EVFILT_SIGNAL, EV_ADD | EV_CLEAR, 0, 0, (void*) TASK_VAL(t));
1.8 misho 836: #endif
837: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
838: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
839: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
840: else
841: LOGERR;
842: return (void*) -1;
843: }
1.39.4.1! misho 844: #else
! 845: sigaddset(&TASK_ROOT(t)->root_sigset, TASK_VAL(t));
1.25 misho 846: #endif
1.39.4.1! misho 847:
1.8 misho 848: return NULL;
849: }
850:
851: /*
852: * sched_hook_user() - Default USER hook
853: *
854: * @task = current task
855: * @arg = unused
856: * return: <0 errors and 0 ok
857: */
858: #ifdef EVFILT_USER
859: void *
860: sched_hook_user(void *task, void *arg __unused)
861: {
1.28 misho 862: #if SUP_ENABLE == KQ_SUPPORT
1.8 misho 863: sched_task_t *t = task;
864: struct kevent chg[1];
865: struct timespec timeout = { 0, 0 };
866:
867: if (!t || !TASK_ROOT(t))
868: return (void*) -1;
869:
870: #ifdef __NetBSD__
871: EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_ADD | EV_CLEAR, TASK_DATLEN(t),
872: 0, (intptr_t) TASK_VAL(t));
873: #else
874: EV_SET(&chg[0], TASK_VAL(t), EVFILT_USER, EV_ADD | EV_CLEAR, TASK_DATLEN(t),
875: 0, (void*) TASK_VAL(t));
876: #endif
877: if (kevent(TASK_ROOT(t)->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
878: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
879: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
880: else
881: LOGERR;
882: return (void*) -1;
883: }
884:
1.25 misho 885: #endif
1.8 misho 886: return NULL;
887: }
888: #endif
889:
1.28 misho 890: #if SUP_ENABLE == KQ_SUPPORT
891: static inline void
892: fetch_hook_kevent_proceed(int en, struct kevent *res, sched_root_task_t *r)
1.1 misho 893: {
1.28 misho 894: struct kevent evt[1];
1.35 misho 895: register int i, flg;
1.6 misho 896: sched_task_t *task, *tmp;
1.28 misho 897: struct timespec now = { 0, 0 };
1.11 misho 898: #ifdef AIO_SUPPORT
899: int len, fd;
900: struct aiocb *acb;
901: #ifdef EVFILT_LIO
902: int l;
903: off_t off;
904: struct aiocb **acbs;
905: struct iovec *iv;
906: #endif /* EVFILT_LIO */
907: #endif /* AIO_SUPPORT */
1.1 misho 908:
909: for (i = 0; i < en; i++) {
910: memcpy(evt, &res[i], sizeof evt);
911: evt->flags = EV_DELETE;
912: /* Put read/write task to ready queue */
1.35 misho 913: flg = 0;
1.1 misho 914: switch (res[i].filter) {
915: case EVFILT_READ:
1.6 misho 916: TAILQ_FOREACH_SAFE(task, &r->root_read, task_node, tmp) {
1.32 misho 917: if (TASK_FD(task) == ((intptr_t) res[i].udata)) {
1.35 misho 918: if (!flg) {
919: TASK_RET(task) = res[i].data;
920: TASK_FLAG(task) = (u_long) res[i].fflags;
921:
922: /* remove read handle */
923: remove_task_from(task, &r->root_read);
924:
925: if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
926: if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
927: task->task_type = taskUNUSE;
928: insert_task_to(task, &r->root_unuse);
929: } else {
930: task->task_type = taskREADY;
931: insert_task_to(task, &r->root_ready);
932: }
1.32 misho 933: } else {
934: task->task_type = taskREADY;
935: insert_task_to(task, &r->root_ready);
936: }
1.3 misho 937: }
1.35 misho 938: flg++;
1.3 misho 939: }
1.1 misho 940: }
941: break;
942: case EVFILT_WRITE:
1.6 misho 943: TAILQ_FOREACH_SAFE(task, &r->root_write, task_node, tmp) {
1.32 misho 944: if (TASK_FD(task) == ((intptr_t) res[i].udata)) {
1.35 misho 945: if (!flg) {
946: TASK_RET(task) = res[i].data;
947: TASK_FLAG(task) = (u_long) res[i].fflags;
948:
949: /* remove write handle */
950: remove_task_from(task, &r->root_write);
951:
952: if (r->root_hooks.hook_exec.exception && res[i].flags & EV_EOF) {
953: if (r->root_hooks.hook_exec.exception(r, (void*) EV_EOF)) {
954: task->task_type = taskUNUSE;
955: insert_task_to(task, &r->root_unuse);
956: } else {
957: task->task_type = taskREADY;
958: insert_task_to(task, &r->root_ready);
959: }
1.32 misho 960: } else {
961: task->task_type = taskREADY;
962: insert_task_to(task, &r->root_ready);
963: }
1.3 misho 964: }
1.35 misho 965: flg++;
1.3 misho 966: }
1.1 misho 967: }
968: break;
1.7 misho 969: case EVFILT_TIMER:
970: TAILQ_FOREACH_SAFE(task, &r->root_alarm, task_node, tmp) {
1.32 misho 971: if ((uintptr_t) TASK_DATA(task) == ((uintptr_t) res[i].udata)) {
1.35 misho 972: if (!flg) {
973: TASK_RET(task) = res[i].data;
974: TASK_FLAG(task) = (u_long) res[i].fflags;
1.32 misho 975:
1.35 misho 976: /* remove alarm handle */
977: transit_task2ready(task, &r->root_alarm);
978: }
979: flg++;
1.14 misho 980: }
1.7 misho 981: }
982: break;
1.8 misho 983: case EVFILT_VNODE:
984: TAILQ_FOREACH_SAFE(task, &r->root_node, task_node, tmp) {
1.32 misho 985: if (TASK_FD(task) == ((intptr_t) res[i].udata)) {
1.35 misho 986: if (!flg) {
987: TASK_RET(task) = res[i].data;
988: TASK_FLAG(task) = (u_long) res[i].fflags;
1.32 misho 989:
1.35 misho 990: /* remove node handle */
991: transit_task2ready(task, &r->root_node);
992: }
993: flg++;
1.8 misho 994: }
995: }
996: break;
997: case EVFILT_PROC:
998: TAILQ_FOREACH_SAFE(task, &r->root_proc, task_node, tmp) {
1.32 misho 999: if (TASK_VAL(task) == ((uintptr_t) res[i].udata)) {
1.35 misho 1000: if (!flg) {
1001: TASK_RET(task) = res[i].data;
1002: TASK_FLAG(task) = (u_long) res[i].fflags;
1.32 misho 1003:
1.35 misho 1004: /* remove proc handle */
1005: transit_task2ready(task, &r->root_proc);
1006: }
1007: flg++;
1.8 misho 1008: }
1009: }
1010: break;
1011: case EVFILT_SIGNAL:
1012: TAILQ_FOREACH_SAFE(task, &r->root_signal, task_node, tmp) {
1.32 misho 1013: if (TASK_VAL(task) == ((uintptr_t) res[i].udata)) {
1.35 misho 1014: if (!flg) {
1015: TASK_RET(task) = res[i].data;
1016: TASK_FLAG(task) = (u_long) res[i].fflags;
1.32 misho 1017:
1.35 misho 1018: /* remove signal handle */
1019: transit_task2ready(task, &r->root_signal);
1020: }
1021: flg++;
1.14 misho 1022: }
1.8 misho 1023: }
1024: break;
1.11 misho 1025: #ifdef AIO_SUPPORT
1026: case EVFILT_AIO:
1027: TAILQ_FOREACH_SAFE(task, &r->root_aio, task_node, tmp) {
1028: acb = (struct aiocb*) TASK_VAL(task);
1.32 misho 1029: if (acb == ((struct aiocb*) res[i].udata)) {
1.35 misho 1030: if (!flg) {
1031: TASK_RET(task) = res[i].data;
1032: TASK_FLAG(task) = (u_long) res[i].fflags;
1033:
1034: /* remove user handle */
1035: transit_task2ready(task, &r->root_aio);
1036:
1037: fd = acb->aio_fildes;
1038: if ((len = aio_return(acb)) != -1) {
1039: if (lseek(fd, acb->aio_offset + len, SEEK_CUR) == -1)
1040: LOGERR;
1041: } else
1.32 misho 1042: LOGERR;
1.37 misho 1043: e_free(acb);
1.35 misho 1044: TASK_DATLEN(task) = (u_long) len;
1045: TASK_FD(task) = fd;
1046: }
1047: flg++;
1.14 misho 1048: }
1.11 misho 1049: }
1050: break;
1051: #ifdef EVFILT_LIO
1052: case EVFILT_LIO:
1053: TAILQ_FOREACH_SAFE(task, &r->root_lio, task_node, tmp) {
1054: acbs = (struct aiocb**) TASK_VAL(task);
1.32 misho 1055: if (acbs == ((struct aiocb**) res[i].udata)) {
1.35 misho 1056: if (!flg) {
1057: TASK_RET(task) = res[i].data;
1058: TASK_FLAG(task) = (u_long) res[i].fflags;
1059:
1060: /* remove user handle */
1061: transit_task2ready(task, &r->root_lio);
1062:
1063: iv = (struct iovec*) TASK_DATA(task);
1064: fd = acbs[0]->aio_fildes;
1065: off = acbs[0]->aio_offset;
1066: for (len = 0; i < TASK_DATLEN(task); len += l, i++) {
1067: if ((iv[i].iov_len = aio_return(acbs[i])) == -1)
1068: l = 0;
1069: else
1070: l = iv[i].iov_len;
1.37 misho 1071: e_free(acbs[i]);
1.35 misho 1072: }
1.37 misho 1073: e_free(acbs);
1.35 misho 1074: TASK_DATLEN(task) = (u_long) len;
1075: TASK_FD(task) = fd;
1.28 misho 1076:
1.35 misho 1077: if (lseek(fd, off + len, SEEK_CUR) == -1)
1078: LOGERR;
1.32 misho 1079: }
1.35 misho 1080: flg++;
1.11 misho 1081: }
1082: }
1083: break;
1084: #endif /* EVFILT_LIO */
1085: #endif /* AIO_SUPPORT */
1.8 misho 1086: #ifdef EVFILT_USER
1087: case EVFILT_USER:
1088: TAILQ_FOREACH_SAFE(task, &r->root_user, task_node, tmp) {
1.32 misho 1089: if (TASK_VAL(task) == ((uintptr_t) res[i].udata)) {
1.35 misho 1090: if (!flg) {
1091: TASK_RET(task) = res[i].data;
1092: TASK_FLAG(task) = (u_long) res[i].fflags;
1.32 misho 1093:
1.35 misho 1094: /* remove user handle */
1095: transit_task2ready(task, &r->root_user);
1096: }
1097: flg++;
1.8 misho 1098: }
1099: }
1100: break;
1.11 misho 1101: #endif /* EVFILT_USER */
1.1 misho 1102: }
1.28 misho 1103:
1.35 misho 1104: if (flg > 1)
1105: evt->flags &= ~EV_DELETE;
1106:
1.4 misho 1107: if (kevent(r->root_kq, evt, 1, NULL, 0, &now) == -1) {
1.28 misho 1108: if (r->root_hooks.hook_exec.exception)
1109: r->root_hooks.hook_exec.exception(r, NULL);
1110: else
1111: LOGERR;
1112: }
1113: }
1114: }
1115: #endif
1116:
1117: #if SUP_ENABLE == EP_SUPPORT
1118: static inline void
1119: fetch_hook_epoll_proceed(int en, struct epoll_event *res, sched_root_task_t *r)
1120: {
1.37 misho 1121: register int i, rflg, wflg;
1.28 misho 1122: int ops = EPOLL_CTL_DEL;
1.32 misho 1123: sched_task_t *t, *tmp, *task;
1.28 misho 1124: struct epoll_event evt[1];
1125:
1126: for (i = 0; i < en; i++) {
1127: memcpy(evt, &res[i], sizeof evt);
1.37 misho 1128: evt->events ^= evt->events;
1129: rflg = wflg = 0;
1.28 misho 1130:
1.37 misho 1131: if (res[i].events & (EPOLLIN | EPOLLPRI)) {
1.32 misho 1132: task = NULL;
1133: TAILQ_FOREACH_SAFE(t, &r->root_read, task_node, tmp) {
1134: if (TASK_FD(t) == evt->data.fd) {
1.37 misho 1135: if (!task)
1.32 misho 1136: task = t;
1.37 misho 1137: rflg++;
1.32 misho 1138: }
1139: }
1.28 misho 1140:
1.37 misho 1141: if (task) {
1.32 misho 1142: TASK_FLAG(task) = ioctl(TASK_FD(task), FIONREAD, &TASK_RET(task));
1.28 misho 1143: /* remove read handle */
1144: remove_task_from(task, &r->root_read);
1145:
1146: if (r->root_hooks.hook_exec.exception && evt->events & (EPOLLRDHUP | EPOLLERR | EPOLLHUP)) {
1147: if (r->root_hooks.hook_exec.exception(r, (void*) (intptr_t)
1148: (evt->events & EPOLLERR ? EV_ERROR | EV_EOF : EV_EOF))) {
1149: task->task_type = taskUNUSE;
1150: insert_task_to(task, &r->root_unuse);
1151: } else {
1152: task->task_type = taskREADY;
1153: insert_task_to(task, &r->root_ready);
1154: }
1155: } else {
1156: task->task_type = taskREADY;
1157: insert_task_to(task, &r->root_ready);
1158: }
1.32 misho 1159:
1.37 misho 1160: if (!(res[i].events & EPOLLOUT) && FD_ISSET(evt->data.fd, &r->root_fds[1])) {
1.32 misho 1161: evt->events |= EPOLLOUT;
1.37 misho 1162: wflg = 42;
1.32 misho 1163: }
1.38 misho 1164: if (rflg > 1) {
1165: if (FD_ISSET(evt->data.fd, &r->root_fds[0]))
1166: evt->events |= EPOLLIN;
1167: if (FD_ISSET(evt->data.fd, &r->root_fds[2]))
1168: evt->events |= EPOLLPRI;
1169: } else {
1.32 misho 1170: FD_CLR(evt->data.fd, &r->root_fds[0]);
1.38 misho 1171: FD_CLR(evt->data.fd, &r->root_fds[2]);
1172: }
1.28 misho 1173: }
1.37 misho 1174: }
1175: if (res[i].events & EPOLLOUT) {
1.32 misho 1176: task = NULL;
1177: TAILQ_FOREACH_SAFE(t, &r->root_write, task_node, tmp) {
1178: if (TASK_FD(t) == evt->data.fd) {
1.37 misho 1179: if (!task)
1.32 misho 1180: task = t;
1.37 misho 1181: wflg++;
1.28 misho 1182: }
1.32 misho 1183: }
1184:
1.37 misho 1185: if (task) {
1.32 misho 1186: TASK_FLAG(task) = ioctl(TASK_FD(task), FIONWRITE, &TASK_RET(task));
1.28 misho 1187: /* remove write handle */
1188: remove_task_from(task, &r->root_write);
1189:
1190: if (r->root_hooks.hook_exec.exception && evt->events & (EPOLLERR | EPOLLHUP)) {
1191: if (r->root_hooks.hook_exec.exception(r, (void*) (intptr_t)
1192: (evt->events & EPOLLERR ? EV_ERROR | EV_EOF : EV_EOF))) {
1193: task->task_type = taskUNUSE;
1194: insert_task_to(task, &r->root_unuse);
1195: } else {
1196: task->task_type = taskREADY;
1197: insert_task_to(task, &r->root_ready);
1198: }
1199: } else {
1200: task->task_type = taskREADY;
1201: insert_task_to(task, &r->root_ready);
1202: }
1.32 misho 1203:
1.38 misho 1204: if (!(res[i].events & EPOLLIN) && FD_ISSET(evt->data.fd, &r->root_fds[0])) {
1205: evt->events |= EPOLLIN;
1206: rflg = 42;
1207: }
1208: if (!(res[i].events & EPOLLPRI) && FD_ISSET(evt->data.fd, &r->root_fds[2])) {
1209: evt->events |= EPOLLPRI;
1.37 misho 1210: rflg = 42;
1.32 misho 1211: }
1.37 misho 1212: if (wflg > 1)
1.32 misho 1213: evt->events |= EPOLLOUT;
1.37 misho 1214: else
1.32 misho 1215: FD_CLR(evt->data.fd, &r->root_fds[1]);
1.28 misho 1216: }
1217: }
1218:
1.39 misho 1219: ops = EPOLL_CTL_DEL;
1.37 misho 1220: if (rflg > 1 || wflg > 1)
1221: ops = EPOLL_CTL_MOD;
1222:
1.28 misho 1223: if (epoll_ctl(r->root_kq, ops, evt->data.fd, evt) == -1) {
1.3 misho 1224: if (r->root_hooks.hook_exec.exception) {
1.28 misho 1225: r->root_hooks.hook_exec.exception(r, NULL);
1.3 misho 1226: } else
1227: LOGERR;
1228: }
1.25 misho 1229: }
1.28 misho 1230: }
1231: #endif
1232:
1233: #if SUP_ENABLE == NO_SUPPORT
1234: static inline void
1235: fetch_hook_select_proceed(int en, fd_set rfd, fd_set wfd, fd_set xfd, sched_root_task_t *r)
1236: {
1.37 misho 1237: register int i, rflg, wflg;
1238: sched_task_t *t, *tmp, *task;
1.28 misho 1239:
1240: /* skip select check if return value from select is zero */
1241: if (!en)
1242: return;
1243:
1.25 misho 1244: for (i = 0; i < r->root_kq; i++) {
1.38 misho 1245: if (!FD_ISSET(i, &r->root_fds[0]) &&
1246: !FD_ISSET(i, &r->root_fds[1]) &&
1247: !FD_ISSET(i, &r->root_fds[2]))
1.37 misho 1248: continue;
1249:
1250: rflg = wflg = 0;
1251:
1.25 misho 1252: if (FD_ISSET(i, &rfd) || FD_ISSET(i, &xfd)) {
1.37 misho 1253: task = NULL;
1.32 misho 1254: TAILQ_FOREACH_SAFE(t, &r->root_read, task_node, tmp) {
1255: if (TASK_FD(t) == i) {
1.37 misho 1256: if (!task)
1.32 misho 1257: task = t;
1.37 misho 1258: rflg++;
1.25 misho 1259: }
1.32 misho 1260: }
1261:
1.37 misho 1262: if (task) {
1.32 misho 1263: TASK_FLAG(task) = ioctl(TASK_FD(task), FIONREAD, &TASK_RET(task));
1264:
1.25 misho 1265: /* remove read handle */
1.28 misho 1266: remove_task_from(task, &r->root_read);
1267:
1.25 misho 1268: if (r->root_hooks.hook_exec.exception) {
1269: if (r->root_hooks.hook_exec.exception(r, NULL)) {
1270: task->task_type = taskUNUSE;
1.28 misho 1271: insert_task_to(task, &r->root_unuse);
1.25 misho 1272: } else {
1273: task->task_type = taskREADY;
1.28 misho 1274: insert_task_to(task, &r->root_ready);
1.25 misho 1275: }
1276: } else {
1277: task->task_type = taskREADY;
1.28 misho 1278: insert_task_to(task, &r->root_ready);
1.25 misho 1279: }
1.32 misho 1280:
1281: /* remove resouce */
1.38 misho 1282: if (rflg == 1) {
1.32 misho 1283: FD_CLR(i, &r->root_fds[0]);
1.38 misho 1284: FD_CLR(i, &r->root_fds[2]);
1285: }
1.25 misho 1286: }
1.37 misho 1287: }
1288: if (FD_ISSET(i, &wfd)) {
1289: task = NULL;
1.32 misho 1290: TAILQ_FOREACH_SAFE(t, &r->root_write, task_node, tmp) {
1291: if (TASK_FD(t) == i) {
1.37 misho 1292: if (!task)
1.32 misho 1293: task = t;
1.37 misho 1294: wflg++;
1.25 misho 1295: }
1.32 misho 1296: }
1297:
1.37 misho 1298: if (task) {
1.32 misho 1299: TASK_FLAG(task) = ioctl(TASK_FD(task), FIONWRITE, &TASK_RET(task));
1300:
1.25 misho 1301: /* remove write handle */
1.28 misho 1302: remove_task_from(task, &r->root_write);
1303:
1.25 misho 1304: if (r->root_hooks.hook_exec.exception) {
1305: if (r->root_hooks.hook_exec.exception(r, NULL)) {
1306: task->task_type = taskUNUSE;
1.28 misho 1307: insert_task_to(task, &r->root_unuse);
1.25 misho 1308: } else {
1309: task->task_type = taskREADY;
1.28 misho 1310: insert_task_to(task, &r->root_ready);
1.25 misho 1311: }
1312: } else {
1313: task->task_type = taskREADY;
1.28 misho 1314: insert_task_to(task, &r->root_ready);
1.25 misho 1315: }
1.32 misho 1316:
1317: /* remove resouce */
1.37 misho 1318: if (wflg == 1)
1.32 misho 1319: FD_CLR(i, &r->root_fds[1]);
1.25 misho 1320: }
1321: }
1322: }
1323:
1324: /* optimize select */
1.37 misho 1325: for (i = r->root_kq - 1; i >= 0; i--)
1.38 misho 1326: if (FD_ISSET(i, &r->root_fds[0]) ||
1327: FD_ISSET(i, &r->root_fds[1]) ||
1328: FD_ISSET(i, &r->root_fds[2]))
1.25 misho 1329: break;
1.37 misho 1330: r->root_kq = i + 1;
1.28 misho 1331: }
1332: #endif
1333:
1334: /*
1335: * sched_hook_fetch() - Default FETCH hook
1336: *
1337: * @root = root task
1338: * @arg = unused
1339: * return: NULL error or !=NULL fetched task
1340: */
1341: void *
1342: sched_hook_fetch(void *root, void *arg __unused)
1343: {
1344: sched_root_task_t *r = root;
1345: sched_task_t *task, *tmp;
1346: struct timespec now, m, mtmp;
1347: #if SUP_ENABLE == KQ_SUPPORT
1348: struct kevent res[KQ_EVENTS];
1349: struct timespec *timeout;
1350: #elif SUP_ENABLE == EP_SUPPORT
1351: struct epoll_event res[KQ_EVENTS];
1352: u_long timeout = 0;
1353: #else
1354: struct timeval *timeout, tv;
1355: fd_set rfd, wfd, xfd;
1356: #endif
1357: int en;
1358:
1359: if (!r)
1360: return NULL;
1361:
1362: /* get new task by queue priority */
1363: while ((task = TAILQ_FIRST(&r->root_event))) {
1364: transit_task2unuse(task, &r->root_event);
1365: return task;
1366: }
1367: while ((task = TAILQ_FIRST(&r->root_ready))) {
1368: transit_task2unuse(task, &r->root_ready);
1369: return task;
1370: }
1371:
1.33 misho 1372: /* if present member of task, set NOWAIT */
1373: if (!TAILQ_FIRST(&r->root_task)) {
1374: /* timer tasks */
1.28 misho 1375: #ifdef TIMER_WITHOUT_SORT
1.33 misho 1376: clock_gettime(CLOCK_MONOTONIC, &now);
1.28 misho 1377:
1.33 misho 1378: sched_timespecclear(&r->root_wait);
1379: TAILQ_FOREACH(task, &r->root_timer, task_node) {
1380: if (!sched_timespecisset(&r->root_wait))
1381: r->root_wait = TASK_TS(task);
1382: else if (sched_timespeccmp(&TASK_TS(task), &r->root_wait, -) < 0)
1383: r->root_wait = TASK_TS(task);
1384: }
1385:
1386: if (TAILQ_FIRST(&r->root_timer)) {
1387: m = r->root_wait;
1388: sched_timespecsub(&m, &now, &mtmp);
1389: r->root_wait = mtmp;
1390: } else {
1391: /* set wait INFTIM */
1392: sched_timespecinf(&r->root_wait);
1393: }
1.28 misho 1394: #else /* ! TIMER_WITHOUT_SORT */
1.33 misho 1395: if ((task = TAILQ_FIRST(&r->root_timer))) {
1396: clock_gettime(CLOCK_MONOTONIC, &now);
1.28 misho 1397:
1.33 misho 1398: m = TASK_TS(task);
1399: sched_timespecsub(&m, &now, &mtmp);
1400: r->root_wait = mtmp;
1401: } else {
1402: /* set wait INFTIM */
1403: sched_timespecinf(&r->root_wait);
1404: }
1.28 misho 1405: #endif /* TIMER_WITHOUT_SORT */
1.33 misho 1406: } else /* no waiting for event, because we have ready task */
1.28 misho 1407: sched_timespecclear(&r->root_wait);
1408:
1409: if (r->root_wait.tv_sec != -1 && r->root_wait.tv_nsec != -1) {
1410: #if SUP_ENABLE == KQ_SUPPORT
1411: timeout = &r->root_wait;
1412: #elif SUP_ENABLE == EP_SUPPORT
1413: timeout = r->root_wait.tv_sec * 1000 + r->root_wait.tv_nsec / 1000000;
1414: #else
1415: sched_timespec2val(&r->root_wait, &tv);
1416: timeout = &tv;
1417: #endif /* KQ_SUPPORT */
1418: } else if (sched_timespecisinf(&r->root_poll))
1419: #if SUP_ENABLE == EP_SUPPORT
1420: timeout = -1;
1421: #else
1422: timeout = NULL;
1423: #endif
1424: else {
1425: #if SUP_ENABLE == KQ_SUPPORT
1426: timeout = &r->root_poll;
1427: #elif SUP_ENABLE == EP_SUPPORT
1428: timeout = r->root_poll.tv_sec * 1000 + r->root_poll.tv_nsec / 1000000;
1429: #else
1430: sched_timespec2val(&r->root_poll, &tv);
1431: timeout = &tv;
1432: #endif /* KQ_SUPPORT */
1433: }
1434:
1435: #if SUP_ENABLE == KQ_SUPPORT
1436: if ((en = kevent(r->root_kq, NULL, 0, res, KQ_EVENTS, timeout)) == -1) {
1437: #elif SUP_ENABLE == EP_SUPPORT
1438: if ((en = epoll_wait(r->root_kq, res, KQ_EVENTS, timeout)) == -1) {
1439: #else
1.38 misho 1440: xfd = r->root_fds[2];
1441: rfd = r->root_fds[0];
1.28 misho 1442: wfd = r->root_fds[1];
1443: if ((en = select(r->root_kq, &rfd, &wfd, &xfd, timeout)) == -1) {
1444: #endif /* KQ_SUPPORT */
1445: if (r->root_hooks.hook_exec.exception) {
1446: if (r->root_hooks.hook_exec.exception(r, NULL))
1447: return NULL;
1448: } else if (errno != EINTR)
1449: LOGERR;
1450: goto skip_event;
1451: }
1452:
1453: /* Go and catch the cat into pipes ... */
1454: #if SUP_ENABLE == KQ_SUPPORT
1455: /* kevent dispatcher */
1456: fetch_hook_kevent_proceed(en, res, r);
1457: #elif SUP_ENABLE == EP_SUPPORT
1458: /* epoll dispatcher */
1459: fetch_hook_epoll_proceed(en, res, r);
1460: #else
1461: /* select dispatcher */
1462: fetch_hook_select_proceed(en, rfd, wfd, xfd, r);
1463: #endif /* KQ_SUPPORT */
1.1 misho 1464:
1.24 misho 1465: skip_event:
1.2 misho 1466: /* timer update & put in ready queue */
1.4 misho 1467: clock_gettime(CLOCK_MONOTONIC, &now);
1.1 misho 1468:
1.6 misho 1469: TAILQ_FOREACH_SAFE(task, &r->root_timer, task_node, tmp)
1.28 misho 1470: if (sched_timespeccmp(&now, &TASK_TS(task), -) >= 0)
1471: transit_task2ready(task, &r->root_timer);
1.1 misho 1472:
1.12 misho 1473: /* put regular task priority task to ready queue,
1.13 misho 1474: if there is no ready task or reach max missing hit for regular task */
1.12 misho 1475: if ((task = TAILQ_FIRST(&r->root_task))) {
1.13 misho 1476: if (!TAILQ_FIRST(&r->root_ready) || r->root_miss >= TASK_VAL(task)) {
1477: r->root_miss ^= r->root_miss;
1.1 misho 1478:
1.28 misho 1479: transit_task2ready(task, &r->root_task);
1.1 misho 1480: } else
1.13 misho 1481: r->root_miss++;
1.1 misho 1482: } else
1.13 misho 1483: r->root_miss ^= r->root_miss;
1.1 misho 1484:
1485: /* OK, lets get ready task !!! */
1.6 misho 1486: task = TAILQ_FIRST(&r->root_ready);
1.28 misho 1487: if (task)
1488: transit_task2unuse(task, &r->root_ready);
1.1 misho 1489: return task;
1490: }
1.3 misho 1491:
1492: /*
1493: * sched_hook_exception() - Default EXCEPTION hook
1.5 misho 1494: *
1.3 misho 1495: * @root = root task
1496: * @arg = custom handling: if arg == EV_EOF or other value; default: arg == NULL log errno
1497: * return: <0 errors and 0 ok
1498: */
1499: void *
1500: sched_hook_exception(void *root, void *arg)
1501: {
1502: sched_root_task_t *r = root;
1503:
1.6 misho 1504: if (!r)
1.3 misho 1505: return NULL;
1506:
1507: /* custom exception handling ... */
1508: if (arg) {
1509: if (arg == (void*) EV_EOF)
1510: return NULL;
1511: return (void*) -1; /* raise scheduler error!!! */
1512: }
1513:
1514: /* if error hook exists */
1515: if (r->root_hooks.hook_root.error)
1516: return (r->root_hooks.hook_root.error(root, (void*) ((intptr_t) errno)));
1517:
1518: /* default case! */
1519: LOGERR;
1520: return NULL;
1521: }
1.5 misho 1522:
1523: /*
1524: * sched_hook_condition() - Default CONDITION hook
1525: *
1526: * @root = root task
1527: * @arg = killState from schedRun()
1528: * return: NULL kill scheduler loop or !=NULL ok
1529: */
1530: void *
1531: sched_hook_condition(void *root, void *arg)
1532: {
1533: sched_root_task_t *r = root;
1534:
1.6 misho 1535: if (!r)
1.5 misho 1536: return NULL;
1537:
1.28 misho 1538: return (void*) (*r->root_cond - *(intptr_t*) arg);
1.5 misho 1539: }
1.19 misho 1540:
1541: /*
1542: * sched_hook_rtc() - Default RTC hook
1543: *
1544: * @task = current task
1545: * @arg = unused
1546: * return: <0 errors and 0 ok
1547: */
1548: void *
1549: sched_hook_rtc(void *task, void *arg __unused)
1550: {
1.30 misho 1551: #if defined(HAVE_LIBRT) && defined(HAVE_TIMER_CREATE) && \
1552: defined(HAVE_TIMER_SETTIME) && defined(HAVE_TIMER_DELETE)
1.19 misho 1553: sched_task_t *sigt = NULL, *t = task;
1554: struct itimerspec its;
1555: struct sigevent evt;
1556: timer_t tmr;
1.28 misho 1557: #if SUP_ENABLE != KQ_SUPPORT
1558: struct sigaction sa;
1559: #endif
1.19 misho 1560:
1561: if (!t || !TASK_ROOT(t))
1562: return (void*) -1;
1563:
1564: memset(&evt, 0, sizeof evt);
1565: evt.sigev_notify = SIGEV_SIGNAL;
1.20 misho 1566: evt.sigev_signo = (intptr_t) TASK_DATA(t) + SIGRTMIN;
1.28 misho 1567: evt.sigev_value.sival_ptr = t;
1.19 misho 1568:
1569: if (timer_create(CLOCK_MONOTONIC, &evt, &tmr) == -1) {
1570: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
1571: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
1572: else
1573: LOGERR;
1574: return (void*) -1;
1575: } else
1576: TASK_FLAG(t) = (u_long) tmr;
1577:
1.28 misho 1578: #if SUP_ENABLE == KQ_SUPPORT
1.21 misho 1579: if (!(sigt = schedSignal(TASK_ROOT(t), _sched_rtcWrapper, TASK_ARG(t), evt.sigev_signo,
1580: t, (size_t) tmr))) {
1.19 misho 1581: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
1582: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
1583: else
1584: LOGERR;
1585: timer_delete(tmr);
1586: return (void*) -1;
1587: } else
1588: TASK_RET(t) = (uintptr_t) sigt;
1.28 misho 1589: #else
1590: memset(&sa, 0, sizeof sa);
1591: sigemptyset(&sa.sa_mask);
1592: sa.sa_sigaction = _sched_rtcSigWrapper;
1593: sa.sa_flags = SA_SIGINFO | SA_RESTART;
1594:
1595: if (sigaction(evt.sigev_signo, &sa, NULL) == -1) {
1596: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
1597: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
1598: else
1599: LOGERR;
1600: timer_delete(tmr);
1601: return (void*) -1;
1602: }
1603: #endif
1.19 misho 1604:
1605: memset(&its, 0, sizeof its);
1606: its.it_value.tv_sec = t->task_val.ts.tv_sec;
1607: its.it_value.tv_nsec = t->task_val.ts.tv_nsec;
1608:
1609: if (timer_settime(tmr, TIMER_RELTIME, &its, NULL) == -1) {
1610: if (TASK_ROOT(t)->root_hooks.hook_exec.exception)
1611: TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL);
1612: else
1613: LOGERR;
1614: schedCancel(sigt);
1615: timer_delete(tmr);
1616: return (void*) -1;
1617: }
1.30 misho 1618: #endif /* HAVE_TIMER_CREATE */
1.19 misho 1619: return NULL;
1620: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>