#include "seek.h" struct rc { int pending; quad_t start, finish, vt; int share; quad_t tput, ktput, util; int m_tput, m_ktput, m_util; } rc[NRC]; #define RC(bp) (rc[bproc(bp) && pinfo(bproc(bp)) && bpinfo(bp).rc >= 0 \ && bpinfo(bp).rc < NRC ? bpinfo(bp).rc : 0]) void _sched_init(void) { quad_t unit = (10000 * 1000) / ((NRC * (NRC+1))/2); /* 1:2:3:.. */ /* int shares[] = { 60, 20, 20 }; */ int i; for (i = 0; i < NRC; i++) { bzero(&rc[i], sizeof(struct rc)); rc[i].share = ((i+1) * unit) / 1000; /* rc[i].share = shares[i] * 100; */ } sched_init(); } #undef sched_init #define sched_init _sched_init void _sched_enqueue(struct buf *bp) { #ifdef YFQ if (!RC(bp).pending) { int i; quad_t minstart = QUAD_MAX, maxfinish = 0, numbusy = 0; for(i = 0; i < NRC; i++) { if (rc[i].pending) { numbusy++; if (minstart > rc[i].start) minstart = rc[i].start; } if (maxfinish < rc[i].finish) maxfinish = rc[i].finish; } /* * made a transition to runnable mode, so A(q_fj) is now */ RC(bp).vt = numbusy ? minstart : maxfinish; } RC(bp).start = qmax(RC(bp).vt, RC(bp).finish); #endif RC(bp).pending++; sched_enqueue(bp); /* parallel seek reducer */ } #undef sched_enqueue #define sched_enqueue _sched_enqueue static struct buf *_sched_select() { int i; struct buf *bp, *bq = 0; int t0 = INT_MAX; #ifdef FQ quad_t minstart = QUAD_MAX; if (!pending) return NULL; for (i = 0; i < NRC; i++) { #ifdef STRIDE rc[i].start = rc[i].finish; #endif if (rc[i].pending) { if (rc[i].start < minstart) minstart = rc[i].start; } } #endif /* FQ */ #ifdef LOTTERY int ticket, total = 0; if (!pending) return NULL; for (i = 0; i < NRC; i++) if (rc[i].pending) total += rc[i].share; if (total == 0) return NULL; ticket = random() % total; for (i = 0; i < NRC; i++) if (rc[i].pending) { ticket -= rc[i].share; if (ticket < 0) break; } if (i == NRC) panic("lottery screwup"); #endif /* LOTTERY */ #ifndef PROP_RELAX_THRESH #define PROP_RELAX_THRESH 0 #endif #define thresh(rc) (PROP_RELAX_THRESH*1000 * 10LL) / (rc.share / 100) sched_foreach(bp) { #ifdef FQ if (RC(bp).start - thresh(RC(bp)) <= minstart) #else if (&RC(bp) == &rc[i]) #endif { int t = sched_dist(bp); if (!bq || t < t0) t0 = t, bq = bp; } } if (!bq) printf("returning NULL, despite having %d requests\n", pending); return bq; } #undef sched_select #define sched_select _sched_select void _sched_dequeue(struct buf *bp) { RC(bp).pending--; sched_dequeue(bp); } #undef sched_dequeue #define sched_dequeue _sched_dequeue void _sched_iodone(struct buf *bp) { #ifdef FQ quad_t reqtime = bp->b_t_iodone - qmax(bp->b_t_iostart, t_lastiodone); if (reqtime > 1000000) return; #endif #ifdef YFQ { quad_t minstart = QUAD_MAX, maxfinish = 0, numbusy = 0; int i; for (i = 0; i < NRC; i++) { if (rc[i].pending) { numbusy++; if (minstart > rc[i].start) minstart = rc[i].start; } if (maxfinish < rc[i].finish) maxfinish = rc[i].finish; } RC(bp).vt = numbusy ? minstart : maxfinish; RC(bp).start = RC(bp).finish; RC(bp).finish = RC(bp).start + (reqtime * 100LL) / (RC(bp).share / 100); } #endif #if defined(STRIDE) RC(bp).finish += (reqtime * 10LL) / (RC(bp).share / 100); #endif } #undef sched_iodone #define sched_iodone _sched_iodone #include "prop_nwcs.h" #undef sched_collect_stats void sched_collect_stats(struct buf *new) { seek_collect_stats(new); prop_collect_stats(new); } #define candidate(rc) (rc.start - thresh(rc) < minstart) #undef sched_evaluate int sched_evaluate(volatile struct buf *last, volatile struct buf *next) { int seek_eval = -1, prop_eval = -1; prop_eval = prop_evaluate(last, next); /* if (candidate(RC(last))) */ seek_eval = seek_evaluate(last, next); return imax(seek_eval, prop_eval); }