--- libaitsched/src/hooks.c 2014/06/03 20:42:48 1.27.2.7 +++ libaitsched/src/hooks.c 2016/09/29 13:44:23 1.31 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: hooks.c,v 1.27.2.7 2014/06/03 20:42:48 misho Exp $ +* $Id: hooks.c,v 1.31 2016/09/29 13:44:23 misho Exp $ * ************************************************************************** The ELWIX and AITNET software is distributed under the following @@ -12,7 +12,7 @@ terms: All of the documentation and software included in the ELWIX and AITNET Releases is copyrighted by ELWIX - Sofia/Bulgaria -Copyright 2004 - 2014 +Copyright 2004 - 2016 by Michael Pounov . All rights reserved. Redistribution and use in source and binary forms, with or without @@ -56,6 +56,77 @@ transit_task2ready(sched_task_t * __restrict t, sched_ insert_task_to(t, &(TASK_ROOT(t))->root_ready); } +#ifdef HAVE_LIBPTHREAD +static void * +_sched_threadWrapper(sched_task_t *t) +{ + void *ret = NULL; + sched_root_task_t *r; + + if (!t || !TASK_ROOT(t)) + pthread_exit(ret); + else + r = (sched_root_task_t*) TASK_ROOT(t); + + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + /* + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + */ + + /* notify parent, thread is ready for execution */ + pthread_testcancel(); + + ret = schedCall(t); + r->root_ret = ret; + + if (TASK_VAL(t)) { + transit_task2unuse(t, &r->root_thread); + TASK_VAL(t) = 0; + } + + pthread_exit(ret); +} +#endif + +#if defined(HAVE_LIBRT) && defined(HAVE_TIMER_CREATE) && \ + defined(HAVE_TIMER_SETTIME) && defined(HAVE_TIMER_DELETE) +#if SUP_ENABLE == KQ_SUPPORT +static void * +_sched_rtcWrapper(sched_task_t *t) +{ + sched_task_t *task; + void *ret; + + if (!t || !TASK_ROOT(t) || !TASK_DATA(t)) + return NULL; + else { + task = (sched_task_t*) TASK_DATA(t); + timer_delete((timer_t) TASK_DATLEN(t)); + } + + ret = schedCall(task); + + transit_task2unuse(task, &(TASK_ROOT(task))->root_rtc); + return ret; +} +#else +static void +_sched_rtcSigWrapper(int sig, siginfo_t *si, void *uc) +{ + sched_task_t *task; + + if (si && si->si_value.sival_ptr) { + task = (sched_task_t*) si->si_value.sival_ptr; + timer_delete((timer_t) TASK_FLAG(task)); + + TASK_RET(task) = (intptr_t) schedCall(task); + + transit_task2unuse(task, &(TASK_ROOT(task))->root_rtc); + } +} +#endif +#endif + /* * sched_hook_init() - Default INIT hook * @@ -303,7 +374,8 @@ sched_hook_cancel(void *task, void *arg __unused) 0, 0, (void*) TASK_VAL(t)); #endif /* restore signal */ - signal(TASK_VAL(t), SIG_DFL); + if (flg < 2) + signal(TASK_VAL(t), SIG_DFL); #endif break; #ifdef AIO_SUPPORT @@ -395,10 +467,25 @@ sched_hook_cancel(void *task, void *arg __unused) } #endif return NULL; -#if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME) && defined(HAVE_TIMER_DELETE) +#if defined(HAVE_LIBRT) && defined(HAVE_TIMER_CREATE) && \ + defined(HAVE_TIMER_SETTIME) && defined(HAVE_TIMER_DELETE) case taskRTC: timer_delete((timer_t) TASK_FLAG(t)); +#if SUP_ENABLE == KQ_SUPPORT schedCancel((sched_task_t*) TASK_RET(t)); +#else + /* check for multi subscribers */ + flg = 0; + TAILQ_FOREACH_SAFE(tt, &r->root_rtc, task_node, tmp) + if (TASK_DATA(tt) != TASK_DATA(t)) + continue; + else + flg++; + + /* restore signal */ + if (flg < 2) + signal((intptr_t) TASK_DATA(t) + SIGRTMIN, SIG_DFL); +#endif return NULL; #endif /* HAVE_TIMER_CREATE */ default: @@ -726,24 +813,6 @@ sched_hook_signal(void *task, void *arg __unused) LOGERR; return (void*) -1; } -#else -#if 0 - sched_task_t *t = task; - struct sigaction sa; - - memset(&sa, 0, sizeof sa); - sigemptyset(&sa.sa_mask); - sa.sa_handler = _sched_sigHandler; - sa.sa_flags = SA_RESETHAND | SA_RESTART; - - if (sigaction(TASK_VAL(t), &sa, NULL) == -1) { - if (TASK_ROOT(t)->root_hooks.hook_exec.exception) - TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL); - else - LOGERR; - return (void*) -1; - } -#endif /* 0 */ #endif return NULL; } @@ -792,7 +861,7 @@ static inline void fetch_hook_kevent_proceed(int en, struct kevent *res, sched_root_task_t *r) { struct kevent evt[1]; - register int i, flg; + register int i; sched_task_t *task, *tmp; struct timespec now = { 0, 0 }; #ifdef AIO_SUPPORT @@ -800,7 +869,6 @@ fetch_hook_kevent_proceed(int en, struct kevent *res, struct aiocb *acb; #ifdef EVFILT_LIO int l; - register int j; off_t off; struct aiocb **acbs; struct iovec *iv; @@ -813,12 +881,10 @@ fetch_hook_kevent_proceed(int en, struct kevent *res, /* Put read/write task to ready queue */ switch (res[i].filter) { case EVFILT_READ: - flg = 0; TAILQ_FOREACH_SAFE(task, &r->root_read, task_node, tmp) { if (TASK_FD(task) != ((intptr_t) res[i].udata)) continue; else { - flg++; TASK_RET(task) = res[i].data; TASK_FLAG(task) = (u_long) res[i].fflags; } @@ -838,17 +904,12 @@ fetch_hook_kevent_proceed(int en, struct kevent *res, insert_task_to(task, &r->root_ready); } } - /* if match at least 2, don't remove resouce of event */ - if (flg > 1) - evt->flags ^= evt->flags; break; case EVFILT_WRITE: - flg = 0; TAILQ_FOREACH_SAFE(task, &r->root_write, task_node, tmp) { if (TASK_FD(task) != ((intptr_t) res[i].udata)) continue; else { - flg++; TASK_RET(task) = res[i].data; TASK_FLAG(task) = (u_long) res[i].fflags; } @@ -868,87 +929,62 @@ fetch_hook_kevent_proceed(int en, struct kevent *res, insert_task_to(task, &r->root_ready); } } - /* if match at least 2, don't remove resouce of event */ - if (flg > 1) - evt->flags ^= evt->flags; break; case EVFILT_TIMER: - flg = 0; TAILQ_FOREACH_SAFE(task, &r->root_alarm, task_node, tmp) { if ((uintptr_t) TASK_DATA(task) != ((uintptr_t) res[i].udata)) continue; else { - flg++; TASK_RET(task) = res[i].data; TASK_FLAG(task) = (u_long) res[i].fflags; } /* remove alarm handle */ transit_task2ready(task, &r->root_alarm); } - /* if match at least 2, don't remove resouce of event */ - if (flg > 1) - evt->flags ^= evt->flags; break; case EVFILT_VNODE: - flg = 0; TAILQ_FOREACH_SAFE(task, &r->root_node, task_node, tmp) { if (TASK_FD(task) != ((intptr_t) res[i].udata)) continue; else { - flg++; TASK_RET(task) = res[i].data; TASK_FLAG(task) = (u_long) res[i].fflags; } /* remove node handle */ transit_task2ready(task, &r->root_node); } - /* if match at least 2, don't remove resouce of event */ - if (flg > 1) - evt->flags ^= evt->flags; break; case EVFILT_PROC: - flg = 0; TAILQ_FOREACH_SAFE(task, &r->root_proc, task_node, tmp) { if (TASK_VAL(task) != ((uintptr_t) res[i].udata)) continue; else { - flg++; TASK_RET(task) = res[i].data; TASK_FLAG(task) = (u_long) res[i].fflags; } /* remove proc handle */ transit_task2ready(task, &r->root_proc); } - /* if match at least 2, don't remove resouce of event */ - if (flg > 1) - evt->flags ^= evt->flags; break; case EVFILT_SIGNAL: - flg = 0; TAILQ_FOREACH_SAFE(task, &r->root_signal, task_node, tmp) { if (TASK_VAL(task) != ((uintptr_t) res[i].udata)) continue; else { - flg++; TASK_RET(task) = res[i].data; TASK_FLAG(task) = (u_long) res[i].fflags; } /* remove signal handle */ transit_task2ready(task, &r->root_signal); } - /* if match at least 2, don't remove resouce of event */ - if (flg > 1) - evt->flags ^= evt->flags; break; #ifdef AIO_SUPPORT case EVFILT_AIO: - flg = 0; TAILQ_FOREACH_SAFE(task, &r->root_aio, task_node, tmp) { acb = (struct aiocb*) TASK_VAL(task); if (acb != ((struct aiocb*) res[i].udata)) continue; else { - flg++; TASK_RET(task) = res[i].data; TASK_FLAG(task) = (u_long) res[i].fflags; } @@ -965,19 +1001,14 @@ fetch_hook_kevent_proceed(int en, struct kevent *res, TASK_DATLEN(task) = (u_long) len; TASK_FD(task) = fd; } - /* if match at least 2, don't remove resouce of event */ - if (flg > 1) - evt->flags ^= evt->flags; break; #ifdef EVFILT_LIO case EVFILT_LIO: - flg = 0; TAILQ_FOREACH_SAFE(task, &r->root_lio, task_node, tmp) { acbs = (struct aiocb**) TASK_VAL(task); if (acbs != ((struct aiocb**) res[i].udata)) continue; else { - flg++; TASK_RET(task) = res[i].data; TASK_FLAG(task) = (u_long) res[i].fflags; } @@ -987,7 +1018,7 @@ fetch_hook_kevent_proceed(int en, struct kevent *res, iv = (struct iovec*) TASK_DATA(task); fd = acbs[0]->aio_fildes; off = acbs[0]->aio_offset; - for (j = len = 0; i < TASK_DATLEN(task); len += l, i++) { + for (len = 0; i < TASK_DATLEN(task); len += l, i++) { if ((iv[i].iov_len = aio_return(acbs[i])) == -1) l = 0; else @@ -1001,29 +1032,21 @@ fetch_hook_kevent_proceed(int en, struct kevent *res, if (lseek(fd, off + len, SEEK_CUR) == -1) LOGERR; } - /* if match at least 2, don't remove resouce of event */ - if (flg > 1) - evt->flags ^= evt->flags; break; #endif /* EVFILT_LIO */ #endif /* AIO_SUPPORT */ #ifdef EVFILT_USER case EVFILT_USER: - flg = 0; TAILQ_FOREACH_SAFE(task, &r->root_user, task_node, tmp) { if (TASK_VAL(task) != ((uintptr_t) res[i].udata)) continue; else { - flg++; TASK_RET(task) = res[i].data; TASK_FLAG(task) = (u_long) res[i].fflags; } /* remove user handle */ transit_task2ready(task, &r->root_user); } - /* if match at least 2, don't remove resouce of event */ - if (flg > 1) - evt->flags ^= evt->flags; break; #endif /* EVFILT_USER */ } @@ -1173,8 +1196,8 @@ fetch_hook_select_proceed(int en, fd_set rfd, fd_set w insert_task_to(task, &r->root_ready); } } - /* if match equal to 1, remove resouce */ - if (flg == 1) + /* remove resouce */ + if (flg) FD_CLR(i, &r->root_fds[0]); } @@ -1204,8 +1227,8 @@ fetch_hook_select_proceed(int en, fd_set rfd, fd_set w insert_task_to(task, &r->root_ready); } } - /* if match equal to 1, remove resouce */ - if (flg == 1) + /* remove resouce */ + if (flg) FD_CLR(i, &r->root_fds[1]); } } @@ -1430,14 +1453,18 @@ sched_hook_condition(void *root, void *arg) * @arg = unused * return: <0 errors and 0 ok */ -#if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME) && defined(HAVE_TIMER_DELETE) void * sched_hook_rtc(void *task, void *arg __unused) { +#if defined(HAVE_LIBRT) && defined(HAVE_TIMER_CREATE) && \ + defined(HAVE_TIMER_SETTIME) && defined(HAVE_TIMER_DELETE) sched_task_t *sigt = NULL, *t = task; struct itimerspec its; struct sigevent evt; timer_t tmr; +#if SUP_ENABLE != KQ_SUPPORT + struct sigaction sa; +#endif if (!t || !TASK_ROOT(t)) return (void*) -1; @@ -1445,7 +1472,7 @@ sched_hook_rtc(void *task, void *arg __unused) memset(&evt, 0, sizeof evt); evt.sigev_notify = SIGEV_SIGNAL; evt.sigev_signo = (intptr_t) TASK_DATA(t) + SIGRTMIN; - evt.sigev_value.sival_ptr = TASK_DATA(t); + evt.sigev_value.sival_ptr = t; if (timer_create(CLOCK_MONOTONIC, &evt, &tmr) == -1) { if (TASK_ROOT(t)->root_hooks.hook_exec.exception) @@ -1456,6 +1483,7 @@ sched_hook_rtc(void *task, void *arg __unused) } else TASK_FLAG(t) = (u_long) tmr; +#if SUP_ENABLE == KQ_SUPPORT if (!(sigt = schedSignal(TASK_ROOT(t), _sched_rtcWrapper, TASK_ARG(t), evt.sigev_signo, t, (size_t) tmr))) { if (TASK_ROOT(t)->root_hooks.hook_exec.exception) @@ -1466,7 +1494,22 @@ sched_hook_rtc(void *task, void *arg __unused) return (void*) -1; } else TASK_RET(t) = (uintptr_t) sigt; +#else + memset(&sa, 0, sizeof sa); + sigemptyset(&sa.sa_mask); + sa.sa_sigaction = _sched_rtcSigWrapper; + sa.sa_flags = SA_SIGINFO | SA_RESTART; + if (sigaction(evt.sigev_signo, &sa, NULL) == -1) { + if (TASK_ROOT(t)->root_hooks.hook_exec.exception) + TASK_ROOT(t)->root_hooks.hook_exec.exception(TASK_ROOT(t), NULL); + else + LOGERR; + timer_delete(tmr); + return (void*) -1; + } +#endif + memset(&its, 0, sizeof its); its.it_value.tv_sec = t->task_val.ts.tv_sec; its.it_value.tv_nsec = t->task_val.ts.tv_nsec; @@ -1480,7 +1523,6 @@ sched_hook_rtc(void *task, void *arg __unused) timer_delete(tmr); return (void*) -1; } - +#endif /* HAVE_TIMER_CREATE */ return NULL; } -#endif /* HAVE_TIMER_CREATE */