void __noprof kernel_main_thread(void *data) { struct thread *me = CURRENT(); struct thread_queue tmp_q; tq_init(&tmp_q); tq_insert_head(me, &tmp_q); bug_on(!scheduler_enqueue(&tmp_q)); mach_running(); kprintf("Initializing vfs core... "); fs_init(); kprintf("Done.\n"); call_late_init(); run_tests(); load_init(); for (;;) { scheduler_yield(); arch_idle(); } bug(); }
t_status interface_scheduler_yield(o_syscall* message) { t_status error; error = scheduler_yield(); message->u.reply.error = error; return (STATUS_OK); }
int main(void) { config_clocks(); config_gpio(); scheduler_init(); /* Start running the tasks. This call will never return. */ scheduler_yield(); return 0; }
void scheduler_terminateCurrentTask() { log(LOG_DEBUG, "scheduler: Deleting current task <%s>\n", currentTask->name); if(currentTask->next == currentTask) currentTask = NULL; else { currentTask->next->last = currentTask->last; currentTask->last->next = currentTask->next; } scheduler_yield(); }
/* Fade an LED in and out in a sinusoidal fashion. */ static void blinkloop(float speed, uint16_t ledpin) { while (true) { float step; unsigned i; for (step = -3.14; step < 3.14; step += speed) { unsigned duty = 128 + 128 * quicksine(step); gpio_clear(GPIOC, ledpin); /* LED off */ for (i = 0; i < 256; i++) { if (i == duty) { gpio_set(GPIOC, ledpin); /* LED on */ } /* Let the other tasks run */ scheduler_yield(); } } } }
struct sysret sys_yield(capaddr_t target) { dispatcher_handle_t handle = dcb_current->disp; struct dispatcher_shared_generic *disp = get_dispatcher_shared_generic(handle); debug(SUBSYS_DISPATCH, "%.*s yields%s\n", DISP_NAME_LEN, disp->name, !disp->haswork && disp->lmp_delivered == disp->lmp_seen ? " and is removed from the runq" : ""); if (!disp->disabled) { printk(LOG_ERR, "SYSCALL_YIELD while enabled\n"); return SYSRET(SYS_ERR_CALLER_ENABLED); } struct capability *yield_to = NULL; if (target != CPTR_NULL) { errval_t err; /* directed yield */ err = caps_lookup_cap(&dcb_current->cspace.cap, target, CPTR_BITS, &yield_to, CAPRIGHTS_READ); if (err_is_fail(err)) { return SYSRET(err); } else if (yield_to == NULL || (yield_to->type != ObjType_EndPoint && yield_to->type != ObjType_Dispatcher)) { return SYSRET(SYS_ERR_INVALID_YIELD_TARGET); } /* FIXME: check rights? */ } disp->disabled = false; dcb_current->disabled = false; // Remove from queue when no work and no more messages and no missed wakeup systime_t wakeup = disp->wakeup; if (!disp->haswork && disp->lmp_delivered == disp->lmp_seen && (wakeup == 0 || wakeup > (kernel_now + kcb_current->kernel_off))) { trace_event(TRACE_SUBSYS_NNET, TRACE_EVENT_NNET_SCHED_REMOVE, (uint32_t)(lvaddr_t)dcb_current & 0xFFFFFFFF); trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_SCHED_REMOVE, 151); scheduler_remove(dcb_current); if (wakeup != 0) { wakeup_set(dcb_current, wakeup); } } else { // Otherwise yield for the timeslice scheduler_yield(dcb_current); } if (yield_to != NULL) { struct dcb *target_dcb = NULL; if (yield_to->type == ObjType_EndPoint) { target_dcb = yield_to->u.endpoint.listener; } else if (yield_to->type == ObjType_Dispatcher) { target_dcb = yield_to->u.dispatcher.dcb; } else { panic("invalid type in yield cap"); } trace_event(TRACE_SUBSYS_NNET, TRACE_EVENT_NNET_YIELD, (uint32_t)(lvaddr_t)target_dcb & 0xFFFFFFFF); make_runnable(target_dcb); dispatch(target_dcb); } else { // trace_event(TRACE_SUBSYS_BNET, TRACE_EVENT_BNET_YIELD, // 0); /* undirected yield */ dispatch(schedule()); } panic("Yield returned!"); }
int main(int argc, char **argv) { int tasks = 0, alltasks = MAXTASKS, runtime, quantum = 1; if(argc < 3) { printf("Usage: %s <config.cfg> <runtime> [quantum]\n", argv[0]); exit(EXIT_FAILURE); } runtime = atoi(argv[2]); if(argc >= 4) { quantum = atoi(argv[3]); } sched = malloc(sizeof(struct dcb) * runtime * alltasks); allptrs = calloc(alltasks, sizeof(struct dcb *)); FILE *f = fopen(argv[1], "r"); assert(f != NULL); bool readline = true; for(kernel_now = 0; kernel_now < runtime; kernel_now++) { unsigned long time, wcet, period, weight, id, blocktime, deadline, rd; char b[512], *r; for(;;) { if(readline) { do { r = fgets(b, 512, f); } while(r != NULL && (b[0] == '#' || b[0] == '\n')); if(r == NULL) { break; } } else { readline = true; } if((rd = sscanf(b, "%lu H %lu %lu %lu %lu", &time, &wcet, &period, &blocktime, &deadline)) >= 4) { if(time != kernel_now) { readline = false; break; } // Create new hard real-time task struct dcb *dcb = malloc(sizeof(struct dcb)); init_dcb(dcb, tasks); dcb->type = TASK_TYPE_HARD_REALTIME; dcb->wcet = wcet; dcb->period = period; dcb->blocktime = blocktime; dcb->release_time = kernel_now; snprintf(dcb->dsg.name, DISP_NAME_LEN, "h %d", tasks); if(rd == 5) { dcb->deadline = deadline; } else { dcb->deadline = period; } make_runnable(dcb); assert(tasks < MAXTASKS); allptrs[tasks++] = dcb; } else if(sscanf(b, "%lu S %lu %lu", &time, &wcet, &period) == 3) { if(time != kernel_now) { readline = false; break; } // Create new soft real-time task struct dcb *dcb = malloc(sizeof(struct dcb)); init_dcb(dcb, tasks); dcb->type = TASK_TYPE_SOFT_REALTIME; dcb->wcet = wcet; dcb->period = period; snprintf(dcb->dsg.name, DISP_NAME_LEN, "s %d", tasks); make_runnable(dcb); assert(tasks < MAXTASKS); allptrs[tasks++] = dcb; } else if(sscanf(b, "%lu B %lu", &time, &weight) == 2) { if(time != kernel_now) { readline = false; break; } // Create new best-effort task struct dcb *dcb = malloc(sizeof(struct dcb)); init_dcb(dcb, tasks); dcb->type = TASK_TYPE_BEST_EFFORT; dcb->weight = weight; snprintf(dcb->dsg.name, DISP_NAME_LEN, "b %d", tasks); make_runnable(dcb); assert(tasks < MAXTASKS); allptrs[tasks++] = dcb; } else if(sscanf(b, "%lu d %lu", &time, &id) == 2) { if(time != kernel_now) { readline = false; break; } // Delete task with given ID assert(id < MAXTASKS); scheduler_remove(allptrs[id]); } else if(sscanf(b, "%lu r %lu", &time, &id) == 2) { if(time != kernel_now) { readline = false; break; } // Re-release task with given ID assert(id < MAXTASKS); if(allptrs[id]->type != TASK_TYPE_BEST_EFFORT) { allptrs[id]->release_time = kernel_now; } make_runnable(allptrs[id]); } else if(sscanf(b, "%lu y %lu", &time, &id) == 2) { if(time != kernel_now) { readline = false; break; } // Yield task with given ID assert(id < MAXTASKS); scheduler_yield(allptrs[id]); } else if(sscanf(b, "%lu c %lu", &time, &id) == 2) { if(time != kernel_now) { readline = false; break; } // Context switch to task with given ID assert(id < MAXTASKS); dcb_current = allptrs[id]; continue; } else { fprintf(stderr, "Invalid line: %s\n", b); abort(); } dcb_current = schedule(); } for(int i = 0; i < alltasks; i++) { struct dcb *cd = allptrs[i]; if(cd != NULL) { cd->dispatched = false; #if 0 if(cd->type == TASK_TYPE_HARD_REALTIME) { if(cd->etime >= cd->blocktime) { scheduler_remove(cd); } } #endif } } if(kernel_now % quantum == 0) { dcb_current = schedule(); } if(dcb_current != NULL) { dcb_current->dispatched = true; /* printf("%4d: dispatching %2d, release time: %4lu, deadline: %4lu, period: %3lu, WCET: %3lu/%3lu\n", kernel_now, dcb_current->id, dcb_current->release_time, dcb_current->deadline, dcb_current->period, dcb_current->etime, dcb_current->wcet); */ } for(int i = 0; i < alltasks; i++) { if(allptrs[i] != NULL) { sched[kernel_now * alltasks + i] = *allptrs[i]; } } } fclose(f); // Print schedule printf(" "); for(int t = 0; t < runtime; t++) { if(t % 1000 == 0) { printf("%d", (t / 1000) % 10); } else { printf(" "); } } printf("\n"); printf(" "); for(int t = 0; t < runtime; t++) { if(t % 100 == 0) { printf("%d", (t / 100) % 10); } else { printf(" "); } } printf("\n"); printf(" "); for(int t = 0; t < runtime; t++) { if(t % 10 == 0) { printf("%d", (t / 10) % 10); } else { printf(" "); } } printf("\n"); printf(" "); for(int t = 0; t < runtime; t++) { printf("%d", t % 10); } printf("\n"); for(int i = 0; i < tasks; i++) { struct dcb *ct = allptrs[i]; printf("%c%2d: ", typechar(ct->type), i); for(int t = 0; t < runtime; t++) { struct dcb *s = &sched[t * alltasks + i]; if(s->dispatched) { printf("#"); } else { printf(" "); } } printf("\n"); printf(" "); for(int t = 0; t < runtime; t++) { struct dcb *s = &sched[t * alltasks + i]; if(s->release_time == t) { printf("r"); } else { printf(" "); } } printf("\n"); } free(sched); free(allptrs); return 0; }