Annotation of libaitsched/src/hooks.c, revision 1.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 $
! 6: * $Id: aitcrc.c,v 1.4.2.1 2011/05/10 20:48:49 misho Exp $
! 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:
! 15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
! 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
! 52: * @root = root task
! 53: * @data = optional data if !=NULL
! 54: * return: <0 errors and 0 ok
! 55: */
! 56: void *
! 57: sched_hook_init(void *root, void *data)
! 58: {
! 59: sched_root_task_t *r = root;
! 60:
! 61: if (!r || r->root_data.iov_base || r->root_data.iov_len)
! 62: return (void*) -1;
! 63:
! 64: r->root_data.iov_base = malloc(sizeof(struct sched_IO));
! 65: if (!r->root_data.iov_base) {
! 66: LOGERR;
! 67: return (void*) -1;
! 68: } else {
! 69: r->root_data.iov_len = sizeof(struct sched_IO);
! 70: memset(r->root_data.iov_base, 0, r->root_data.iov_len);
! 71: }
! 72:
! 73: r->root_kq = kqueue();
! 74: if (r->root_kq == -1) {
! 75: LOGERR;
! 76: return (void*) -1;
! 77: }
! 78:
! 79: return NULL;
! 80: }
! 81:
! 82: /*
! 83: * sched_hook_fini() - Default FINI hook
! 84: * @root = root task
! 85: * @arg = unused
! 86: * return: <0 errors and 0 ok
! 87: */
! 88: void *
! 89: sched_hook_fini(void *root, void *arg __unused)
! 90: {
! 91: sched_root_task_t *r = root;
! 92:
! 93: if (!r)
! 94: return (void*) -1;
! 95:
! 96: if (r->root_kq > 2) {
! 97: close(r->root_kq);
! 98: r->root_kq = 0;
! 99: }
! 100:
! 101: if (r->root_data.iov_base && r->root_data.iov_len) {
! 102: free(r->root_data.iov_base);
! 103: r->root_data.iov_base = NULL;
! 104: r->root_data.iov_len = 0;
! 105: }
! 106:
! 107: return NULL;
! 108: }
! 109:
! 110: /*
! 111: * sched_hook_cancel() - Default CANCEL hook
! 112: * @task = current task
! 113: * @arg = unused
! 114: * return: <0 errors and 0 ok
! 115: */
! 116: void *
! 117: sched_hook_cancel(void *task, void *arg __unused)
! 118: {
! 119: struct sched_IO *io;
! 120: sched_task_t *t = task;
! 121: struct kevent chg[1];
! 122: struct timespec timeout;
! 123:
! 124: if (!t || !t->task_root || !ROOT_DATA(t->task_root) || !ROOT_DATLEN(t->task_root))
! 125: return (void*) -1;
! 126: else
! 127: io = ROOT_DATA(t->task_root);
! 128:
! 129: timespecclear(&timeout);
! 130: switch (t->task_type) {
! 131: case taskREAD:
! 132: if (FD_ISSET(TASK_FD(t), &io->wfd))
! 133: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD, 0, 0, &TASK_FD(t));
! 134: else
! 135: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_DELETE, 0, 0, &TASK_FD(t));
! 136: kevent(t->task_root->root_kq, chg, 1, NULL, 0, &timeout);
! 137:
! 138: FD_CLR(TASK_FD(t), &io->rfd);
! 139: break;
! 140: case taskWRITE:
! 141: if (FD_ISSET(TASK_FD(t), &io->rfd))
! 142: EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD, 0, 0, &TASK_FD(t));
! 143: else
! 144: EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_DELETE, 0, 0, &TASK_FD(t));
! 145: kevent(t->task_root->root_kq, chg, 1, NULL, 0, &timeout);
! 146:
! 147: FD_CLR(TASK_FD(t), &io->wfd);
! 148: break;
! 149: default:
! 150: break;
! 151: }
! 152:
! 153: return NULL;
! 154: }
! 155:
! 156: /*
! 157: * sched_hook_read() - Default READ hook
! 158: * @task = current task
! 159: * @arg = unused
! 160: * return: <0 errors and 0 ok
! 161: */
! 162: void *
! 163: sched_hook_read(void *task, void *arg __unused)
! 164: {
! 165: struct sched_IO *io;
! 166: sched_task_t *t = task;
! 167: struct kevent chg[1];
! 168: struct timespec timeout;
! 169:
! 170: if (!t || !t->task_root || !ROOT_DATA(t->task_root) || !ROOT_DATLEN(t->task_root))
! 171: return (void*) -1;
! 172: else
! 173: io = ROOT_DATA(t->task_root);
! 174:
! 175: if (FD_ISSET(TASK_FD(t), &io->rfd))
! 176: return NULL;
! 177: else
! 178: FD_SET(TASK_FD(t), &io->rfd);
! 179:
! 180: timespecclear(&timeout);
! 181: EV_SET(&chg[0], TASK_FD(t), EVFILT_READ, EV_ADD, 0, 0, &TASK_FD(t));
! 182: if (kevent(t->task_root->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
! 183: LOGERR;
! 184: return (void*) -1;
! 185: }
! 186:
! 187: return NULL;
! 188: }
! 189:
! 190: /*
! 191: * sched_hook_write() - Default WRITE hook
! 192: * @task = current task
! 193: * @arg = unused
! 194: * return: <0 errors and 0 ok
! 195: */
! 196: void *
! 197: sched_hook_write(void *task, void *arg __unused)
! 198: {
! 199: struct sched_IO *io;
! 200: sched_task_t *t = task;
! 201: struct kevent chg[1];
! 202: struct timespec timeout;
! 203:
! 204: if (!t || !t->task_root || !ROOT_DATA(t->task_root) || !ROOT_DATLEN(t->task_root))
! 205: return (void*) -1;
! 206: else
! 207: io = ROOT_DATA(t->task_root);
! 208:
! 209: if (FD_ISSET(TASK_FD(t), &io->wfd))
! 210: return NULL;
! 211: else
! 212: FD_SET(TASK_FD(t), &io->wfd);
! 213:
! 214: timespecclear(&timeout);
! 215: EV_SET(&chg[0], TASK_FD(t), EVFILT_WRITE, EV_ADD, 0, 0, &TASK_FD(t));
! 216: if (kevent(t->task_root->root_kq, chg, 1, NULL, 0, &timeout) == -1) {
! 217: LOGERR;
! 218: return (void*) -1;
! 219: }
! 220:
! 221: return NULL;
! 222: }
! 223:
! 224: /*
! 225: * sched_hook_fetch() - Default FETCH hook
! 226: * @root = root task
! 227: * @arg = unused
! 228: * return: NULL error or !=NULL fetched task
! 229: */
! 230: void *
! 231: sched_hook_fetch(void *root, void *arg __unused)
! 232: {
! 233: struct sched_IO *io;
! 234: sched_root_task_t *r = root;
! 235: sched_task_t *task;
! 236: struct timeval now, m, mtmp;
! 237: struct timespec nw, *timeout;
! 238: struct kevent evt[1], res[KQ_EVENTS];
! 239: register int i;
! 240: int en;
! 241:
! 242: if (!r || !ROOT_DATA(r) || !ROOT_DATLEN(r))
! 243: return NULL;
! 244:
! 245: /* get new task by queue priority */
! 246: retry:
! 247: while ((task = TAILQ_FIRST(&r->root_event))) {
! 248: TAILQ_REMOVE(&r->root_event, task, task_node);
! 249: task->task_type = taskUNUSE;
! 250: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
! 251: return task;
! 252: }
! 253: while ((task = TAILQ_FIRST(&r->root_ready))) {
! 254: TAILQ_REMOVE(&r->root_ready, task, task_node);
! 255: task->task_type = taskUNUSE;
! 256: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
! 257: return task;
! 258: }
! 259:
! 260: #ifdef TIMER_WITHOUT_SORT
! 261: clock_gettime(CLOCK_MONOTONIC, &nw);
! 262: now.tv_sec = nw.tv_sec;
! 263: now.tv_usec = nw.tv_nsec / 1000;
! 264:
! 265: timerclear(&r->root_wait);
! 266: TAILQ_FOREACH(task, &r->root_timer, task_node) {
! 267: if (!timerisset(&r->root_wait))
! 268: r->root_wait = TASK_TV(task);
! 269: else if (timercmp(&TASK_TV(task), &r->root_wait, -) < 0)
! 270: r->root_wait = TASK_TV(task);
! 271: }
! 272:
! 273: if (TAILQ_FIRST(&r->root_timer)) {
! 274: m = r->root_wait;
! 275: timersub(&m, &now, &mtmp);
! 276: r->root_wait = mtmp;
! 277: } else {
! 278: /* set wait INFTIM */
! 279: r->root_wait.tv_sec = r->root_wait.tv_usec = -1;
! 280: }
! 281: #else
! 282: if (!TAILQ_FIRST(&r->root_eventlo) && (task = TAILQ_FIRST(&r->root_timer))) {
! 283: clock_gettime(CLOCK_MONOTONIC, &nw);
! 284: now.tv_sec = nw.tv_sec;
! 285: now.tv_usec = nw.tv_nsec / 1000;
! 286:
! 287: m = TASK_TV(task);
! 288: timersub(&m, &now, &mtmp);
! 289: r->root_wait = mtmp;
! 290: } else {
! 291: /* set wait INFTIM */
! 292: r->root_wait.tv_sec = r->root_wait.tv_usec = -1;
! 293: }
! 294: #endif
! 295: /* if present member of eventLo, set NOWAIT */
! 296: if (TAILQ_FIRST(&r->root_eventlo))
! 297: timerclear(&r->root_wait);
! 298:
! 299: if (r->root_wait.tv_sec != -1 && r->root_wait.tv_usec != -1) {
! 300: nw.tv_sec = r->root_wait.tv_sec;
! 301: nw.tv_nsec = r->root_wait.tv_usec * 1000;
! 302: timeout = &nw;
! 303: } else /* wait INFTIM */
! 304: timeout = NULL;
! 305: if ((en = kevent(r->root_kq, NULL, 0, res, KQ_EVENTS, timeout)) == -1) {
! 306: LOGERR;
! 307: goto retry;
! 308: }
! 309:
! 310: timespecclear(&nw);
! 311: /* Go and catch the cat into pipes ... */
! 312: for (i = 0; i < en; i++) {
! 313: memcpy(evt, &res[i], sizeof evt);
! 314: evt->flags = EV_DELETE;
! 315: /* Put read/write task to ready queue */
! 316: switch (res[i].filter) {
! 317: case EVFILT_READ:
! 318: TAILQ_FOREACH(task, &r->root_read, task_node) {
! 319: if (TASK_FD(task) != *((int*) res[i].udata))
! 320: continue;
! 321: /* remove read handle */
! 322: io = ROOT_DATA(task->task_root);
! 323: FD_CLR(TASK_FD(task), &io->rfd);
! 324:
! 325: TAILQ_REMOVE(&r->root_read, task, task_node);
! 326: task->task_type = taskREADY;
! 327: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
! 328: break;
! 329: }
! 330: break;
! 331: case EVFILT_WRITE:
! 332: TAILQ_FOREACH(task, &r->root_write, task_node) {
! 333: if (TASK_FD(task) != *((int*) res[i].udata))
! 334: continue;
! 335: /* remove write handle */
! 336: io = ROOT_DATA(task->task_root);
! 337: FD_CLR(TASK_FD(task), &io->wfd);
! 338:
! 339: TAILQ_REMOVE(&r->root_write, task, task_node);
! 340: task->task_type = taskREADY;
! 341: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
! 342: break;
! 343: }
! 344: break;
! 345: }
! 346:
! 347: if (kevent(r->root_kq, evt, 1, NULL, 0, &nw) == -1)
! 348: LOGERR;
! 349: }
! 350:
! 351: /* timer update */
! 352: clock_gettime(CLOCK_MONOTONIC, &nw);
! 353: now.tv_sec = nw.tv_sec;
! 354: now.tv_usec = nw.tv_nsec / 1000;
! 355:
! 356: TAILQ_FOREACH(task, &r->root_timer, task_node)
! 357: if (timercmp(&now, &TASK_TV(task), -) >= 0) {
! 358: TAILQ_REMOVE(&r->root_timer, task, task_node);
! 359: task->task_type = taskREADY;
! 360: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
! 361: }
! 362:
! 363: /* put eventlo priority task to ready queue, if there is no ready task or
! 364: reach max missed fetch-rotate */
! 365: if ((task = TAILQ_FIRST(&r->root_eventlo))) {
! 366: if (!TAILQ_FIRST(&r->root_ready) || r->root_eventlo_miss > MAX_EVENTLO_MISS) {
! 367: r->root_eventlo_miss = 0;
! 368:
! 369: TAILQ_REMOVE(&r->root_eventlo, task, task_node);
! 370: task->task_type = taskREADY;
! 371: TAILQ_INSERT_TAIL(&r->root_ready, task, task_node);
! 372: } else
! 373: r->root_eventlo_miss++;
! 374: } else
! 375: r->root_eventlo_miss = 0;
! 376:
! 377: /* OK, lets get ready task !!! */
! 378: if (!(task = TAILQ_FIRST(&r->root_ready)))
! 379: goto retry;
! 380: TAILQ_REMOVE(&r->root_ready, task, task_node);
! 381: task->task_type = taskUNUSE;
! 382: TAILQ_INSERT_TAIL(&r->root_unuse, task, task_node);
! 383: return task;
! 384: }
! 385:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>