/* litmus/pgm.c - common pgm control code */ #include #include #include #include /* Only readjust release/deadline if difference is over a given threshold. It's a weak method for accounting overheads. Ideally, we'd know the last time t was woken up by its last predecessor, rather than having to look at 'now'. Adjustment threshold currently set to 200us. */ #define ADJUSTMENT_THRESH_NS (200*1000LL) int setup_pgm_release(struct task_struct* t) { int shifted_release = 0; /* approximate time last predecessor gave us tokens */ lt_t now = litmus_clock(); TRACE_TASK(t, "is starting a new PGM job: waiting:%d\n", tsk_rt(t)->ctrl_page->pgm_waiting); BUG_ON(!tsk_rt(t)->ctrl_page->pgm_waiting); /* Adjust release time if we got the last tokens after release of this job. This is possible since PGM jobs are early-released. Don't shift our deadline if we got the tokens earlier than expected. */ if (now > tsk_rt(t)->job_params.release) { long long diff_ns = now - tsk_rt(t)->job_params.release; if (diff_ns > ADJUSTMENT_THRESH_NS) { lt_t adj_deadline = now + get_rt_relative_deadline(t); TRACE_TASK(t, "adjusting PGM release time from (r = %llu, d = %llu) " "to (r = %llu, d = %llu)\n", tsk_rt(t)->job_params.release, tsk_rt(t)->job_params.deadline, now, adj_deadline); tsk_rt(t)->job_params.release = now; tsk_rt(t)->job_params.deadline = adj_deadline; shifted_release = 1; } else { TRACE_TASK(t, "adjustment falls below threshold. %lld < %lld\n", diff_ns, ADJUSTMENT_THRESH_NS); } } else { TRACE_TASK(t, "got tokens early--no need to adjust release. " "cur time = %llu, release time = %llu\n", now, tsk_rt(t)->job_params.release); } /* possible that there can be multiple instances of pgm_release logged. analysis tools should filter out all but the last pgm_release for a given job release */ sched_trace_pgm_release(t); return shifted_release; }