aboutsummaryrefslogtreecommitdiffstats
path: root/litmus/sched_edf_hsb.c
diff options
context:
space:
mode:
authorChristopher Kenna <cjk@cs.unc.edu>2010-10-31 16:59:40 -0400
committerChristopher Kenna <cjk@cs.unc.edu>2010-11-22 11:02:04 -0500
commit88d6578d9546a826136d5edbf8ea59c50fb40389 (patch)
tree181b85cd7c7d40041adfa21e0e9e887183e2c498 /litmus/sched_edf_hsb.c
parent05cf8f197fb336276a1298a9a3c7a5f82c21c92f (diff)
remove complex initialization, add possible race conditions
Removed the complex initilization procedure by removing the is_initialized atomic type. However, this introduces a slight chance that we might activate the plugin with invalid parameters.
Diffstat (limited to 'litmus/sched_edf_hsb.c')
-rw-r--r--litmus/sched_edf_hsb.c145
1 files changed, 31 insertions, 114 deletions
diff --git a/litmus/sched_edf_hsb.c b/litmus/sched_edf_hsb.c
index 4c4643226675..dbf912e889f3 100644
--- a/litmus/sched_edf_hsb.c
+++ b/litmus/sched_edf_hsb.c
@@ -7,6 +7,7 @@
7#include <linux/ctype.h> 7#include <linux/ctype.h>
8#include <linux/time.h> 8#include <linux/time.h>
9#include <linux/string.h> 9#include <linux/string.h>
10#include <linux/sched.h>
10 11
11#include <litmus/litmus.h> 12#include <litmus/litmus.h>
12#include <litmus/rt_domain.h> 13#include <litmus/rt_domain.h>
@@ -14,9 +15,9 @@
14#include <litmus/litmus_proc.h> 15#include <litmus/litmus_proc.h>
15#include <litmus/edf_common.h> 16#include <litmus/edf_common.h>
16 17
17/* synchronization point to start only when all HRT servers are set up */ 18/* forward declaration so the below macro works */
18static atomic_t initialized = ATOMIC_INIT(0); 19static struct sched_plugin edf_hsb_plugin __cacheline_aligned_in_smp;
19#define is_initialized (atomic_read(&initialized)) 20#define is_active_plugin (litmus == &edf_hsb_plugin)
20 21
21struct hrt_server { 22struct hrt_server {
22 int cpu; 23 int cpu;
@@ -37,7 +38,8 @@ DEFINE_PER_CPU_SHARED_ALIGNED(struct hrt_server, hrt_servers);
37/* 38/*
38 * Set the WCET and period for an HRT server on a specific CPU. 39 * Set the WCET and period for an HRT server on a specific CPU.
39 * Times are given in milliseconds. 40 * Times are given in milliseconds.
40 * This should only be done in the initialization phase! 41 * There is a small race condition in checking we're not the active plugin
42 * before setting parameters, but we are not worried about that so much.
41 */ 43 */
42int set_hrt_params(unsigned long long cpu, unsigned long long wcet, 44int set_hrt_params(unsigned long long cpu, unsigned long long wcet,
43 unsigned long long period) 45 unsigned long long period)
@@ -64,17 +66,14 @@ int set_hrt_params(unsigned long long cpu, unsigned long long wcet,
64 goto out; 66 goto out;
65 } 67 }
66 68
67 hrt_server = &per_cpu(hrt_servers, cpu); 69 if (is_active_plugin) {
68 70 printk(KERN_WARNING "Can't set params on active plugin.\n");
69 write_lock_irq(&hrt_server->param_lock);
70
71 /* must do this check after getting the write lock for correctness */
72 if (is_initialized){
73 printk(KERN_WARNING "Attempt to set HRT params after init.\n");
74 rv = -EPERM; 71 rv = -EPERM;
75 goto out_unlock; 72 goto out;
76 } 73 }
77 74
75 hrt_server = &per_cpu(hrt_servers, cpu);
76 write_lock_irq(&hrt_server->param_lock);
78 hrt_server->wcet = wcet * NSEC_PER_MSEC; 77 hrt_server->wcet = wcet * NSEC_PER_MSEC;
79 hrt_server->period = period * NSEC_PER_MSEC; 78 hrt_server->period = period * NSEC_PER_MSEC;
80 79
@@ -82,59 +81,33 @@ int set_hrt_params(unsigned long long cpu, unsigned long long wcet,
82 * TODO probably need a function to reset hrtimers and stuff here 81 * TODO probably need a function to reset hrtimers and stuff here
83 */ 82 */
84 83
85out_unlock:
86 write_unlock_irq(&hrt_server->param_lock); 84 write_unlock_irq(&hrt_server->param_lock);
87out: 85out:
88 return rv; 86 return rv;
89} 87}
90 88
91/* 89/*
92 * do all hrt_servers have a non-zero WCET and period? if they do, set 90 * Do all hrt_servers have a non-zero WCET and period? Return 0 if so.
93 * the atomic initialized variable to 1.
94 */ 91 */
95static int check_hrt_servers_initialized(void) 92static int check_hrt_servers_initialized(void)
96{ 93{
97 struct hrt_server *hrt_server; 94 struct hrt_server *hrt_server;
98 int cpu, all_init = 1; 95 int cpu, all_init = 1;
99 96
100 /*
101 * we first acquire hrt server writer locks for each cpu to ensure that
102 * no one changes the value of the parameters from under us while we
103 * are checking that they are valid
104 *
105 * we don't support cpu hotplug (and I hope we never have to)
106 */
107
108 for_each_online_cpu(cpu) { 97 for_each_online_cpu(cpu) {
109 98
110 hrt_server = &per_cpu(hrt_servers, cpu); 99 hrt_server = &per_cpu(hrt_servers, cpu);
111 100 read_lock_irq(&hrt_server->param_lock);
112 /*
113 * acquire all the reader/writer locks as writers.
114 * this usually triggers a "recursive lock" warning in syslog.
115 */
116 write_lock_irq(&hrt_server->param_lock);
117 101
118 /* if any parameter is zero, all_init will become zero */ 102 /* if any parameter is zero, all_init will become zero */
119 all_init = all_init && hrt_server->wcet && 103 all_init = all_init && hrt_server->wcet &&
120 hrt_server->period; 104 hrt_server->period;
121 }
122
123 /*
124 * now we hold all the writer locks, so we can make a decision about
125 * these HRT servers without worry about them getting re-set
126 * underneath us.
127 */
128 if (all_init)
129 atomic_set(&initialized, 1);
130 105
131 for_each_online_cpu(cpu) { 106 read_unlock_irq(&hrt_server->param_lock);
132 hrt_server = &per_cpu(hrt_servers, cpu);
133 /* unlock all the reader/writer locks */
134 write_unlock_irq(&hrt_server->param_lock);
135 } 107 }
136 108
137 return all_init; 109 /* inverted because zero is success */
110 return !all_init;
138} 111}
139 112
140void reset_hrt_servers(void) 113void reset_hrt_servers(void)
@@ -157,22 +130,30 @@ void reset_hrt_servers(void)
157 130
158static long edf_hsb_deactivate_plugin(void) 131static long edf_hsb_deactivate_plugin(void)
159{ 132{
160 return 0;
161 atomic_set(&initialized, 0);
162 reset_hrt_servers(); 133 reset_hrt_servers();
134 return 0;
163} 135}
164 136
137/*
138 * There is a small race condition in checking that all the server parameters
139 * are valid, then having one of them change before setting the active plugin,
140 * but oh well.
141 */
165static long edf_hsb_activate_plugin(void) 142static long edf_hsb_activate_plugin(void)
166{ 143{
167 return 0; 144 long rv = 0;
145
146 if (check_hrt_servers_initialized())
147 rv = -EINVAL;
148
149 return rv;
168} 150}
169 151
170/************************************************************ 152/************************************************************
171 * Proc stuff 153 * Proc stuff
172************************************************************/ 154************************************************************/
173 155
174static struct proc_dir_entry *edf_hsb_proc_dir = NULL, *hrt_server_proc = NULL, 156static struct proc_dir_entry *edf_hsb_proc_dir = NULL, *hrt_server_proc = NULL;
175 *initialized_proc = NULL;
176 157
177static int hrt_proc_read(char* page, char **start, off_t off, int count, 158static int hrt_proc_read(char* page, char **start, off_t off, int count,
178 int *eof, void *data) 159 int *eof, void *data)
@@ -274,53 +255,8 @@ loop_end:
274 return count; 255 return count;
275} 256}
276 257
277static int initialized_proc_read(char* page, char **start, off_t off, int count, 258/* actual plugin object */
278 int *eof, void *data) 259/* static struct sched_plugin edf_hsb_plugin = { */
279{
280 int len = 0;
281 len += snprintf(page, PAGE_SIZE, "%d\n", is_initialized);
282 *eof = 1;
283 return len;
284}
285
286static int initialized_proc_write(struct file *file, const char __user *input,
287 unsigned long count, void *data)
288{
289#define INITIALIZED_PROC_BUF 3
290 char buffer[INITIALIZED_PROC_BUF];
291 int in_val = -1, num_read;
292
293 /* don't allow changes after initialized */
294 if (is_initialized)
295 return -EPERM;
296
297 if (count >= INITIALIZED_PROC_BUF){
298 printk(KERN_WARNING "proc buffer possibly too small in %s.\n",
299 __func__);
300 return -ENOSPC;
301 }
302
303 if (copy_from_user(buffer, input, (INITIALIZED_PROC_BUF - 1)))
304 return -EFAULT;
305
306 buffer[INITIALIZED_PROC_BUF-1] = '\0';
307
308 num_read = sscanf(buffer, "%d", &in_val);
309
310 if (!num_read || (in_val!= 0 && in_val != 1)) {
311 printk(KERN_WARNING "Invalid HSB initialization in proc.\n");
312 return -EIO;
313 } else if (in_val == 1) {
314 check_hrt_servers_initialized();
315 if (!is_initialized)
316 printk(KERN_WARNING "Attempted to set initialized = 1 "
317 "without all HRT servers setup.\n");
318 }
319
320 return count;
321}
322
323/* Plugin object */
324static struct sched_plugin edf_hsb_plugin __cacheline_aligned_in_smp = { 260static struct sched_plugin edf_hsb_plugin __cacheline_aligned_in_smp = {
325 .plugin_name = "EDF-HSB", 261 .plugin_name = "EDF-HSB",
326 262
@@ -349,15 +285,9 @@ static struct sched_plugin edf_hsb_plugin __cacheline_aligned_in_smp = {
349}; 285};
350 286
351#define HRT_SERVER_PROC_NAME "hrt_server" 287#define HRT_SERVER_PROC_NAME "hrt_server"
352#define INITIALIZED_PROC_NAME "initialized"
353 288
354static void exit_proc(void) 289static void exit_proc(void)
355{ 290{
356 if (initialized_proc) {
357 remove_proc_entry(INITIALIZED_PROC_NAME, edf_hsb_proc_dir);
358 initialized_proc = NULL;
359 }
360
361 if (hrt_server_proc) { 291 if (hrt_server_proc) {
362 remove_proc_entry(HRT_SERVER_PROC_NAME, edf_hsb_proc_dir); 292 remove_proc_entry(HRT_SERVER_PROC_NAME, edf_hsb_proc_dir);
363 hrt_server_proc = NULL; 293 hrt_server_proc = NULL;
@@ -399,19 +329,6 @@ static int __init init_edf_hsb(void)
399 hrt_server_proc->read_proc = hrt_proc_read; 329 hrt_server_proc->read_proc = hrt_proc_read;
400 hrt_server_proc->write_proc = hrt_proc_write; 330 hrt_server_proc->write_proc = hrt_proc_write;
401 331
402 initialized_proc = create_proc_entry(INITIALIZED_PROC_NAME,
403 0644, edf_hsb_proc_dir);
404 if (!initialized_proc) {
405 printk(KERN_ERR "Could not create proc entry: %s.\n",
406 INITIALIZED_PROC_NAME);
407 rv = -ENOENT;
408 goto out_clean_proc;
409 }
410
411 initialized_proc->read_proc = initialized_proc_read;
412 initialized_proc->write_proc = initialized_proc_write;
413
414 atomic_set(&initialized, 0);
415 reset_hrt_servers(); 332 reset_hrt_servers();
416 333
417 goto out; 334 goto out;