aboutsummaryrefslogtreecommitdiffstats
path: root/litmus/sync.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-04-19 17:31:52 -0400
committerJonathan Herman <hermanjl@cs.unc.edu>2013-04-19 17:31:52 -0400
commitf70a290e8a889caa905ab7650c696f2bb299be1a (patch)
tree56f0886d839499e9f522f189999024b3e86f9be2 /litmus/sync.c
parentfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (diff)
parent7ef4a793a624c6e66c16ca1051847f75161f5bec (diff)
Merge branch 'wip-nested-locking' into tegra-nested-lockingwip-nested-locking
Conflicts: Makefile include/linux/fs.h
Diffstat (limited to 'litmus/sync.c')
-rw-r--r--litmus/sync.c152
1 files changed, 152 insertions, 0 deletions
diff --git a/litmus/sync.c b/litmus/sync.c
new file mode 100644
index 00000000000..3e79e0a12a5
--- /dev/null
+++ b/litmus/sync.c
@@ -0,0 +1,152 @@
1/* litmus/sync.c - Support for synchronous and asynchronous task system releases.
2 *
3 *
4 */
5
6#include <asm/atomic.h>
7#include <asm/uaccess.h>
8#include <linux/spinlock.h>
9#include <linux/list.h>
10#include <linux/sched.h>
11#include <linux/completion.h>
12
13#include <litmus/litmus.h>
14#include <litmus/sched_plugin.h>
15#include <litmus/jobs.h>
16
17#include <litmus/sched_trace.h>
18
19struct ts_release_wait {
20 struct list_head list;
21 struct completion completion;
22 lt_t ts_release_time;
23};
24
25#define DECLARE_TS_RELEASE_WAIT(symb) \
26 struct ts_release_wait symb = \
27 { \
28 LIST_HEAD_INIT(symb.list), \
29 COMPLETION_INITIALIZER_ONSTACK(symb.completion), \
30 0 \
31 }
32
33static LIST_HEAD(task_release_list);
34static DEFINE_MUTEX(task_release_lock);
35
36static long do_wait_for_ts_release(void)
37{
38 DECLARE_TS_RELEASE_WAIT(wait);
39
40 long ret = -ERESTARTSYS;
41
42 if (mutex_lock_interruptible(&task_release_lock))
43 goto out;
44
45 list_add(&wait.list, &task_release_list);
46
47 mutex_unlock(&task_release_lock);
48
49 /* We are enqueued, now we wait for someone to wake us up. */
50 ret = wait_for_completion_interruptible(&wait.completion);
51
52 if (!ret) {
53 /* Completion succeeded, setup release. */
54 litmus->release_at(current, wait.ts_release_time
55 + current->rt_param.task_params.phase
56 - current->rt_param.task_params.period);
57 /* trigger advance to next job release at the programmed time */
58 ret = complete_job();
59 } else {
60 /* We were interrupted, must cleanup list. */
61 mutex_lock(&task_release_lock);
62 if (!wait.completion.done)
63 list_del(&wait.list);
64 mutex_unlock(&task_release_lock);
65 }
66
67out:
68 return ret;
69}
70
71int count_tasks_waiting_for_release(void)
72{
73 int task_count = 0;
74 struct list_head *pos;
75
76 mutex_lock(&task_release_lock);
77
78 list_for_each(pos, &task_release_list) {
79 task_count++;
80 }
81
82 mutex_unlock(&task_release_lock);
83
84
85 return task_count;
86}
87
88static long do_release_ts(lt_t start)
89{
90 long task_count = 0;
91
92 struct list_head *pos, *safe;
93 struct ts_release_wait *wait;
94
95 if (mutex_lock_interruptible(&task_release_lock)) {
96 task_count = -ERESTARTSYS;
97 goto out;
98 }
99
100 TRACE("<<<<<< synchronous task system release >>>>>>\n");
101 sched_trace_sys_release(&start);
102
103 task_count = 0;
104 list_for_each_safe(pos, safe, &task_release_list) {
105 wait = (struct ts_release_wait*)
106 list_entry(pos, struct ts_release_wait, list);
107
108 task_count++;
109 wait->ts_release_time = start;
110 complete(&wait->completion);
111 }
112
113 /* clear stale list */
114 INIT_LIST_HEAD(&task_release_list);
115
116 mutex_unlock(&task_release_lock);
117
118out:
119 return task_count;
120}
121
122
123asmlinkage long sys_wait_for_ts_release(void)
124{
125 long ret = -EPERM;
126 struct task_struct *t = current;
127
128 if (is_realtime(t))
129 ret = do_wait_for_ts_release();
130
131 return ret;
132}
133
134#define ONE_MS 1000000
135
136asmlinkage long sys_release_ts(lt_t __user *__delay)
137{
138 long ret;
139 lt_t delay;
140 lt_t start_time;
141
142 /* FIXME: check capabilities... */
143
144 ret = copy_from_user(&delay, __delay, sizeof(delay));
145 if (ret == 0) {
146 /* round up to next larger integral millisecond */
147 start_time = ((litmus_clock() / ONE_MS) + 1) * ONE_MS;
148 ret = do_release_ts(start_time + delay);
149 }
150
151 return ret;
152}