diff options
author | Bjoern Brandenburg <bbb@mpi-sws.org> | 2015-12-17 16:44:59 -0500 |
---|---|---|
committer | Bjoern Brandenburg <bbb@mpi-sws.org> | 2015-12-18 03:34:40 -0500 |
commit | 3e0c32c25e6f32c24c53c0a401d67f1c05576c38 (patch) | |
tree | 9fe7cfe94402cbed6eaabdcfdad6060a37368c1e | |
parent | b8438dac7a15cc2a584663f8e6d30ed85c2eb588 (diff) |
Add alternate complete_job() default implementation
Let jobs sleep like regular Linux tasks by suspending and waking them
with a one-shot timer. Plugins can opt into using this implementation
instead of the classic complete_job() implementation (or custom
implementations).
-rw-r--r-- | include/litmus/jobs.h | 2 | ||||
-rw-r--r-- | litmus/jobs.c | 46 |
2 files changed, 48 insertions, 0 deletions
diff --git a/include/litmus/jobs.h b/include/litmus/jobs.h index 24771dfaebf8..7db931b2b89f 100644 --- a/include/litmus/jobs.h +++ b/include/litmus/jobs.h | |||
@@ -6,5 +6,7 @@ void release_at(struct task_struct *t, lt_t start); | |||
6 | 6 | ||
7 | long default_wait_for_release_at(lt_t release_time); | 7 | long default_wait_for_release_at(lt_t release_time); |
8 | long complete_job(void); | 8 | long complete_job(void); |
9 | long complete_job_oneshot(void); | ||
10 | long sleep_until_next_release(void); | ||
9 | 11 | ||
10 | #endif | 12 | #endif |
diff --git a/litmus/jobs.c b/litmus/jobs.c index 3a6a14f9121c..80649d989499 100644 --- a/litmus/jobs.c +++ b/litmus/jobs.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <litmus/preempt.h> | 6 | #include <litmus/preempt.h> |
7 | #include <litmus/litmus.h> | 7 | #include <litmus/litmus.h> |
8 | #include <litmus/sched_plugin.h> | 8 | #include <litmus/sched_plugin.h> |
9 | #include <litmus/sched_trace.h> | ||
9 | #include <litmus/jobs.h> | 10 | #include <litmus/jobs.h> |
10 | 11 | ||
11 | static inline void setup_release(struct task_struct *t, lt_t release) | 12 | static inline void setup_release(struct task_struct *t, lt_t release) |
@@ -88,3 +89,48 @@ long complete_job(void) | |||
88 | preempt_enable(); | 89 | preempt_enable(); |
89 | return 0; | 90 | return 0; |
90 | } | 91 | } |
92 | |||
93 | |||
94 | /* alternative job completion implementation that suspends the task */ | ||
95 | long complete_job_oneshot(void) | ||
96 | { | ||
97 | struct task_struct *t = current; | ||
98 | |||
99 | TRACE_CUR("job completes at %llu (deadline: %llu)\n", litmus_clock(), | ||
100 | get_deadline(t)); | ||
101 | |||
102 | sched_trace_task_completion(t, 0); | ||
103 | prepare_for_next_period(t); | ||
104 | sched_trace_task_release(t); | ||
105 | |||
106 | return sleep_until_next_release(); | ||
107 | } | ||
108 | |||
109 | long sleep_until_next_release(void) | ||
110 | { | ||
111 | struct task_struct *t = current; | ||
112 | ktime_t next_release; | ||
113 | long err; | ||
114 | |||
115 | preempt_disable(); | ||
116 | next_release = ns_to_ktime(get_release(t)); | ||
117 | |||
118 | TRACE_CUR("next_release=%llu\n", get_release(t)); | ||
119 | |||
120 | if (lt_after(get_release(t), litmus_clock())) { | ||
121 | set_current_state(TASK_INTERRUPTIBLE); | ||
122 | preempt_enable_no_resched(); | ||
123 | err = schedule_hrtimeout(&next_release, HRTIMER_MODE_ABS); | ||
124 | /* If we get woken by a signal, we return early. | ||
125 | * This is intentional; we want to be able to kill tasks | ||
126 | * that are waiting for the next job release. | ||
127 | */ | ||
128 | } else { | ||
129 | err = 0; | ||
130 | TRACE_CUR("TARDY: release=%llu now=%llu\n", get_release(t), litmus_clock()); | ||
131 | preempt_enable(); | ||
132 | } | ||
133 | |||
134 | TRACE_CUR("return to next job at %llu\n", litmus_clock()); | ||
135 | return err; | ||
136 | } | ||