aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern Brandenburg <bbb@mpi-sws.org>2015-12-17 16:44:59 -0500
committerBjoern Brandenburg <bbb@mpi-sws.org>2015-12-18 03:34:40 -0500
commit3e0c32c25e6f32c24c53c0a401d67f1c05576c38 (patch)
tree9fe7cfe94402cbed6eaabdcfdad6060a37368c1e
parentb8438dac7a15cc2a584663f8e6d30ed85c2eb588 (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.h2
-rw-r--r--litmus/jobs.c46
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
7long default_wait_for_release_at(lt_t release_time); 7long default_wait_for_release_at(lt_t release_time);
8long complete_job(void); 8long complete_job(void);
9long complete_job_oneshot(void);
10long 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
11static inline void setup_release(struct task_struct *t, lt_t release) 12static 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 */
95long 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
109long 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}