aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern Brandenburg <bbb@mpi-sws.org>2013-01-14 08:56:17 -0500
committerBjoern Brandenburg <bbb@mpi-sws.org>2013-02-04 09:11:46 -0500
commitf308b757af1574632627b727c90e08a65b1dfc96 (patch)
treed5a20b70e6f3ebd792b9810c6f55c67cfef52463
parent176e38bd5876bfe691d09d75de8959801eda9da2 (diff)
Add basic locking support to rtspin
This is useful for testing locking protocol implementations (not intended for benchmarking!), and also serves to document how to use the LITMUS^RT locking API.
-rw-r--r--bin/rtspin.c71
-rw-r--r--include/litmus.h7
-rw-r--r--src/litmus.c20
3 files changed, 91 insertions, 7 deletions
diff --git a/bin/rtspin.c b/bin/rtspin.c
index f0a477d..5054d0b 100644
--- a/bin/rtspin.c
+++ b/bin/rtspin.c
@@ -4,6 +4,7 @@
4#include <stdlib.h> 4#include <stdlib.h>
5#include <unistd.h> 5#include <unistd.h>
6#include <time.h> 6#include <time.h>
7#include <string.h>
7#include <assert.h> 8#include <assert.h>
8 9
9 10
@@ -21,8 +22,10 @@ static void usage(char *error) {
21 " rt_spin -l\n" 22 " rt_spin -l\n"
22 "\n" 23 "\n"
23 "COMMON-OPTS = [-w] [-p PARTITION] [-c CLASS] [-s SCALE]\n" 24 "COMMON-OPTS = [-w] [-p PARTITION] [-c CLASS] [-s SCALE]\n"
25 " [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]"
24 "\n" 26 "\n"
25 "WCET and PERIOD are milliseconds, DURATION is seconds.\n"); 27 "WCET and PERIOD are milliseconds, DURATION is seconds.\n"
28 "CRITICAL SECTION LENGTH is in milliseconds.\n");
26 exit(EXIT_FAILURE); 29 exit(EXIT_FAILURE);
27} 30}
28 31
@@ -150,18 +153,37 @@ static void debug_delay_loop(void)
150 } 153 }
151} 154}
152 155
153static int job(double exec_time, double program_end) 156static int job(double exec_time, double program_end, int lock_od, double cs_length)
154{ 157{
158 double chunk1, chunk2;
159
155 if (wctime() > program_end) 160 if (wctime() > program_end)
156 return 0; 161 return 0;
157 else { 162 else {
158 loop_for(exec_time, program_end + 1); 163 if (lock_od >= 0) {
164 /* simulate critical section somewhere in the middle */
165 chunk1 = drand48() * (exec_time - cs_length);
166 chunk2 = exec_time - cs_length - chunk1;
167
168 /* non-critical section */
169 loop_for(chunk1, program_end + 1);
170
171 /* critical section */
172 litmus_lock(lock_od);
173 loop_for(cs_length, program_end + 1);
174 litmus_unlock(lock_od);
175
176 /* non-critical section */
177 loop_for(chunk2, program_end + 2);
178 } else {
179 loop_for(exec_time, program_end + 1);
180 }
159 sleep_next_period(); 181 sleep_next_period();
160 return 1; 182 return 1;
161 } 183 }
162} 184}
163 185
164#define OPTSTR "p:c:wlveo:f:s:q:" 186#define OPTSTR "p:c:wlveo:f:s:q:X:L:Q:"
165 187
166int main(int argc, char** argv) 188int main(int argc, char** argv)
167{ 189{
@@ -184,6 +206,13 @@ int main(int argc, char** argv)
184 task_class_t class = RT_CLASS_HARD; 206 task_class_t class = RT_CLASS_HARD;
185 int cur_job, num_jobs; 207 int cur_job, num_jobs;
186 208
209 /* locking */
210 int lock_od = -1;
211 int resource_id = 0;
212 const char *lock_namespace = "./rtspin-locks";
213 int protocol = -1;
214 double cs_length = 1; /* millisecond */
215
187 progname = argv[0]; 216 progname = argv[0];
188 217
189 while ((opt = getopt(argc, argv, OPTSTR)) != -1) { 218 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
@@ -220,6 +249,21 @@ int main(int argc, char** argv)
220 case 's': 249 case 's':
221 scale = atof(optarg); 250 scale = atof(optarg);
222 break; 251 break;
252 case 'X':
253 protocol = lock_protocol_for_name(optarg);
254 if (protocol < 0)
255 usage("Unknown locking protocol specified.");
256 break;
257 case 'L':
258 cs_length = atof(optarg);
259 if (cs_length <= 0)
260 usage("Invalid critical section length.");
261 break;
262 case 'Q':
263 resource_id = atoi(optarg);
264 if (resource_id <= 0 && strcmp(optarg, "0"))
265 usage("Invalid resource ID.");
266 break;
223 case ':': 267 case ':':
224 usage("Argument missing."); 268 usage("Argument missing.");
225 break; 269 break;
@@ -235,6 +279,8 @@ int main(int argc, char** argv)
235 return 0; 279 return 0;
236 } 280 }
237 281
282 srand(getpid());
283
238 if (file) { 284 if (file) {
239 get_exec_times(file, column, &num_jobs, &exec_times); 285 get_exec_times(file, column, &num_jobs, &exec_times);
240 286
@@ -293,6 +339,15 @@ int main(int argc, char** argv)
293 if (ret != 0) 339 if (ret != 0)
294 bail_out("could not become RT task"); 340 bail_out("could not become RT task");
295 341
342 if (protocol >= 0) {
343 /* open reference to semaphore */
344 lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cpu);
345 if (lock_od < 0) {
346 perror("litmus_open_lock");
347 usage("Could not open lock.");
348 }
349 }
350
296 if (wait) { 351 if (wait) {
297 ret = wait_for_ts_release(); 352 ret = wait_for_ts_release();
298 if (ret != 0) 353 if (ret != 0)
@@ -306,11 +361,13 @@ int main(int argc, char** argv)
306 for (cur_job = 0; cur_job < num_jobs; ++cur_job) { 361 for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
307 /* convert job's length to seconds */ 362 /* convert job's length to seconds */
308 job(exec_times[cur_job] * 0.001 * scale, 363 job(exec_times[cur_job] * 0.001 * scale,
309 start + duration); 364 start + duration,
365 lock_od, cs_length * 0.001);
310 } 366 }
311 } else { 367 } else {
312 /* conver to seconds and scale */ 368 /* convert to seconds and scale */
313 while (job(wcet_ms * 0.001 * scale, start + duration)); 369 while (job(wcet_ms * 0.001 * scale, start + duration,
370 lock_od, cs_length * 0.001));
314 } 371 }
315 372
316 ret = task_mode(BACKGROUND_TASK); 373 ret = task_mode(BACKGROUND_TASK);
diff --git a/include/litmus.h b/include/litmus.h
index 2b6a1dd..58af6b7 100644
--- a/include/litmus.h
+++ b/include/litmus.h
@@ -80,6 +80,13 @@ static inline int od_open(int fd, obj_type_t type, int obj_id)
80 return od_openx(fd, type, obj_id, 0); 80 return od_openx(fd, type, obj_id, 0);
81} 81}
82 82
83int litmus_open_lock(
84 obj_type_t protocol, /* which locking protocol to use, e.g., FMLP_SEM */
85 int lock_id, /* numerical id of the lock, user-specified */
86 const char* namespace, /* path to a shared file */
87 void *config_param); /* any extra info needed by the protocol (such
88 * as CPU under SRP and PCP), may be NULL */
89
83/* real-time locking protocol support */ 90/* real-time locking protocol support */
84int litmus_lock(int od); 91int litmus_lock(int od);
85int litmus_unlock(int od); 92int litmus_unlock(int od);
diff --git a/src/litmus.c b/src/litmus.c
index b32254b..e0d9253 100644
--- a/src/litmus.c
+++ b/src/litmus.c
@@ -3,7 +3,10 @@
3#include <stdio.h> 3#include <stdio.h>
4#include <string.h> 4#include <string.h>
5#include <signal.h> 5#include <signal.h>
6#include <fcntl.h>
6#include <sys/mman.h> 7#include <sys/mman.h>
8#include <sys/types.h>
9
7 10
8#include <sched.h> /* for cpu sets */ 11#include <sched.h> /* for cpu sets */
9 12
@@ -49,6 +52,23 @@ const char* name_for_lock_protocol(int id)
49 return "<UNKNOWN>"; 52 return "<UNKNOWN>";
50} 53}
51 54
55int litmus_open_lock(
56 obj_type_t protocol,
57 int lock_id,
58 const char* namespace,
59 void *config_param)
60{
61 int fd, od;
62
63 fd = open(namespace, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
64 if (fd < 0)
65 return -1;
66 od = od_openx(fd, protocol, lock_id, config_param);
67 close(fd);
68 return od;
69}
70
71
52 72
53void show_rt_param(struct rt_task* tp) 73void show_rt_param(struct rt_task* tp)
54{ 74{