summaryrefslogtreecommitdiffstats
path: root/extra.h
diff options
context:
space:
mode:
Diffstat (limited to 'extra.h')
-rw-r--r--extra.h196
1 files changed, 140 insertions, 56 deletions
diff --git a/extra.h b/extra.h
index 8c67b33..8c894f6 100644
--- a/extra.h
+++ b/extra.h
@@ -29,8 +29,13 @@ extern int sched_getcpu();
29#include <sys/syscall.h> 29#include <sys/syscall.h>
30#endif 30#endif
31 31
32<<<<<<< HEAD
32#define LITMUS 1 33#define LITMUS 1
33#define MC2 0 34#define MC2 0
35=======
36// This is a proxy for "case study mode" now
37#define LITMUS 0
38>>>>>>> rtas20-wip
34#define MMDC_PROF 0 39#define MMDC_PROF 0
35 40
36#if LITMUS 41#if LITMUS
@@ -41,18 +46,6 @@ extern int sched_getcpu();
41#include "/media/speedy/litmus/tools/mmdc/mmdc.h" 46#include "/media/speedy/litmus/tools/mmdc/mmdc.h"
42#endif 47#endif
43 48
44#if LITMUS
45#define SET_UP LOAD_PARAMS SETUP_LITMUS
46#else
47#define SET_UP LOAD_PARAMS
48#endif
49
50#if MMDC_PROF
51#define LOAD_PARAMS LOAD_PARAMS_ITRL SETUP_MMDC
52#else
53#define LOAD_PARAMS LOAD_PARAMS_ITRL
54#endif
55
56// Store state globally so that the job can be outside main() 49// Store state globally so that the job can be outside main()
57// Arrays use float as a comprimise between overflow and size 50// Arrays use float as a comprimise between overflow and size
58// Paired arrays use long longs as precision is more important for those times 51// Paired arrays use long longs as precision is more important for those times
@@ -82,50 +75,72 @@ char *_rt_other_core;
82char *_rt_barrier; 75char *_rt_barrier;
83sem_t *_rt_first_sem, *_rt_second_sem; 76sem_t *_rt_first_sem, *_rt_second_sem;
84int _rt_lock_id; 77int _rt_lock_id;
78#define _ID_SZ 128
79char _rt_sem1_name[_ID_SZ] = "/_libextra_first_sem-";
80char _rt_sem2_name[_ID_SZ] = "/_libextra_second_sem-";
81char _rt_shm_name[_ID_SZ] = "/_libextra_barrier-";
82#endif /* PAIRED */
83
84#if LITMUS
85long unsigned int _rt_period;
85#endif 86#endif
86 87
87static void _rt_load_params_itrl(int argc, char **argv) { 88static void _rt_load_params_itrl(int argc, char **argv) {
88#ifdef PAIRED 89#ifdef PAIRED
89 if (argc != 8) { 90 if (argc != (8 + LITMUS*2) && argc != (9 + LITMUS*2)) {
90 fprintf(stderr, "Usage: %s <name> <loops> <my core> <other core> <other name> <runID> <lockID>", argv[0]); 91 fprintf(stderr, "Usage: %s <name> <loops> <my core> <other core> <other name> <runID> <save results?>", argv[0]);
91 fprintf(stderr, " <name> string for logging. Name of this task.\n");
92 fprintf(stderr, " <loops> integer number of iterations. -1 for infinite.\n");
93 fprintf(stderr, " <my core> UNUSED. Core is now auto-detected.\n");
94 fprintf(stderr, " <other core> integer for logging. Core of paired task.\n");
95 fprintf(stderr, " <other name> string for logging. Name of paired task.\n");
96 fprintf(stderr, " <runID> string to append with .txt to yield output file name.\n");
97 fprintf(stderr, " <lockID> 1 to indicate this is pair member 1, otherwise pair member 2.\n");
98 exit(1);
99 }
100#else 92#else
101 if (argc != 6) { 93 if (argc != (6 + LITMUS*2)) {
102 fprintf(stderr, "Usage: %s <name> <loops> <my core> <runID> <save results?>\n", argv[0]); 94 fprintf(stderr, "Usage: %s <name> <loops> <my core> <runID> <save results?>\n", argv[0]);
95#endif /* PAIRED */
103 fprintf(stderr, " <name> string for logging. Name of this task.\n"); 96 fprintf(stderr, " <name> string for logging. Name of this task.\n");
104 fprintf(stderr, " <loops> integer number of iterations. -1 for infinite.\n"); 97 fprintf(stderr, " <loops> integer number of iterations. -1 for infinite.\n");
105 fprintf(stderr, " <my core> UNUSED. Core is now auto-detected.\n"); 98 fprintf(stderr, " <my core> integer core number. Only used for LITMUS-RT.\n");
99#ifdef PAIRED
100 fprintf(stderr, " <other core> integer for logging. Core of paired task.\n");
101 fprintf(stderr, " <other name> string for logging. Name of paired task.\n");
102#endif /* PAIRED */
106 fprintf(stderr, " <runID> string to append with .txt to yield output file name.\n"); 103 fprintf(stderr, " <runID> string to append with .txt to yield output file name.\n");
107 fprintf(stderr, " <save results?> 1 to save results, 0 to discard.\n"); 104 fprintf(stderr, " <save results?> 1 to save results, 0 to discard.\n");
105#ifdef PAIRED
106 fprintf(stderr, " <pairID> (optional).\n");
107#endif
108#if LITMUS
109 fprintf(stderr, " <task period> in ms\n");
110 fprintf(stderr, " <task criticality level> 0 for Level-A, 1 for Level-B, 2 for Level-C\n");
111#endif /* LITMUS */
108 exit(1); 112 exit(1);
109 } 113 }
110#endif
111 _rt_our_prog_name = argv[1]; 114 _rt_our_prog_name = argv[1];
112 _rt_max_jobs = atol(argv[2]); 115 _rt_max_jobs = atol(argv[2]);
116#if !LITMUS
113 _rt_core = sched_getcpu(); 117 _rt_core = sched_getcpu();
118#else
119 _rt_core = atoi(argv[3]);
120#endif
114#ifdef PAIRED 121#ifdef PAIRED
115 _rt_other_core = argv[4]; 122 _rt_other_core = argv[4];
116 _rt_other_prog_name = argv[5]; 123 _rt_other_prog_name = argv[5];
117 _rt_run_id = argv[6]; 124 _rt_run_id = argv[6];
118 _rt_lock_id = atoi(argv[7]); 125 _rt_will_output = atoi(argv[7]);
119 // The paired version doesn't support disabling output (legacy compatibility) 126 char *pairId;
120 _rt_will_output = 1; 127 int end;
128 if (argc > 8) {
129 pairId = argv[8];
130 end = 8;
131 } else {
132 pairId = "none";
133 end = 9;
134 }
121#else 135#else
122 _rt_other_core = "none"; 136 _rt_other_core = "none";
123 _rt_other_prog_name = "none"; 137 _rt_other_prog_name = "none";
124 _rt_run_id = argv[4]; 138 _rt_run_id = argv[4];
125 _rt_will_output = atoi(argv[5]); 139 _rt_will_output = atoi(argv[5]);
140 int end = 6;
126#endif /* PAIRED */ 141#endif /* PAIRED */
127 if (_rt_max_jobs < 0 && _rt_will_output != 0) { 142 if (_rt_max_jobs < 0 && _rt_will_output != 0) {
128 fprintf(stderr, "Infinite loops only supported when _rt_will_output is disabled!\n"); 143 fprintf(stderr, "Infinite loops only supported when output is disabled!\n");
129 exit(1); 144 exit(1);
130 } 145 }
131 if (strlen(_rt_run_id) + 5 > _RT_FILENAME_LEN) { 146 if (strlen(_rt_run_id) + 5 > _RT_FILENAME_LEN) {
@@ -133,32 +148,54 @@ static void _rt_load_params_itrl(int argc, char **argv) {
133 exit(1); 148 exit(1);
134 } 149 }
135#ifdef PAIRED 150#ifdef PAIRED
151 // __rt_sem2_name happens to be the longest
152 if (strlen(pairId) + strlen(_rt_sem2_name) > _ID_SZ) {
153 fprintf(stderr, "PairID is too long! Maximum length is %ld characters.\n", _ID_SZ - strlen(_rt_sem2_name));
154 exit(1);
155 }
136 _rt_start_time = calloc(_rt_max_jobs * _rt_will_output, sizeof(long long)); 156 _rt_start_time = calloc(_rt_max_jobs * _rt_will_output, sizeof(long long));
137 _rt_end_time = calloc(_rt_max_jobs * _rt_will_output, sizeof(long long)); 157 _rt_end_time = calloc(_rt_max_jobs * _rt_will_output, sizeof(long long));
138 if (!_rt_end_time || !_rt_start_time) { 158 if (!_rt_end_time || !_rt_start_time) {
139 perror("Unable to allocate buffers for execution times"); 159 perror("Unable to allocate buffers for execution times");
140 exit(1); 160 exit(1);
141 } 161 }
142 _rt_first_sem = sem_open("/_libextra_first_sem", O_CREAT, 644, 0); 162 // Use PairID to create unique semaphore and shared memory paths
143 _rt_second_sem = sem_open("/_libextra_second_sem", O_CREAT, 644, 0); 163 strcat(_rt_sem1_name, pairId);
164 strcat(_rt_sem2_name, pairId);
165 strcat(_rt_shm_name, pairId);
166 _rt_first_sem = sem_open(_rt_sem1_name, O_CREAT, 644, 0);
167 _rt_second_sem = sem_open(_rt_sem2_name, O_CREAT, 644, 0);
144 if (_rt_first_sem == SEM_FAILED || _rt_second_sem == SEM_FAILED) { 168 if (_rt_first_sem == SEM_FAILED || _rt_second_sem == SEM_FAILED) {
145 perror("Error while creating semaphores"); 169 perror("Error while creating semaphores");
146 exit(1); 170 exit(1);
147 } 171 }
148 int barrier_file = shm_open("/_libextra_barrier", O_CREAT | O_RDWR, 644); 172 // Create shared memory for barrier synchronization and infer lock ID
173 int barrier_file = shm_open(_rt_shm_name, O_CREAT | O_RDWR | O_EXCL, 644);
174 if (barrier_file == -1) {
175 // File already existed - we're the 2nd program and thus lock ID 2
176 _rt_lock_id = 2;
177 barrier_file = shm_open(_rt_shm_name, O_CREAT | O_RDWR, 644);
178 } else {
179 _rt_lock_id = 1;
180 }
149 if (barrier_file == -1) { 181 if (barrier_file == -1) {
150 perror("Error while creating shared memory for barrier synchronization"); 182 perror("Error while creating shared memory for barrier synchronization");
151 exit(1); 183 exit(1);
152 } 184 }
153 if (ftruncate(barrier_file, 1) == -1) { 185 if (ftruncate(barrier_file, 2) == -1) {
154 perror("Error while setting size of shared memory for barrier synchronization"); 186 perror("Error while setting size of shared memory for barrier synchronization");
155 exit(1); 187 exit(1);
156 } 188 }
157 _rt_barrier = mmap(NULL, 1, PROT_WRITE, MAP_SHARED, barrier_file, 0); 189 _rt_barrier = mmap(NULL, 2, PROT_WRITE, MAP_SHARED, barrier_file, 0);
158 if (_rt_barrier == MAP_FAILED) { 190 if (_rt_barrier == MAP_FAILED) {
159 perror("Error while mapping shared memory for barrier synchronization"); 191 perror("Error while mapping shared memory for barrier synchronization");
160 exit(1); 192 exit(1);
161 } 193 }
194 // If we're the 2nd user of this barrier, mark it as in-use
195 if (_rt_lock_id == 2 && !__sync_bool_compare_and_swap(_rt_barrier+1, 0, 1)) {
196 fprintf(stderr, "Pair ID already in use!\n");
197 exit(1);
198 }
162 *_rt_barrier = 0; 199 *_rt_barrier = 0;
163#else 200#else
164 _rt_exec_time = calloc(_rt_max_jobs * _rt_will_output, sizeof(float)); 201 _rt_exec_time = calloc(_rt_max_jobs * _rt_will_output, sizeof(float));
@@ -169,8 +206,46 @@ static void _rt_load_params_itrl(int argc, char **argv) {
169#endif /* PAIRED */ 206#endif /* PAIRED */
170 _rt_jobs_complete = 0; 207 _rt_jobs_complete = 0;
171 mlockall(MCL_CURRENT || MCL_FUTURE); 208 mlockall(MCL_CURRENT || MCL_FUTURE);
209#if LITMUS
210 _rt_period = strtoul(argv[end], NULL, 10);
211 unsigned int crit = atoi(argv[end+1]);
212 unsigned int wait = 1;
213 if (be_migrate_to_domain(_rt_core) < 0) {
214 perror("Unable to migrate to specified CPU");
215 exit(1);
216 }
217 struct rt_task rt_param;
218 init_rt_task_param(&rt_param);
219 rt_param.exec_cost = 0; // We disable budget enforcement, so this doesn't matter
220 rt_param.period = ms2ns(_rt_period);
221 rt_param.relative_deadline = 0;
222 rt_param.phase = 0;
223 rt_param.priority = LITMUS_LOWEST_PRIORITY;
224 rt_param.cls = crit;
225 rt_param.release_policy = TASK_PERIODIC;
226 rt_param.budget_policy = NO_ENFORCEMENT;
227 rt_param.cpu = _rt_core;
228 if (set_rt_task_param(gettid(), &rt_param) < 0) {
229 perror("Unable to set real-time parameters");
230 exit(1);
231 }
232 if (init_litmus() != 0) {
233 perror("init_litmus failed");
234 exit(1);
235 }
236 if (task_mode(LITMUS_RT_TASK) != 0) {
237 perror("Unable to become real-time task");
238 exit(1);
239 }
240 if (wait && wait_for_ts_release() != 0) {
241 perror("Unable to wait for taskset release");
242 exit(1);
243 }
244#endif /* LITMUS */
245#if MMDC_PROF
246 SETUP_MMDC
247#endif
172} 248}
173#define LOAD_PARAMS_ITRL _rt_load_params_itrl(argc, argv);
174 249
175#define SETUP_MMDC \ 250#define SETUP_MMDC \
176 _rt_mmdc_read = calloc(_rt_max_jobs * _rt_will_output, sizeof(float));\ 251 _rt_mmdc_read = calloc(_rt_max_jobs * _rt_will_output, sizeof(float));\
@@ -194,6 +269,7 @@ static void _rt_load_params_itrl(int argc, char **argv) {
194 mmdc->madpcr1 = axi_arm1;\ 269 mmdc->madpcr1 = axi_arm1;\
195 msync(&(mmdc->madpcr1),4,MS_SYNC); 270 msync(&(mmdc->madpcr1),4,MS_SYNC);
196 271
272<<<<<<< HEAD
197#define SETUP_LITMUS \ 273#define SETUP_LITMUS \
198 unsigned int wait = 0; \ 274 unsigned int wait = 0; \
199 if (be_migrate_to_domain(_rt_core) < 0) { \ 275 if (be_migrate_to_domain(_rt_core) < 0) { \
@@ -242,6 +318,8 @@ static void _rt_load_params_itrl(int argc, char **argv) {
242 exit(1); \ 318 exit(1); \
243 } \ 319 } \
244 320
321=======
322>>>>>>> rtas20-wip
245#if __arm__ 323#if __arm__
246// On ARM, manually flush the cache 324// On ARM, manually flush the cache
247#define FLUSH_CACHES \ 325#define FLUSH_CACHES \
@@ -305,28 +383,28 @@ static void _rt_load_params_itrl(int argc, char **argv) {
305 383
306// Buffer timing result from a single job 384// Buffer timing result from a single job
307static void _rt_save_job_result() { 385static void _rt_save_job_result() {
386 if (!_rt_will_output)
387 return;
308 if (_rt_jobs_complete >= _rt_max_jobs) { 388 if (_rt_jobs_complete >= _rt_max_jobs) {
309 fprintf(stderr, "Max jobs setting too small! Trying to record job #%ld when we only have space for %ld jobs. Exiting...\n", _rt_jobs_complete, _rt_max_jobs); 389 fprintf(stderr, "Max jobs setting too small! Trying to record job #%ld when we only have space for %ld jobs. Exiting...\n", _rt_jobs_complete, _rt_max_jobs);
310 exit(1); 390 exit(1);
311 } 391 }
312 if (_rt_jobs_complete > -1 && _rt_will_output) {
313#ifdef PAIRED 392#ifdef PAIRED
314 _rt_start_time[_rt_jobs_complete] = _rt_start.tv_sec; 393 _rt_start_time[_rt_jobs_complete] = _rt_start.tv_sec;
315 _rt_start_time[_rt_jobs_complete] *= _BILLION; 394 _rt_start_time[_rt_jobs_complete] *= _BILLION;
316 _rt_start_time[_rt_jobs_complete] += _rt_start.tv_nsec; 395 _rt_start_time[_rt_jobs_complete] += _rt_start.tv_nsec;
317 _rt_end_time[_rt_jobs_complete] = _rt_end.tv_sec; 396 _rt_end_time[_rt_jobs_complete] = _rt_end.tv_sec;
318 _rt_end_time[_rt_jobs_complete] *= _BILLION; 397 _rt_end_time[_rt_jobs_complete] *= _BILLION;
319 _rt_end_time[_rt_jobs_complete] += _rt_end.tv_nsec; 398 _rt_end_time[_rt_jobs_complete] += _rt_end.tv_nsec;
320#else 399#else
321 _rt_exec_time[_rt_jobs_complete] = _rt_end.tv_sec - _rt_start.tv_sec; 400 _rt_exec_time[_rt_jobs_complete] = _rt_end.tv_sec - _rt_start.tv_sec;
322 _rt_exec_time[_rt_jobs_complete] *= _BILLION; 401 _rt_exec_time[_rt_jobs_complete] *= _BILLION;
323 _rt_exec_time[_rt_jobs_complete] += _rt_end.tv_nsec - _rt_start.tv_nsec; 402 _rt_exec_time[_rt_jobs_complete] += _rt_end.tv_nsec - _rt_start.tv_nsec;
324#endif /* PAIRED */ 403#endif /* PAIRED */
325#if MMDC_PROF 404#if MMDC_PROF
326 _rt_mmdc_read[_rt_jobs_complete] = mmdc_res.read_bytes; 405 _rt_mmdc_read[_rt_jobs_complete] = mmdc_res.read_bytes;
327 _rt_mmdc_write[_rt_jobs_complete] = mmdc_res.write_bytes; 406 _rt_mmdc_write[_rt_jobs_complete] = mmdc_res.write_bytes;
328#endif 407#endif /* MMDC_PROF */
329 }
330} 408}
331 409
332// Save all buffered timing results to disk 410// Save all buffered timing results to disk
@@ -365,13 +443,16 @@ static void _rt_write_to_file() {
365 fclose(fp); 443 fclose(fp);
366out: 444out:
367#if LITMUS 445#if LITMUS
368 CLEANUP_LITMUS 446 if (task_mode(BACKGROUND_TASK) != 0) {
447 perror("Unable to become a real-time task");
448 exit(1);
449 }
369#endif /* LITMUS */ 450#endif /* LITMUS */
370#ifdef PAIRED 451#ifdef PAIRED
371 munmap(_rt_barrier, 1); 452 munmap(_rt_barrier, 2);
372 shm_unlink("/_libextra_barrier"); 453 sem_unlink(_rt_sem1_name);
373 sem_unlink("/_libextra_first_sem"); 454 sem_unlink(_rt_sem2_name);
374 sem_unlink("/_libextra_second_sem"); 455 shm_unlink(_rt_shm_name);
375 free(_rt_start_time); 456 free(_rt_start_time);
376 free(_rt_end_time); 457 free(_rt_end_time);
377#else 458#else
@@ -396,7 +477,9 @@ static void _rt_start_loop() {
396 FIRST_UNLOCK 477 FIRST_UNLOCK
397 FIRST_LOCK 478 FIRST_LOCK
398#endif /* PAIRED */ 479#endif /* PAIRED */
480#if !LITMUS
399 FLUSH_CACHES 481 FLUSH_CACHES
482#endif
400#ifdef PAIRED 483#ifdef PAIRED
401 BARRIER_SYNC 484 BARRIER_SYNC
402#endif /* PAIRED */ 485#endif /* PAIRED */
@@ -444,7 +527,7 @@ static void _rt_stop_loop() {
444 * result. We use this to call our void function from inside a comparison. 527 * result. We use this to call our void function from inside a comparison.
445 */ 528 */
446#define for_each_job \ 529#define for_each_job \
447 for (; _rt_jobs_complete < _rt_max_jobs && (_rt_start_loop(),1); \ 530 for (; (_rt_max_jobs == -1 || _rt_jobs_complete < _rt_max_jobs) && (_rt_start_loop(),1); \
448 _rt_stop_loop()) 531 _rt_stop_loop())
449 532
450/****** Legacy API ****** 533/****** Legacy API ******
@@ -466,6 +549,7 @@ static void _rt_stop_loop() {
466 * able to read them. 549 * able to read them.
467 */ 550 */
468static int jobsComplete = 0; 551static int jobsComplete = 0;
552#define SET_UP _rt_load_params_itrl(argc, argv);
469#define START_LOOP _rt_start_loop(); 553#define START_LOOP _rt_start_loop();
470#define STOP_LOOP _rt_stop_loop(); 554#define STOP_LOOP _rt_stop_loop();
471#define WRITE_TO_FILE _rt_write_to_file(); 555#define WRITE_TO_FILE _rt_write_to_file();