aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern Brandenburg <bbb@mpi-sws.org>2016-06-23 06:58:12 -0400
committerBjoern Brandenburg <bbb@mpi-sws.org>2016-07-20 07:42:41 -0400
commit9a8d7e447bbd1525f9f9f4660977072219bbc726 (patch)
treeca4df9b22144b2d7e53c8a1c637dff6f8bb6629c
parent98510c506a16b2a444eb6615ec8d78bc7c64e0aa (diff)
rtspin: Add sporadic task mode
While at it, also fix exec-times-from-CSV support.
-rw-r--r--bin/rtspin.c259
1 files changed, 160 insertions, 99 deletions
diff --git a/bin/rtspin.c b/bin/rtspin.c
index f14b549..d33e9b3 100644
--- a/bin/rtspin.c
+++ b/bin/rtspin.c
@@ -1,5 +1,6 @@
1#include <sys/time.h> 1#include <sys/time.h>
2 2
3#include <fcntl.h>
3#include <stdio.h> 4#include <stdio.h>
4#include <stdlib.h> 5#include <stdlib.h>
5#include <unistd.h> 6#include <unistd.h>
@@ -16,14 +17,20 @@
16 17
17const char *usage_msg = 18const char *usage_msg =
18 "Usage: (1) rtspin OPTIONS WCET PERIOD DURATION\n" 19 "Usage: (1) rtspin OPTIONS WCET PERIOD DURATION\n"
19 " (2) rtspin OPTIONS -F FILE [-C COLUMN] WCET PERIOD\n" 20 " (2) rtspin -S [INPUT] WCET PERIOD DURATION\n"
20 " (3) rtspin -l\n" 21 " (3) rtspin OPTIONS -F FILE [-C COLUMN] WCET PERIOD [DURATION]\n"
21 " (4) rtspin -B\n" 22 " (4) rtspin -l\n"
23 " (5) rtspin -B -m FOOTPRINT\n"
22 "\n" 24 "\n"
23 "Modes: (1) run as periodic task with given WCET and PERIOD\n" 25 "Modes: (1) run as periodic task with given WCET and PERIOD\n"
24 " (2) as (1), but load per-job execution times from a CSV file\n" 26 " (2) run as sporadic task with given WCET and PERIOD,\n"
25 " (3) Run calibration loop (how accurately are target runtimes met?)\n" 27 " using INPUT as a file from which events are received\n"
26 " (4) Run background, non-real-time cache-thrashing loop (w/ -m).\n" 28 " by means of blocking reads (default: read from STDIN)\n"
29 " (3) as (1) or (2), but load per-job execution times from\n"
30 " a CSV file\n"
31 " (4) Run calibration loop (how accurately are target\n"
32 " runtimes met?)\n"
33 " (5) Run background, non-real-time cache-thrashing loop.\n"
27 "\n" 34 "\n"
28 "Required arguments:\n" 35 "Required arguments:\n"
29 " WCET, PERIOD reservation parameters (in ms)\n" 36 " WCET, PERIOD reservation parameters (in ms)\n"
@@ -49,7 +56,11 @@ const char *usage_msg =
49 " -w wait for synchronous release\n" 56 " -w wait for synchronous release\n"
50 "\n" 57 "\n"
51 " -F FILE load per-job execution times from CSV file\n" 58 " -F FILE load per-job execution times from CSV file\n"
52 " -C COLUMNS specify column to read per-job execution times from (default: 1)\n" 59 " -C COLUMN specify column to read per-job execution times from (default: 1)\n"
60 "\n"
61 " -S [FILE] read from FILE to trigger sporadic job releases\n"
62 " default w/o -S: periodic job releases\n"
63 " default if FILE is omitted: read from STDIN\n"
53 "\n" 64 "\n"
54 " -X PROTOCOL access a shared resource protected by a locking protocol\n" 65 " -X PROTOCOL access a shared resource protected by a locking protocol\n"
55 " -L CS-LENGTH simulate a critical section length of CS-LENGTH milliseconds\n" 66 " -L CS-LENGTH simulate a critical section length of CS-LENGTH milliseconds\n"
@@ -79,8 +90,7 @@ static void usage(char *error) {
79 */ 90 */
80static int skip_to_next_line(FILE *fstream) 91static int skip_to_next_line(FILE *fstream)
81{ 92{
82 int ch; 93 int ch; for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
83 for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
84 return ch; 94 return ch;
85} 95}
86 96
@@ -186,10 +196,14 @@ static int loop_for(double exec_time, double emergency_exit)
186 now = cputime(); 196 now = cputime();
187 last_loop = now - loop_start; 197 last_loop = now - loop_start;
188 if (emergency_exit && wctime() > emergency_exit) { 198 if (emergency_exit && wctime() > emergency_exit) {
189 /* Oops --- this should only be possible if the execution time tracking 199 /* Oops --- this should only be possible if the
190 * is broken in the LITMUS^RT kernel. */ 200 * execution time tracking is broken in the LITMUS^RT
191 fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid()); 201 * kernel or the user specified infeasible parameters.
192 fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n"); 202 */
203 fprintf(stderr, "!!! rtspin/%d emergency exit!\n",
204 getpid());
205 fprintf(stderr, "Reached experiment timeout while "
206 "spinning.\n");
193 break; 207 break;
194 } 208 }
195 } 209 }
@@ -216,37 +230,53 @@ static void debug_delay_loop(void)
216 } 230 }
217} 231}
218 232
219static int job(double exec_time, double program_end, int lock_od, double cs_length) 233static int wait_for_input(int event_fd)
234{
235 /* We do a blocking read, accepting up to 4KiB of data.
236 * For simplicity, for now, if there's more than 4KiB of data,
237 * we treat this as multiple jobs. Note that this means that
238 * tardiness can result in coalesced jobs. Ideally, there should
239 * be some sort of configurable job boundary marker, but that's
240 * not supported in this basic version yet. Patches welcome.
241 */
242 char buf[4096];
243 size_t consumed;
244
245 consumed = read(event_fd, buf, sizeof(buf));
246
247 if (consumed == 0)
248 fprintf(stderr, "reached end-of-file on input event stream\n");
249 if (consumed < 0)
250 fprintf(stderr, "error reading input event stream (%m)\n");
251
252 return consumed > 0;
253}
254
255static void job(double exec_time, double program_end, int lock_od, double cs_length)
220{ 256{
221 double chunk1, chunk2; 257 double chunk1, chunk2;
222 258
223 if (wctime() > program_end) 259 if (lock_od >= 0) {
224 return 0; 260 /* simulate critical section somewhere in the middle */
225 else { 261 chunk1 = drand48() * (exec_time - cs_length);
226 if (lock_od >= 0) { 262 chunk2 = exec_time - cs_length - chunk1;
227 /* simulate critical section somewhere in the middle */
228 chunk1 = drand48() * (exec_time - cs_length);
229 chunk2 = exec_time - cs_length - chunk1;
230 263
231 /* non-critical section */ 264 /* non-critical section */
232 loop_for(chunk1, program_end + 1); 265 loop_for(chunk1, program_end + 1);
233 266
234 /* critical section */ 267 /* critical section */
235 litmus_lock(lock_od); 268 litmus_lock(lock_od);
236 loop_for(cs_length, program_end + 1); 269 loop_for(cs_length, program_end + 1);
237 litmus_unlock(lock_od); 270 litmus_unlock(lock_od);
238 271
239 /* non-critical section */ 272 /* non-critical section */
240 loop_for(chunk2, program_end + 2); 273 loop_for(chunk2, program_end + 2);
241 } else { 274 } else {
242 loop_for(exec_time, program_end + 1); 275 loop_for(exec_time, program_end + 1);
243 }
244 sleep_next_period();
245 return 1;
246 } 276 }
247} 277}
248 278
249#define OPTSTR "p:c:wlveo:F:s:m:q:r:X:L:Q:iRu:Bhd:C:" 279#define OPTSTR "p:c:wlveo:F:s:m:q:r:X:L:Q:iRu:Bhd:C:S::"
250int main(int argc, char** argv) 280int main(int argc, char** argv)
251{ 281{
252 int ret; 282 int ret;
@@ -274,9 +304,12 @@ int main(int argc, char** argv)
274 int cur_job = 0, num_jobs = 0; 304 int cur_job = 0, num_jobs = 0;
275 struct rt_task param; 305 struct rt_task param;
276 306
277 int rss=0; 307 int rss = 0;
278 int idx; 308 int idx;
279 309
310 int sporadic = 0; /* trigger jobs sporadically? */
311 int event_fd = -1; /* file descriptor for sporadic events */
312
280 int verbose = 0; 313 int verbose = 0;
281 unsigned int job_no; 314 unsigned int job_no;
282 struct control_page* cp; 315 struct control_page* cp;
@@ -333,6 +366,19 @@ int main(int argc, char** argv)
333 case 'F': 366 case 'F':
334 file = optarg; 367 file = optarg;
335 break; 368 break;
369 case 'S':
370 sporadic = 1;
371 if (!optarg || strcmp(optarg, "-") == 0)
372 event_fd = STDIN_FILENO;
373 else
374 event_fd = open(optarg, O_RDONLY);
375 if (event_fd == -1) {
376 fprintf(stderr, "Could not open file '%s' "
377 "(%m)\n", optarg);
378 usage("-S requires a valid file path or '-' "
379 "for STDIN.");
380 }
381 break;
336 case 'm': 382 case 'm':
337 nr_of_pages = atoi(optarg); 383 nr_of_pages = atoi(optarg);
338 break; 384 break;
@@ -426,24 +472,8 @@ int main(int argc, char** argv)
426 return 0; 472 return 0;
427 } 473 }
428 474
429 if (file) { 475 if (argc - optind < 3 || (argc - optind < 2 && !file))
430 get_exec_times(file, column, &num_jobs, &exec_times); 476 usage("Arguments missing.");
431
432 if (argc - optind < 2)
433 usage("Arguments missing.");
434
435 for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
436 /* convert the execution time to seconds */
437 duration += exec_times[cur_job] * 0.001;
438 } <