aboutsummaryrefslogtreecommitdiffstats
path: root/litmus/pgm.c
blob: db3378ff803d7d09712e087e6c88826d0c7de8bc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/* litmus/pgm.c - common pgm control code
 */

#include <linux/sched.h>
#include <litmus/litmus.h>
#include <litmus/pgm.h>
#include <litmus/sched_trace.h>

/* 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;
}