static int fp_thread_params(struct sched_thd *t, char *p) { int prio, tmp; char curr = p[0]; struct sched_thd *c; assert(t); switch (curr) { case 'r': /* priority relative to current thread */ c = sched_get_current(); assert(c); tmp = atoi(&p[1]); prio = sched_get_metric(c)->priority + tmp; memcpy(sched_get_accounting(t), sched_get_accounting(c), sizeof(struct sched_accounting)); #ifdef DEFERRABLE if (sched_get_accounting(t)->T) ADD_LIST(&servers, t, sched_next, sched_prev); #endif if (prio > PRIO_LOWEST) prio = PRIO_LOWEST; break; case 'a': /* absolute priority */ prio = atoi(&p[1]); break; case 'i': /* idle thread */ prio = PRIO_LOWEST; break; case 't': /* timer thread */ prio = PRIO_HIGHEST; break; #ifdef DEFERRABLE case 'd': { prio = ds_parse_params(t, p); if (EMPTY_LIST(t, sched_next, sched_prev) && sched_get_accounting(t)->T) { ADD_LIST(&servers, t, sched_next, sched_prev); } fp_move_end_runnable(t); break; } #endif default: printc("unknown priority option @ %s, setting to low\n", p); prio = PRIO_LOW; } if (sched_thd_ready(t)) fp_rem_thd(t); fp_add_thd(t, prio); return 0; }
int thread_resparams_set(struct sched_thd *t, res_spec_t rs) { #ifdef DEFERRABLE if (rs.a < 0 || rs.w < 0 || rs.a > rs.w) return -1; sched_get_accounting(t)->C = rs.a; sched_get_accounting(t)->C_used = 0; sched_get_accounting(t)->T = rs.w; sched_get_accounting(t)->T_exp = 0; #endif return 0; }
void timer_tick(int num_ticks) { /* see time_elapsed for time mgmt */ #ifdef DEFERRABLE { struct sched_thd *t; assert(num_ticks > 0); ticks += num_ticks; for (t = FIRST_LIST(&servers, sched_next, sched_prev) ; t != &servers ; t = FIRST_LIST(t, sched_next, sched_prev)) { struct sched_accounting *sa = sched_get_accounting(t); unsigned long T_exp = sa->T_exp, T = sa->T; assert(T); if (T_exp <= ticks) { unsigned long off = T - (ticks % T); //printc("(%ld+%ld/%ld @ %ld)\n", sa->C_used, (unsigned long)sa->pol_cycles, T, T_exp); sa->T_exp = ticks + off; sa->C_used = 0; // sa->pol_cycles = 0; if (sched_thd_suspended(t)) { t->flags &= ~THD_SUSPENDED; if (sched_thd_ready(t)) { fp_add_thd(t, sched_get_metric(t)->priority); } } } } } #endif }
void time_elapsed(struct sched_thd *t, u32_t processing_time) { struct sched_accounting *sa; assert(t); sa = sched_get_accounting(t); sa->pol_cycles += processing_time; sa->cycles += processing_time; if (sa->cycles >= QUANTUM) { while (sa->cycles > QUANTUM) { sa->cycles -= QUANTUM; sa->ticks++; } /* round robin */ if (sched_thd_ready(t) && !sched_thd_suspended(t)) { assert(!sched_thd_inactive_evt(t)); assert(!sched_thd_blocked(t)); fp_move_end_runnable(t); } #ifdef DEFERRABLE #endif } if (sa->pol_cycles > QUANTUM) { sa->pol_cycles -= QUANTUM; if (sa->T) { sa->C_used++; if (sa->C_used >= sa->C) { sched_set_thd_urgency(t, NUM_PRIOS); if (sched_thd_ready(t)) fp_rem_thd(t); t->flags |= THD_SUSPENDED; } } } }
void runqueue_print(void) { struct sched_thd *t; int i = 0; printc("Core %ld: Running threads (thd, prio, ticks):\n", cos_cpuid()); for (i = 0 ; i < NUM_PRIOS ; i++) { for (t = FIRST_LIST(&PERCPU_GET(fprr_state)->priorities[i].runnable, prio_next, prio_prev) ; t != &PERCPU_GET(fprr_state)->priorities[i].runnable ; t = FIRST_LIST(t, prio_next, prio_prev)) { struct sched_accounting *sa = sched_get_accounting(t); unsigned long diff = sa->ticks - sa->prev_ticks; //if (!(diff || sa->cycles)) continue; printc("\t%d, %d, %ld+%ld/%d\n", t->id, i, diff, (unsigned long)sa->cycles, QUANTUM); sa->prev_ticks = sa->ticks; sa->cycles = 0; } } #ifdef DEFERRABLE printc("Suspended threads (thd, prio, ticks):\n"); for (t = FIRST_LIST(&PERCPU_GET(fprr_state)->servers, sched_next, sched_prev) ; t != &PERCPU_GET(fprr_state)->servers ; t = FIRST_LIST(t, sched_next, sched_prev)) { struct sched_accounting *sa = sched_get_accounting(t); unsigned long diff = sa->ticks - sa->prev_ticks; if (!sched_thd_suspended(t)) continue; if (diff || sa->cycles) { printc("\t%d, %d, %ld+%ld/%d\n", t->id, sched_get_metric(t)->priority, diff, (unsigned long)sa->cycles, QUANTUM); sa->prev_ticks = sa->ticks; sa->cycles = 0; } } #endif printc("done printing runqueue.\n"); }
static int ds_parse_params(struct sched_thd *t, char *s) { int n, prio; assert(s[0] == 'd'); s++; prio = ds_extract_nums(s, &n); s += n; assert(s[0] == 'c'); s++; sched_get_accounting(t)->C = ds_extract_nums(s, &n); s += n; sched_get_accounting(t)->C_used = 0; assert(s[0] == 't'); s++; sched_get_accounting(t)->T = ds_extract_nums(s, &n); sched_get_accounting(t)->T_exp = 0; return prio; }
int thread_param_set(struct sched_thd *t, struct sched_param_s *ps) { unsigned int prio = PRIO_LOWEST; struct sched_thd *c = sched_get_current(); assert(t); while (ps->type != SCHEDP_NOOP) { switch (ps->type) { case SCHEDP_RPRIO: case SCHEDP_RLPRIO: /* The relative priority has been converted to absolute priority in relative_prio_convert(). */ prio = ps->value; /* FIXME: When the IPI handling thread is * creating a thread (requested by a remote * core) , since we can't copy accounting info * from the actual parent (which is on a * different core), we zero the accounting * info instead of touching remote * data-structures. */ if (sched_curr_is_IPI_handler()) sched_clear_accounting(t); else memcpy(sched_get_accounting(t), sched_get_accounting(c), sizeof(struct sched_accounting)); #ifdef DEFERRABLE if (sched_get_accounting(t)->T) ADD_LIST(&PERCPU_GET(fprr_state)->servers, t, sched_next, sched_prev); #endif if (prio > PRIO_LOWEST) prio = PRIO_LOWEST; break; case SCHEDP_PRIO: /* absolute priority */ prio = ps->value; break; case SCHEDP_IDLE: /* idle thread */ prio = PRIO_LOWEST; break; case SCHEDP_INIT: /* idle thread */ prio = PRIO_LOW; break; case SCHEDP_TIMER: /* timer thread */ prio = PRIO_HIGHEST; break; case SCHEDP_IPI_HANDLER: prio = IPI_HANDLER_PRIO; break; case SCHEDP_CORE_ID: assert(ps->value == cos_cpuid()); break; #ifdef DEFERRABLE case SCHEDP_BUDGET: prio = sched_get_metric(t)->priority; sched_get_accounting(t)->C = ps->value; sched_get_accounting(t)->C_used = 0; fp_move_end_runnable(t); break; case SCHEDP_WINDOW: prio = sched_get_metric(t)->priority; sched_get_accounting(t)->T = ps->value; sched_get_accounting(t)->T_exp = 0; if (EMPTY_LIST(t, sched_next, sched_prev) && sched_get_accounting(t)->T) { ADD_LIST(&PERCPU_GET(fprr_state)->servers, t, sched_next, sched_prev); } fp_move_end_runnable(t); break; #endif default: printc("fprr: core %ld received unknown priority option\n", cos_cpuid()); prio = PRIO_LOW; } ps++; } /* printc("fprr: cpu %d has new thd %d @ prio %d\n", cos_cpuid(), t->id, prio); */ if (sched_thd_ready(t)) fp_rem_thd(t); fp_add_thd(t, prio); return 0; }