/* GPL-2.0 */ #include #include #include #include #include #include bool eligible = true; unsigned long V_lim = 20; struct entity { unsigned long vruntime; unsigned long weight; unsigned long request; unsigned long vdeadline; int idx; }; unsigned int gcd(unsigned int a, unsigned int b) { int gcd, m = MIN(a, b); for (int i = 1; i <= m; i++) { if (a%i == 0 && b%i == 0) gcd = i; } return gcd; } int init_entities(int nr, struct entity *es) { unsigned int q = 0; for (int i = 0; i < nr; i++) { unsigned long d = (1024 * es[i].request) / es[i].weight; printf("d = %d\n", d); if (!q) q = d; else q = gcd(q, d); es[i].vdeadline = es[i].vruntime + d; es[i].idx = i; } printf("q = %d\n\n", q); return q; } int run_entity(struct entity *e) { unsigned long d = e->vdeadline - e->vruntime; d *= e->weight; d /= 1024; e->vruntime = e->vdeadline; e->vdeadline += (1024 * e->request) / e->weight; return d; } unsigned long avg_vruntime(int nr, struct entity *es) { unsigned long W = 0, V = 0; for (int i = 0; i < nr; i++) { V += es[i].weight * es[i].vruntime; W += es[i].weight; } V /= W; return V; } struct entity *pick_entity(int nr, struct entity *es) { unsigned long W = 0, V = 0; struct entity *e = NULL; for (int i = 0; i < nr; i++) { V += es[i].weight * es[i].vruntime; W += es[i].weight; } for (int i = 0; i < nr; i++) { if (eligible && W*es[i].vruntime > V) continue; if (!e || es[i].vdeadline < e->vdeadline) e = &es[i]; } return e; } void __print_space(int n) { for (int i = 0; i < n; i++) putchar(' '); } void __print_arrow(int n) { putchar('|'); for (int i = 1; i < (n-1); i++) putchar('-'); putchar('<'); } void print_entity(struct entity *e) { __print_space(e->vruntime); __print_arrow(e->vdeadline - e->vruntime); } void print_entities(int nr, struct entity *es, struct entity *p) { for (int i = 0; i < nr; i++) { if (&es[i] == p) putchar('>'); else putchar(' '); putchar('A' + i); putchar(' '); print_entity(&es[i]); putchar('\n'); } } void print_timeline(unsigned long V) { char timeline[] = "|---------|---------|---------|---------|----"; if (V > sizeof(timeline)-1) { printf("Whoopsie! out of time\n"); exit(0); } timeline[V] = '*'; __print_space(3); puts(timeline); putchar('\n'); } void update_lags(int nr, struct entity *es, unsigned long V, long *min, long *max) { for (int i = 0; i < nr; i++) { long lag = V - es[i].vruntime; if (lag < *min) *min = lag; if (lag > *max) *max = lag; } } int main(int argc, char *argv[]) { unsigned int s = 0, t = 0, n = 0, q = 1; long min_lag = 0, max_lag = 0; struct entity *e, es[8]; unsigned long V; char S[1024]; int opt; const int N = sizeof(es) / sizeof(es[0]); while ((opt = getopt(argc, argv, "nv:e:")) != -1) { unsigned int v,w,r; switch (opt) { case 'n': eligible = false; break; case 'v': V_lim = atol(optarg); break; case 'e': if (n >= N) { printf("Whoopsie! too many entities\n"); exit(0); } if (sscanf(optarg, "%u,%u,%u", &v,&w,&r) == 3) { es[n++] = (struct entity) { .vruntime = v, .weight = w, .request = r, }; } break; default: printf("Whoopsie!, bad arguments\n"); exit(0); } } if (!n) { printf("Whoopsie!, no entities\n"); exit(0); } q = init_entities(n, es); do { int d; V = avg_vruntime(n, es); printf("t=%d V=%ld\n", t, V); update_lags(n, es, V, &min_lag, &max_lag); e = pick_entity(n, es); if (!e) { printf("Whoopsie, no pick\n"); exit(0); } print_entities(n, es, e); print_timeline(V); d = run_entity(e); t += d; for (int i = 0; i < d; i += q) { char c = 'A' + e->idx; if (i) c = 'a' + e->idx; S[s++] = c; S[s] = '\0'; } putchar('\n'); } while (V < V_lim); printf("lags: %ld, %ld\n\n", min_lag, max_lag); puts(S); putchar('\n'); return 0; }