aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2013-03-13 15:33:57 -0400
committerGlenn Elliott <gelliott@cs.unc.edu>2013-03-13 15:33:57 -0400
commit944a78c21028da69fb53c0aec3e9dfdb048d47e4 (patch)
treebdbc77b3c0ff1337670a7e5d0f9d438388c1a866
parentf338b34ea0fb6136ea3895a07161ece030c4b998 (diff)
parent1ff4fc699f01f0ad1359fad48b00c9d3be1b28b4 (diff)
Merge branch 'gh/staging' into temp
Conflicts: Makefile bin/rt_launch.c bin/rtspin.c src/task.c
-rw-r--r--Makefile8
-rw-r--r--bin/base_mt_task.c30
-rw-r--r--bin/base_task.c28
-rw-r--r--bin/null_call.c4
-rw-r--r--bin/release_ts.c32
-rw-r--r--bin/rt_launch.c25
-rw-r--r--bin/rtspin.c113
-rw-r--r--bin/uncache.c381
-rw-r--r--gpu/aux_threads.c14
-rw-r--r--gpu/dgl.c20
-rw-r--r--gpu/ikglptest.c78
-rw-r--r--gpu/locktest.c2
-rw-r--r--gpu/nested.c4
-rw-r--r--gpu/rtspin_fake_cuda.cpp206
-rw-r--r--include/litmus.h34
-rw-r--r--include/tests.h7
-rw-r--r--src/kernel_iface.c15
-rw-r--r--src/litmus.c62
-rw-r--r--src/signal.c2
-rw-r--r--src/task.c12
-rw-r--r--tests/fdso.c4
-rw-r--r--tests/locks.c8
-rw-r--r--tests/nesting.c468
-rw-r--r--tests/pcp.c216
24 files changed, 1447 insertions, 326 deletions
diff --git a/Makefile b/Makefile
index 8886ff9..3489de6 100644
--- a/Makefile
+++ b/Makefile
@@ -19,7 +19,7 @@ LITMUS_KERNEL ?= ../litmus-rt
19# Internal configuration. 19# Internal configuration.
20 20
21# compiler flags 21# compiler flags
22flags-debug = -Wall -Wdeclaration-after-statement -g 22flags-debug = -O2 -Wall -Werror -g -Wdeclaration-after-statement
23flags-api = -D_XOPEN_SOURCE=600 -D_GNU_SOURCE 23flags-api = -D_XOPEN_SOURCE=600 -D_GNU_SOURCE
24flags-misc = -fasynchronous-unwind-tables -fnon-call-exceptions 24flags-misc = -fasynchronous-unwind-tables -fnon-call-exceptions
25 25
@@ -72,7 +72,8 @@ AR := ${CROSS_COMPILE}${AR}
72 72
73all = lib ${rt-apps} 73all = lib ${rt-apps}
74rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \ 74rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \
75 base_mt_task runtests nested locktest ikglptest dgl aux_threads normal_task 75 base_mt_task uncache runtests \
76 nested locktest ikglptest dgl aux_threads normal_task
76 77
77.PHONY: all lib clean dump-config TAGS tags cscope help 78.PHONY: all lib clean dump-config TAGS tags cscope help
78 79
@@ -237,6 +238,9 @@ lib-normal_task = -lrt -pthread -lm
237obj-dgl = dgl.o common.o 238obj-dgl = dgl.o common.o
238lib-dgl = -lrt -pthread 239lib-dgl = -lrt -pthread
239 240
241obj-uncache = uncache.o
242lib-uncache = -lrt
243
240obj-release_ts = release_ts.o 244obj-release_ts = release_ts.o
241 245
242obj-measure_syscall = null_call.o 246obj-measure_syscall = null_call.o
diff --git a/bin/base_mt_task.c b/bin/base_mt_task.c
index 8090cc3..1d72143 100644
--- a/bin/base_mt_task.c
+++ b/bin/base_mt_task.c
@@ -1,4 +1,4 @@
1/* based_mt_task.c -- A basic multi-threaded real-time task skeleton. 1/* based_mt_task.c -- A basic multi-threaded real-time task skeleton.
2 * 2 *
3 * This (by itself useless) task demos how to setup a multi-threaded LITMUS^RT 3 * This (by itself useless) task demos how to setup a multi-threaded LITMUS^RT
4 * real-time task. Familiarity with the single threaded example (base_task.c) 4 * real-time task. Familiarity with the single threaded example (base_task.c)
@@ -28,10 +28,10 @@
28 28
29#define NS_PER_MS 1e6 29#define NS_PER_MS 1e6
30 30
31/* Let's create 10 threads in the example, 31/* Let's create 10 threads in the example,
32 * for a total utilization of 1. 32 * for a total utilization of 1.
33 */ 33 */
34#define NUM_THREADS 10 34#define NUM_THREADS 10
35 35
36/* The information passed to each thread. Could be anything. */ 36/* The information passed to each thread. Could be anything. */
37struct thread_context { 37struct thread_context {
@@ -43,7 +43,7 @@ struct thread_context {
43 */ 43 */
44void* rt_thread(void *tcontext); 44void* rt_thread(void *tcontext);
45 45
46/* Declare the periodically invoked job. 46/* Declare the periodically invoked job.
47 * Returns 1 -> task should exit. 47 * Returns 1 -> task should exit.
48 * 0 -> task should continue. 48 * 0 -> task should continue.
49 */ 49 */
@@ -62,7 +62,7 @@ int job(void);
62 } while (0) 62 } while (0)
63 63
64 64
65/* Basic setup is the same as in the single-threaded example. However, 65/* Basic setup is the same as in the single-threaded example. However,
66 * we do some thread initiliazation first before invoking the job. 66 * we do some thread initiliazation first before invoking the job.
67 */ 67 */
68int main(int argc, char** argv) 68int main(int argc, char** argv)
@@ -71,7 +71,7 @@ int main(int argc, char** argv)
71 struct thread_context ctx[NUM_THREADS]; 71 struct thread_context ctx[NUM_THREADS];
72 pthread_t task[NUM_THREADS]; 72 pthread_t task[NUM_THREADS];
73 73
74 /* The task is in background mode upon startup. */ 74 /* The task is in background mode upon startup. */
75 75
76 76
77 /***** 77 /*****
@@ -79,7 +79,7 @@ int main(int argc, char** argv)
79 */ 79 */
80 80
81 81
82 82
83 /***** 83 /*****
84 * 2) Work environment (e.g., global data structures, file data, etc.) would 84 * 2) Work environment (e.g., global data structures, file data, etc.) would
85 * be setup here. 85 * be setup here.
@@ -94,7 +94,7 @@ int main(int argc, char** argv)
94 init_litmus(); 94 init_litmus();
95 95
96 96
97 /***** 97 /*****
98 * 4) Launch threads. 98 * 4) Launch threads.
99 */ 99 */
100 for (i = 0; i < NUM_THREADS; i++) { 100 for (i = 0; i < NUM_THREADS; i++) {
@@ -102,15 +102,15 @@ int main(int argc, char** argv)
102 pthread_create(task + i, NULL, rt_thread, (void *) (ctx + i)); 102 pthread_create(task + i, NULL, rt_thread, (void *) (ctx + i));
103 } 103 }
104 104
105 105
106 /***** 106 /*****
107 * 5) Wait for RT threads to terminate. 107 * 5) Wait for RT threads to terminate.
108 */ 108 */
109 for (i = 0; i < NUM_THREADS; i++) 109 for (i = 0; i < NUM_THREADS; i++)
110 pthread_join(task[i], NULL); 110 pthread_join(task[i], NULL);
111
112 111
113 /***** 112
113 /*****
114 * 6) Clean up, maybe print results and stats, and exit. 114 * 6) Clean up, maybe print results and stats, and exit.
115 */ 115 */
116 return 0; 116 return 0;
@@ -166,7 +166,7 @@ void* rt_thread(void *tcontext)
166 */ 166 */
167 CALL( task_mode(LITMUS_RT_TASK) ); 167 CALL( task_mode(LITMUS_RT_TASK) );
168 168
169 /* The task is now executing as a real-time task if the call didn't fail. 169 /* The task is now executing as a real-time task if the call didn't fail.
170 */ 170 */
171 171
172 172
@@ -178,11 +178,11 @@ void* rt_thread(void *tcontext)
178 /* Wait until the next job is released. */ 178 /* Wait until the next job is released. */
179 sleep_next_period(); 179 sleep_next_period();
180 /* Invoke job. */ 180 /* Invoke job. */
181 do_exit = job(); 181 do_exit = job();
182 } while (!do_exit); 182 } while (!do_exit);
183 183
184 184
185 185
186 /***** 186 /*****
187 * 4) Transition to background mode. 187 * 4) Transition to background mode.
188 */ 188 */
@@ -194,7 +194,7 @@ void* rt_thread(void *tcontext)
194 194
195 195
196 196
197int job(void) 197int job(void)
198{ 198{
199 /* Do real-time calculation. */ 199 /* Do real-time calculation. */
200 200
diff --git a/bin/base_task.c b/bin/base_task.c
index df0c5a2..2b0a49c 100644
--- a/bin/base_task.c
+++ b/bin/base_task.c
@@ -1,6 +1,6 @@
1/* based_task.c -- A basic real-time task skeleton. 1/* based_task.c -- A basic real-time task skeleton.
2 * 2 *
3 * This (by itself useless) task demos how to setup a 3 * This (by itself useless) task demos how to setup a
4 * single-threaded LITMUS^RT real-time task. 4 * single-threaded LITMUS^RT real-time task.
5 */ 5 */
6 6
@@ -20,7 +20,7 @@
20 */ 20 */
21#include "litmus.h" 21#include "litmus.h"
22 22
23/* Next, we define period and execution cost to be constant. 23/* Next, we define period and execution cost to be constant.
24 * These are only constants for convenience in this example, they can be 24 * These are only constants for convenience in this example, they can be
25 * determined at run time, e.g., from command line parameters. 25 * determined at run time, e.g., from command line parameters.
26 * 26 *
@@ -44,13 +44,13 @@
44 } while (0) 44 } while (0)
45 45
46 46
47/* Declare the periodically invoked job. 47/* Declare the periodically invoked job.
48 * Returns 1 -> task should exit. 48 * Returns 1 -> task should exit.
49 * 0 -> task should continue. 49 * 0 -> task should continue.
50 */ 50 */
51int job(void); 51int job(void);
52 52
53/* typically, main() does a couple of things: 53/* typically, main() does a couple of things:
54 * 1) parse command line parameters, etc. 54 * 1) parse command line parameters, etc.
55 * 2) Setup work environment. 55 * 2) Setup work environment.
56 * 3) Setup real-time parameters. 56 * 3) Setup real-time parameters.
@@ -60,7 +60,7 @@ int job(void);
60 * 7) Clean up and exit. 60 * 7) Clean up and exit.
61 * 61 *
62 * The following main() function provides the basic skeleton of a single-threaded 62 * The following main() function provides the basic skeleton of a single-threaded
63 * LITMUS^RT real-time task. In a real program, all the return values should be 63 * LITMUS^RT real-time task. In a real program, all the return values should be
64 * checked for errors. 64 * checked for errors.
65 */ 65 */
66int main(int argc, char** argv) 66int main(int argc, char** argv)
@@ -100,9 +100,9 @@ int main(int argc, char** argv)
100 100
101 101
102 /***** 102 /*****
103 * 3) Setup real-time parameters. 103 * 3) Setup real-time parameters.
104 * In this example, we create a sporadic task that does not specify a 104 * In this example, we create a sporadic task that does not specify a
105 * target partition (and thus is intended to run under global scheduling). 105 * target partition (and thus is intended to run under global scheduling).
106 * If this were to execute under a partitioned scheduler, it would be assigned 106 * If this were to execute under a partitioned scheduler, it would be assigned
107 * to the first partition (since partitioning is performed offline). 107 * to the first partition (since partitioning is performed offline).
108 */ 108 */
@@ -124,7 +124,7 @@ int main(int argc, char** argv)
124 */ 124 */
125 CALL( task_mode(LITMUS_RT_TASK) ); 125 CALL( task_mode(LITMUS_RT_TASK) );
126 126
127 /* The task is now executing as a real-time task if the call didn't fail. 127 /* The task is now executing as a real-time task if the call didn't fail.
128 */ 128 */
129 129
130 130
@@ -136,11 +136,11 @@ int main(int argc, char** argv)
136 /* Wait until the next job is released. */ 136 /* Wait until the next job is released. */
137 sleep_next_period(); 137 sleep_next_period();
138 /* Invoke job. */ 138 /* Invoke job. */
139 do_exit = job(); 139 do_exit = job();
140 } while (!do_exit); 140 } while (!do_exit);
141 141
142 142
143 143
144 /***** 144 /*****
145 * 6) Transition to background mode. 145 * 6) Transition to background mode.
146 */ 146 */
@@ -148,14 +148,14 @@ int main(int argc, char** argv)
148 148
149 149
150 150
151 /***** 151 /*****
152 * 7) Clean up, maybe print results and stats, and exit. 152 * 7) Clean up, maybe print results and stats, and exit.
153 */ 153 */
154 return 0; 154 return 0;
155} 155}
156 156
157 157
158int job(void) 158int job(void)
159{ 159{
160 /* Do real-time calculation. */ 160 /* Do real-time calculation. */
161 161
diff --git a/bin/null_call.c b/bin/null_call.c
index d714e77..bab8e73 100644
--- a/bin/null_call.c
+++ b/bin/null_call.c
@@ -16,7 +16,7 @@ static void time_null_call(void)
16 t2 = get_cycles(); 16 t2 = get_cycles();
17 if (ret != 0) 17 if (ret != 0)
18 perror("null_call"); 18 perror("null_call");
19 printf("%10" CYCLES_FMT ", " 19 printf("%10" CYCLES_FMT ", "
20 "%10" CYCLES_FMT ", " 20 "%10" CYCLES_FMT ", "
21 "%10" CYCLES_FMT ", " 21 "%10" CYCLES_FMT ", "
22 "%10" CYCLES_FMT ", " 22 "%10" CYCLES_FMT ", "
@@ -38,7 +38,7 @@ int main(int argc, char **argv)
38{ 38{
39 double delay; 39 double delay;
40 struct timespec sleep_time; 40 struct timespec sleep_time;
41 41
42 if (argc == 2) { 42 if (argc == 2) {
43 delay = atof(argv[1]); 43 delay = atof(argv[1]);
44 sleep_time = sec2timespec(delay); 44 sleep_time = sec2timespec(delay);
diff --git a/bin/release_ts.c b/bin/release_ts.c
index 7752097..f745c52 100644
--- a/bin/release_ts.c
+++ b/bin/release_ts.c
@@ -31,35 +31,14 @@ void usage(char *error) {
31void wait_until_ready(int expected) 31void wait_until_ready(int expected)
32{ 32{
33 int ready = 0, all = 0; 33 int ready = 0, all = 0;
34 char buf[100];
35 int loops = 0; 34 int loops = 0;
36 ssize_t len;
37
38 35
39 do { 36 do {
40 if (loops++ > 0) 37 if (loops++ > 0)
41 sleep(1); 38 sleep(1);
42 len = read_file(LITMUS_STATS_FILE, buf, sizeof(buf) - 1); 39 if (!read_litmus_stats(&ready, &all))
43 if (len < 0) { 40 perror("read_litmus_stats");
44 fprintf(stderr, 41 } while (expected > ready || (!expected && ready < all));
45 "(EE) Error while reading '%s': %m.\n"
46 "(EE) Ignoring -w option.\n",
47 LITMUS_STATS_FILE);
48 break;
49 } else {
50 len = sscanf(buf,
51 "real-time tasks = %d\n"
52 "ready for release = %d\n",
53 &all, &ready);
54 if (len != 2) {
55 fprintf(stderr,
56 "(EE) Could not parse '%s'.\n"
57 "(EE) Ignoring -w option.\n",
58 LITMUS_STATS_FILE);
59 break;
60 }
61 }
62 } while (expected > ready || ready < all);
63} 42}
64 43
65int main(int argc, char** argv) 44int main(int argc, char** argv)
@@ -69,7 +48,7 @@ int main(int argc, char** argv)
69 int wait = 0; 48 int wait = 0;
70 int expected = 0; 49 int expected = 0;
71 int opt; 50 int opt;
72 51
73 while ((opt = getopt(argc, argv, OPTSTR)) != -1) { 52 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
74 switch (opt) { 53 switch (opt) {
75 case 'd': 54 case 'd':
@@ -79,6 +58,7 @@ int main(int argc, char** argv)
79 wait = 1; 58 wait = 1;
80 break; 59 break;
81 case 'f': 60 case 'f':
61 wait = 1;
82 expected = atoi(optarg); 62 expected = atoi(optarg);
83 break; 63 break;
84 case ':': 64 case ':':
@@ -99,7 +79,7 @@ int main(int argc, char** argv)
99 perror("release task system"); 79 perror("release task system");
100 exit(1); 80 exit(1);
101 } 81 }
102 82
103 printf("Released %d real-time tasks.\n", released); 83 printf("Released %d real-time tasks.\n", released);
104 84
105 return 0; 85 return 0;
diff --git a/bin/rt_launch.c b/bin/rt_launch.c
index 84a5e6c..db7a8b4 100644
--- a/bin/rt_launch.c
+++ b/bin/rt_launch.c
@@ -29,7 +29,7 @@ int launch(void *task_info_p) {
29} 29}
30 30
31void usage(char *error) { 31void usage(char *error) {
32 fprintf(stderr, "%s\nUsage: rt_launch [-w][-v][-p cpu][-c hrt | srt | be] wcet period program [arg1 arg2 ...]\n" 32 fprintf(stderr, "%s\nUsage: rt_launch [-w][-v][-p cpu][-q prio][-c hrt | srt | be] wcet period program [arg1 arg2 ...]\n"
33 "\t-w\tSynchronous release\n" 33 "\t-w\tSynchronous release\n"
34 "\t-v\tVerbose\n" 34 "\t-v\tVerbose\n"
35 "\t-p\tcpu (or initial cpu)\n" 35 "\t-p\tcpu (or initial cpu)\n"
@@ -41,9 +41,9 @@ void usage(char *error) {
41} 41}
42 42
43 43
44#define OPTSTR "p:c:vw" 44#define OPTSTR "p:c:vwq:"
45 45
46int main(int argc, char** argv) 46int main(int argc, char** argv)
47{ 47{
48 int ret; 48 int ret;
49 lt_t wcet; 49 lt_t wcet;
@@ -54,7 +54,8 @@ int main(int argc, char** argv)
54 int verbose = 0; 54 int verbose = 0;
55 int wait = 0; 55 int wait = 0;
56 startup_info_t info; 56 startup_info_t info;
57 task_class_t rt_class = RT_CLASS_HARD; 57 task_class_t cls = RT_CLASS_HARD;
58 unsigned int priority = LITMUS_LOWEST_PRIORITY;
58 59
59 while ((opt = getopt(argc, argv, OPTSTR)) != -1) { 60 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
60 switch (opt) { 61 switch (opt) {
@@ -68,9 +69,14 @@ int main(int argc, char** argv)
68 cpu = atoi(optarg); 69 cpu = atoi(optarg);
69 migrate = 1; 70 migrate = 1;
70 break; 71 break;
72 case 'q':
73 priority = atoi(optarg);
74 if (!litmus_is_valid_fixed_prio(priority))
75 usage("Invalid priority.");
76 break;
71 case 'c': 77 case 'c':
72 rt_class = str2class(optarg); 78 cls = str2class(optarg);
73 if (rt_class == -1) 79 if (cls == -1)
74 usage("Unknown task class."); 80 usage("Unknown task class.");
75 break; 81 break;
76 82
@@ -87,7 +93,7 @@ int main(int argc, char** argv)
87 signal(SIGUSR1, SIG_IGN); 93 signal(SIGUSR1, SIG_IGN);
88 94
89 if (argc - optind < 3) 95 if (argc - optind < 3)
90 usage("Arguments missing."); 96 usage("Arguments missing.");
91 wcet = ms2lt(atoi(argv[optind + 0])); 97 wcet = ms2lt(atoi(argv[optind + 0]));
92 period = ms2lt(atoi(argv[optind + 1])); 98 period = ms2lt(atoi(argv[optind + 1]));
93 if (wcet <= 0) 99 if (wcet <= 0)
@@ -107,13 +113,12 @@ int main(int argc, char** argv)
107 if (ret < 0) 113 if (ret < 0)
108 bail_out("could not migrate to target partition"); 114 bail_out("could not migrate to target partition");
109 } 115 }
110 ret = __create_rt_task(launch, &info, cpu, wcet, period, rt_class); 116 ret = __create_rt_task(launch, &info, cpu, wcet, period, priority, cls);
111 117
112
113 if (ret < 0) 118 if (ret < 0)
114 bail_out("could not create rt child process"); 119 bail_out("could not create rt child process");
115 else if (verbose) 120 else if (verbose)
116 printf("%d\n", ret); 121 printf("%d\n", ret);
117 122
118 return 0; 123 return 0;
119} 124}
diff --git a/bin/rtspin.c b/bin/rtspin.c
index cbfaee2..6632027 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
@@ -77,7 +80,7 @@ static void get_exec_times(const char *file, const int column,
77 80
78 for (cur_col = 1; cur_col < column; ++cur_col) { 81 for (cur_col = 1; cur_col < column; ++cur_col) {
79 /* discard input until we get to the column we want */ 82 /* discard input until we get to the column we want */
80 fscanf(fstream, "%*s,"); 83 int unused __attribute__ ((unused)) = fscanf(fstream, "%*s,");
81 } 84 }
82 85
83 /* get the desired exec. time */ 86 /* get the desired exec. time */
@@ -150,31 +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{
155 int exit = 0; 158 double chunk1, chunk2;
156 if (wctime() > program_end) { 159
157 exit = 1; 160 if (wctime() > program_end)
158 } 161 return 0;
159 else { 162 else {
160 LITMUS_TRY { 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 {
161 loop_for(exec_time, program_end + 1); 179 loop_for(exec_time, program_end + 1);
162 } 180 }
163 LITMUS_CATCH(SIG_BUDGET) {
164 fprintf(stdout, "Exhausted budget! Finishing job NOW!\n");
165 }
166 END_LITMUS_TRY;
167 }
168
169 if (!exit) {
170 sleep_next_period(); 181 sleep_next_period();
182 return 1;
171 } 183 }
172
173 return !exit;
174} 184}
175 185
176#define OPTSTR "p:c:wlveio:f:s:q:" 186#define OPTSTR "p:c:wlveio:f:s:q:X:L:Q:"
177
178int main(int argc, char** argv) 187int main(int argc, char** argv)
179{ 188{
180 int ret; 189 int ret;
@@ -191,11 +200,18 @@ int main(int argc, char** argv)
191 const char *file = NULL; 200 const char *file = NULL;
192 int want_enforcement = 0; 201 int want_enforcement = 0;
193 int want_signals = 0; 202 int want_signals = 0;
194 double duration = 0, start; 203 double duration = 0, start = 0;
195 double *exec_times = NULL; 204 double *exec_times = NULL;
196 double scale = 1.0; 205 double scale = 1.0;
197 task_class_t rt_class = RT_CLASS_HARD; 206 task_class_t cls = RT_CLASS_HARD;
198 int cur_job, num_jobs; 207 int cur_job = 0, num_jobs = 0;
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 */
199 215
200 progname = argv[0]; 216 progname = argv[0];
201 217
@@ -214,8 +230,8 @@ int main(int argc, char** argv)
214 usage("Invalid priority."); 230 usage("Invalid priority.");
215 break; 231 break;
216 case 'c': 232 case 'c':
217 rt_class = str2class(optarg); 233 cls = str2class(optarg);
218 if (rt_class == -1) 234 if (cls == -1)
219 usage("Unknown task class."); 235 usage("Unknown task class.");
220 break; 236 break;
221 case 'e': 237 case 'e':
@@ -236,6 +252,21 @@ int main(int argc, char** argv)
236 case 's': 252 case 's':
237 scale = atof(optarg); 253 scale = atof(optarg);
238 break; 254 break;
255 case 'X':
256 protocol = lock_protocol_for_name(optarg);
257 if (protocol < 0)
258 usage("Unknown locking protocol specified.");
259 break;
260 case 'L':
261 cs_length = atof(optarg);
262 if (cs_length <= 0)
263 usage("Invalid critical section length.");
264 break;
265 case 'Q':
266 resource_id = atoi(optarg);
267 if (resource_id <= 0 && strcmp(optarg, "0"))
268 usage("Invalid resource ID.");
269 break;
239 case ':': 270 case ':':
240 usage("Argument missing."); 271 usage("Argument missing.");
241 break; 272 break;
@@ -251,6 +282,8 @@ int main(int argc, char** argv)
251 return 0; 282 return 0;
252 } 283 }
253 284
285 srand(getpid());
286
254 if (file) { 287 if (file) {
255 get_exec_times(file, column, &num_jobs, &exec_times); 288 get_exec_times(file, column, &num_jobs, &exec_times);
256 289
@@ -296,12 +329,12 @@ int main(int argc, char** argv)
296 bail_out("could not migrate to target partition"); 329 bail_out("could not migrate to target partition");
297 } 330 }
298 331
299 ret = sporadic_task_ns(wcet, period, 0, cpu, priority, rt_class, 332 ret = sporadic_task_ns(wcet, period, 0, cpu, priority, cls,
300 want_enforcement ? PRECISE_ENFORCEMENT 333 want_enforcement ? PRECISE_ENFORCEMENT
301 : NO_ENFORCEMENT, 334 : NO_ENFORCEMENT,
302 want_signals ? PRECISE_SIGNALS 335 want_signals ? PRECISE_SIGNALS
303 : NO_SIGNALS, 336 : NO_SIGNALS,
304 migrate); 337 migrate);
305 if (ret < 0) 338 if (ret < 0)
306 bail_out("could not setup rt task params"); 339 bail_out("could not setup rt task params");
307 340
@@ -316,6 +349,15 @@ int main(int argc, char** argv)
316 if (ret != 0) 349 if (ret != 0)
317 bail_out("could not become RT task"); 350 bail_out("could not become RT task");
318 351
352 if (protocol >= 0) {
353 /* open reference to semaphore */
354 lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cpu);
355 if (lock_od < 0) {
356 perror("litmus_open_lock");
357 usage("Could not open lock.");
358 }
359 }
360
319 if (wait) { 361 if (wait) {
320 ret = wait_for_ts_release(); 362 ret = wait_for_ts_release();
321 if (ret != 0) 363 if (ret != 0)
@@ -329,14 +371,13 @@ int main(int argc, char** argv)
329 for (cur_job = 0; cur_job < num_jobs; ++cur_job) { 371 for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
330 /* convert job's length to seconds */ 372 /* convert job's length to seconds */
331 job(exec_times[cur_job] * 0.001 * scale, 373 job(exec_times[cur_job] * 0.001 * scale,
332 start + duration); 374 start + duration,
375 lock_od, cs_length * 0.001);
333 } 376 }
334 } else { 377 } else {
335 /* conver to seconds and scale */ 378 /* convert to seconds and scale */
336 int run = 1; 379 while (job(wcet_ms * 0.001 * scale, start + duration,
337 while (run) { 380 lock_od, cs_length * 0.001));
338 run = job(wcet_ms * 0.001 * scale, start + duration);
339 }
340 } 381 }
341 382
342 ret = task_mode(BACKGROUND_TASK); 383 ret = task_mode(BACKGROUND_TASK);
diff --git a/bin/uncache.c b/bin/uncache.c
new file mode 100644
index 0000000..b6f6913
--- /dev/null
+++ b/bin/uncache.c
@@ -0,0 +1,381 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <time.h>
5#include <sched.h>
6#include <assert.h>
7#include <string.h>
8#include <stdint.h>
9#include <sys/fcntl.h>
10#include <sys/mman.h>
11
12/* Test tool for validating Litmus's uncache device. */
13/* Tool also capable basic cache vs. sysmem statistics. */
14/* Compile with '-O2' for significaintly greater margins */
15/* in performance between cache and sysmem: */
16/* (Intel Xeon X5650) */
17/* -g -> uncache is 30x slower */
18/* -O2 -> uncache is >100x slower */
19
20int PAGE_SIZE;
21#define NR_PAGES 16
22
23#define UNCACHE_DEV "/dev/litmus/uncache"
24
25/* volatile forces a read from memory (or cache) on every reference. Note
26 that volatile does not keep data out of the cache! */
27typedef volatile char* pbuf_t;
28
29/* hit the first byte in each page.
30 addr must be page aligned. */
31inline int linear_write(pbuf_t addr, int size, char val)
32{
33 pbuf_t end = addr + size;
34 pbuf_t step;
35 int nr_pages = (unsigned long)(end - addr)/PAGE_SIZE;
36 int times = nr_pages * PAGE_SIZE;
37 int i;
38
39 for (i = 0; i < times; ++i)
40 for(step = addr; step < end; step += PAGE_SIZE)
41 *step = val;
42 return 0;
43}
44inline int linear_read(pbuf_t addr, int size, char val)
45{
46 pbuf_t end = addr + size;
47 pbuf_t step;
48 int nr_pages = (unsigned long)(end - addr)/PAGE_SIZE;
49 int times = nr_pages * PAGE_SIZE;
50 int i;
51
52 for (i = 0; i < times; ++i)
53 for(step = addr; step < end; step += PAGE_SIZE) {
54 if (*step != val)
55 return -1;
56 }
57 return 0;
58}
59
60/* write to *data nr times. */
61inline int hammer_write(pbuf_t data, char val, int nr)
62{
63 int i;
64 for (i = 0; i < nr; ++i)
65 *data = val;
66 return 0;
67}
68
69/* read from *data nr times. */
70inline int hammer_read(pbuf_t data, char val, int nr)
71{
72 int i;
73 for (i = 0; i < nr; ++i) {
74 if (*data != val)
75 return -1;
76 }
77 return 0;
78}
79
80inline int test(pbuf_t data, int size, int trials)
81{
82 int HAMMER_TIME = 10000; /* can't cache this! */
83 char VAL = 0x55;
84 int t;
85 for(t = 0; t < trials; ++t) {
86
87#if 0
88 if (linear_write(data, size, VAL) != 0) {
89 printf("failed linear_write()\n");
90 return -1;
91 }
92 if (linear_read(data, size, VAL) != 0) {
93 printf("failed linear_read()\n");
94 return -1;
95 }
96#endif
97
98 /* hammer at the first byte in the array */
99 if (hammer_write(data, VAL, HAMMER_TIME) != 0) {
100 printf("failed hammer_write()\n");
101 return -1;
102 }
103 if (hammer_read(data, VAL, HAMMER_TIME) != 0) {
104 printf("failed hammer_read()\n");
105 return -1;
106 }
107 }
108 return 0;
109}
110
111inline void timespec_normalize(struct timespec* ts, time_t sec, int64_t nsec)
112{
113 while(nsec > 1000000000LL) {
114 asm("" : "+rm"(nsec));
115 nsec -= 1000000000LL;
116 ++sec;
117 }
118 while(nsec < 0) {
119 asm("" : "+rm"(nsec));
120 nsec += 1000000000LL;
121 --sec;
122 }
123
124 ts->tv_sec = sec;
125 ts->tv_nsec = nsec;
126}
127
128inline struct timespec timespec_sub(struct timespec lhs, struct timespec rhs)
129{
130 struct timespec delta;
131 timespec_normalize(&delta, lhs.tv_sec - rhs.tv_sec, lhs.tv_nsec - rhs.tv_nsec);
132 return delta;
133}
134
135inline struct timespec timespec_add(struct timespec lhs, struct timespec rhs)
136{
137 struct timespec delta;
138 timespec_normalize(&delta, lhs.tv_sec + rhs.tv_sec, lhs.tv_nsec + rhs.tv_nsec);
139 return delta;
140}
141
142inline int64_t timespec_to_us(struct timespec ts)
143{
144 int64_t t;
145 t = ts.tv_sec * 1000000LL;
146 t += ts.tv_nsec / 1000LL;
147 return t;
148}
149
150/* hammers away at the first byte in each mmaped page and
151 times how long it took. */
152int do_data(int do_uncache, int64_t* time)
153{
154 int size;
155 int prot = PROT_READ | PROT_WRITE;
156 int flags = MAP_PRIVATE;
157
158 pbuf_t data;
159
160 struct sched_param fifo_params;
161
162 struct timespec start, end;
163 int64_t elapsed;
164 int trials = 1000;
165
166 printf("Running data access test.\n");
167
168 mlockall(MCL_CURRENT | MCL_FUTURE);
169
170 memset(&fifo_params, 0, sizeof(fifo_params));
171 fifo_params.sched_priority = sched_get_priority_max(SCHED_FIFO);
172
173 size = PAGE_SIZE*NR_PAGES;
174
175 printf("Allocating %d %s pages.\n", NR_PAGES, (do_uncache) ?
176 "uncacheable" : "cacheable");
177 if (do_uncache) {
178 int fd = open(UNCACHE_DEV, O_RDWR);
179 data = mmap(NULL, size, prot, flags, fd, 0);
180 close(fd);
181 }
182 else {
183 /* Accessed data will probably fit in L1, so this will go VERY fast.
184 Code should also have little-to-no pipeline stalls. */
185 flags |= MAP_ANONYMOUS;
186 data = mmap(NULL, size, prot, flags, -1, 0);
187 }
188 if (data == MAP_FAILED) {
189 printf("Failed to alloc data! "
190 "Are you running Litmus? "
191 "Is Litmus broken?\n");
192 return -1;
193 }
194 else {
195 printf("Data allocated at %p.\n", data);
196 }
197
198 printf("Beginning tests...\n");
199 if (sched_setscheduler(getpid(), SCHED_FIFO, &fifo_params)) {
200 printf("(Could not become SCHED_FIFO task.) Are you running as root?\n");
201 }
202
203 /* observations suggest that no warmup phase is needed. */
204 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start);
205 if (test(data, size, trials) != 0) {
206 printf("Test failed!\n");
207 munmap((char*)data, size);
208 return -1;
209 }
210 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end);
211 elapsed = timespec_to_us(timespec_sub(end, start));
212 printf("%s Time: %ldus\n", (do_uncache) ?
213 "Uncache" : "Cache", elapsed);
214
215 munmap((char*)data, size);
216
217 if(time)
218 *time = elapsed;
219
220 return 0;
221}
222
223/* compares runtime of cached vs. uncached */
224int do_data_compare()
225{
226 const double thresh = 1.3;
227 int ret = 0;
228 double ratio;
229 int64_t cache_time = 0, uncache_time = 0;
230
231 printf("Timing cached pages...\n");
232 ret = do_data(0, &cache_time);
233 if (ret != 0)
234 goto out;
235
236 printf("Timing uncached pages...\n");
237 ret = do_data(1, &uncache_time);
238 if (ret != 0)
239 goto out;
240
241 ratio = (double)uncache_time/(double)cache_time;
242 printf("Uncached/Cached Ratio: %f\n", ratio);
243
244 if (ratio < thresh) {
245 printf("Ratio is unexpectedly small (< %f)! "
246 " Uncache broken? Are you on kvm?\n", thresh);
247 ret = -1;
248 }
249
250out:
251 return ret;
252}
253
254/* tries to max out uncache allocations.
255 under normal conditions (non-mlock),
256 pages should spill into swap. uncache
257 pages are not locked in memory. */
258int do_max_alloc(void)
259{
260 int fd;
261 int good = 1;
262 int count = 0;
263 uint64_t mmap_size = PAGE_SIZE; /* start at one page per mmap */
264
265 /* half of default limit on ubuntu. (see /proc/sys/vm/max_map_count) */
266 int max_mmaps = 32765;
267 volatile char** maps = calloc(max_mmaps, sizeof(pbuf_t));
268
269 if (!maps) {
270 printf("failed to alloc pointers for pages\n");
271 return -1;
272 }
273
274 printf("Testing max amount of uncache data. System may get wonkie (OOM Killer)!\n");
275
276 fd = open(UNCACHE_DEV, O_RDWR);
277 do {
278 int i;
279 int nr_pages = mmap_size/PAGE_SIZE;
280 printf("Testing mmaps of %d pages.\n", nr_pages);
281
282 count = 0;
283 for (i = 0; (i < max_mmaps) && good; ++i) {
284 pbuf_t data = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_POPULATE, fd, 0);
285
286 if (data != MAP_FAILED) {
287 maps[i] = data;
288 ++count;
289 }
290 else {
291 perror(NULL);
292 good = 0;
293 }
294 }
295 for (i = 0; i < count; ++i) {
296 if (maps[i])
297 munmap((char*)(maps[i]), mmap_size);
298 }
299 memset(maps, 0, sizeof(maps[0])*max_mmaps);
300
301 mmap_size *= 2; /* let's do it again with bigger allocations */
302 }while(good);
303
304 free(maps);
305 close(fd);
306
307 printf("Maxed out allocs with %d mmaps of %lu pages in size.\n",
308 count, mmap_size/PAGE_SIZE);
309
310 return 0;
311}
312
313typedef enum
314{
315 UNCACHE,
316 CACHE,
317 COMPARE,
318 MAX_ALLOC
319} test_t;
320
321#define OPTSTR "ucxa"
322int main(int argc, char** argv)
323{
324 int ret;
325 test_t test = UNCACHE;
326 int opt;
327 PAGE_SIZE = sysconf(_SC_PAGE_SIZE);
328
329 while((opt = getopt(argc, argv, OPTSTR)) != -1) {
330 switch(opt) {
331 case 'c':
332 test = CACHE;
333 break;
334 case 'u':
335 test = UNCACHE;
336 break;
337 case 'x':
338 test = COMPARE;
339 break;
340 case 'a':
341 test = MAX_ALLOC;
342 break;
343 case ':':
344 printf("missing option\n");
345 exit(-1);
346 case '?':
347 default:
348 printf("bad argument\n");
349 exit(-1);
350 }
351 }
352
353
354 printf("Page Size: %d\n", PAGE_SIZE);
355
356 switch(test)
357 {
358 case CACHE:
359 ret = do_data(0, NULL);
360 break;
361 case UNCACHE:
362 ret = do_data(1, NULL);
363 break;
364 case COMPARE:
365 ret = do_data_compare();
366 break;
367 case MAX_ALLOC:
368 ret = do_max_alloc();
369 break;
370 default:
371 printf("invalid test\n");
372 ret = -1;
373 break;
374 }
375
376 if (ret != 0) {
377 printf("Test failed.\n");
378 }
379
380 return ret;
381}
diff --git a/gpu/aux_threads.c b/gpu/aux_threads.c
index 1e168c6..1711c40 100644
--- a/gpu/aux_threads.c
+++ b/gpu/aux_threads.c
@@ -1,4 +1,4 @@
1/* based_mt_task.c -- A basic multi-threaded real-time task skeleton. 1/* based_mt_task.c -- A basic multi-threaded real-time task skeleton.
2 * 2 *
3 * This (by itself useless) task demos how to setup a multi-threaded LITMUS^RT 3 * This (by itself useless) task demos how to setup a multi-threaded LITMUS^RT
4 * real-time task. Familiarity with the single threaded example (base_task.c) 4 * real-time task. Familiarity with the single threaded example (base_task.c)
@@ -48,7 +48,7 @@ struct thread_context {
48void* rt_thread(void *tcontext); 48void* rt_thread(void *tcontext);
49void* aux_thread(void *tcontext); 49void* aux_thread(void *tcontext);
50 50
51/* Declare the periodically invoked job. 51/* Declare the periodically invoked job.
52 * Returns 1 -> task should exit. 52 * Returns 1 -> task should exit.
53 * 0 -> task should continue. 53 * 0 -> task should continue.
54 */ 54 */
@@ -112,7 +112,7 @@ int main(int argc, char** argv)
112 112
113 ctx = calloc(NUM_AUX_THREADS, sizeof(struct thread_context)); 113 ctx = calloc(NUM_AUX_THREADS, sizeof(struct thread_context));
114 task = calloc(NUM_AUX_THREADS, sizeof(pthread_t)); 114 task = calloc(NUM_AUX_THREADS, sizeof(pthread_t));
115 115
116 //lt_t delay = ms2lt(1000); 116 //lt_t delay = ms2lt(1000);
117 117
118 /***** 118 /*****
@@ -199,9 +199,9 @@ int main(int argc, char** argv)
199 printf("child %d: %fs\n", i, time); 199 printf("child %d: %fs\n", i, time);
200 } 200 }
201 } 201 }
202
203 202
204 /***** 203
204 /*****
205 * 6) Clean up, maybe print results and stats, and exit. 205 * 6) Clean up, maybe print results and stats, and exit.
206 */ 206 */
207 return 0; 207 return 0;
@@ -271,7 +271,7 @@ void* rt_thread(void *tcontext)
271 271
272 wait_for_ts_release(); 272 wait_for_ts_release();
273 273
274 /* The task is now executing as a real-time task if the call didn't fail. 274 /* The task is now executing as a real-time task if the call didn't fail.
275 */ 275 */
276 276
277 277
@@ -304,7 +304,7 @@ void* rt_thread(void *tcontext)
304 return ctx; 304 return ctx;
305} 305}
306 306
307int job(void) 307int job(void)
308{ 308{
309 /* Do real-time calculation. */ 309 /* Do real-time calculation. */
310 310
diff --git a/gpu/dgl.c b/gpu/dgl.c
index dc68ead..42a3ae2 100644
--- a/gpu/dgl.c
+++ b/gpu/dgl.c
@@ -177,7 +177,7 @@ void* rt_thread(void* _ctx)
177 xfprintf(stdout, "ikglp od = %d\n", ctx->ikglp); 177 xfprintf(stdout, "ikglp od = %d\n", ctx->ikglp);
178 } 178 }
179 179
180 180
181 for (i = 0; i < NUM_SEMS; i++) { 181 for (i = 0; i < NUM_SEMS; i++) {
182 if(!USE_PRIOQ) { 182 if(!USE_PRIOQ) {
183 ctx->od[i] = open_fifo_sem(ctx->fd, i+1); 183 ctx->od[i] = open_fifo_sem(ctx->fd, i+1);
@@ -208,29 +208,29 @@ void* rt_thread(void* _ctx)
208 int last = (first + NEST_DEPTH - 1 >= NUM_SEMS) ? NUM_SEMS - 1 : first + NEST_DEPTH - 1; 208 int last = (first + NEST_DEPTH - 1 >= NUM_SEMS) ? NUM_SEMS - 1 : first + NEST_DEPTH - 1;
209 int dgl_size = last - first + 1; 209 int dgl_size = last - first + 1;
210 int dgl[dgl_size]; 210 int dgl[dgl_size];
211 211
212 // construct the DGL 212 // construct the DGL
213 for(i = first; i <= last; ++i) { 213 for(i = first; i <= last; ++i) {
214 dgl[i-first] = ctx->od[i]; 214 dgl[i-first] = ctx->od[i];
215 } 215 }
216 216
217 217
218 if(NUM_REPLICAS) { 218 if(NUM_REPLICAS) {
219 replica = litmus_lock(ctx->ikglp); 219 replica = litmus_lock(ctx->ikglp);
220 xfprintf(stdout, "[%d] got ikglp replica %d.\n", ctx->id, replica); 220 xfprintf(stdout, "[%d] got ikglp replica %d.\n", ctx->id, replica);
221 } 221 }
222 222
223 223
224 litmus_dgl_lock(dgl, dgl_size); 224 litmus_dgl_lock(dgl, dgl_size);
225 xfprintf(stdout, "[%d] acquired dgl.\n", ctx->id); 225 xfprintf(stdout, "[%d] acquired dgl.\n", ctx->id);
226 226
227 do_exit = job(ctx); 227 do_exit = job(ctx);
228 228
229 229
230 xfprintf(stdout, "[%d] unlocking dgl.\n", ctx->id); 230 xfprintf(stdout, "[%d] unlocking dgl.\n", ctx->id);
231 litmus_dgl_unlock(dgl, dgl_size); 231 litmus_dgl_unlock(dgl, dgl_size);
232 232
233 if(NUM_REPLICAS) { 233 if(NUM_REPLICAS) {
234 xfprintf(stdout, "[%d]: freeing ikglp replica %d.\n", ctx->id, replica); 234 xfprintf(stdout, "[%d]: freeing ikglp replica %d.\n", ctx->id, replica);
235 litmus_unlock(ctx->ikglp); 235 litmus_unlock(ctx->ikglp);
236 } 236 }
@@ -249,7 +249,7 @@ void* rt_thread(void* _ctx)
249 return NULL; 249 return NULL;
250} 250}
251 251
252void dirty_kb(int kb) 252void dirty_kb(int kb)
253{ 253{
254 int32_t one_kb[256]; 254 int32_t one_kb[256];
255 int32_t sum = 0; 255 int32_t sum = 0;
diff --git a/gpu/ikglptest.c b/gpu/ikglptest.c
index f802801..30623b7 100644
--- a/gpu/ikglptest.c
+++ b/gpu/ikglptest.c
@@ -172,7 +172,7 @@ struct avg_info feedback(int _a, int _b)
172 } 172 }
173 173
174 stdev = sqrtf(devsum/(NUM_SAMPLES-1)); 174 stdev = sqrtf(devsum/(NUM_SAMPLES-1));
175 175
176 ret.avg = avg; 176 ret.avg = avg;
177 ret.stdev = stdev; 177 ret.stdev = stdev;
178 178
@@ -189,10 +189,10 @@ struct avg_info feedback(int _a, int _b)
189int main(int argc, char** argv) 189int main(int argc, char** argv)
190{ 190{
191 int i; 191 int i;
192 struct thread_context* ctx; 192 struct thread_context* ctx = NULL;
193 struct thread_context* aux_ctx; 193 struct thread_context* aux_ctx = NULL;
194 pthread_t* task; 194 pthread_t* task = NULL;
195 pthread_t* aux_task; 195 pthread_t* aux_task = NULL;
196 int fd; 196 int fd;
197 197
198 int opt; 198 int opt;
@@ -291,7 +291,7 @@ int main(int argc, char** argv)
291 } 291 }
292 } 292 }
293 } 293 }
294 294
295 printf("Best:\ta = %d\tb = %d\t(b-a) = %d\tavg = %6.2f\tstdev = %6.2f\n", best_a, best_b, best_b - best_a, best.avg, best.stdev); 295 printf("Best:\ta = %d\tb = %d\t(b-a) = %d\tavg = %6.2f\tstdev = %6.2f\n", best_a, best_b, best_b - best_a, best.avg, best.stdev);
296 printf("2nd:\ta = %d\tb = %d\t(b-a) = %d\tavg = %6.2f\tstdev = %6.2f\n", second_best_a, second_best_b, second_best_b - second_best_a, second_best.avg, second_best.stdev); 296 printf("2nd:\ta = %d\tb = %d\t(b-a) = %d\tavg = %6.2f\tstdev = %6.2f\n", second_best_a, second_best_b, second_best_b - second_best_a, second_best.avg, second_best.stdev);
297 297
@@ -308,7 +308,7 @@ int main(int argc, char** argv)
308 } 308 }
309 309
310 printf("Aaron:\tavg = %6.2f\tstd = %6.2f\n", avg_accum/TRIALS, std_accum/TRIALS); 310 printf("Aaron:\tavg = %6.2f\tstd = %6.2f\n", avg_accum/TRIALS, std_accum/TRIALS);
311 311
312 312
313 313
314 314
@@ -385,7 +385,7 @@ int affinity_distance(struct thread_context* ctx, int a, int b)
385{ 385{
386 int i; 386 int i;
387 int dist; 387 int dist;
388 388
389 if(a >= 0 && b >= 0) { 389 if(a >= 0 && b >= 0) {
390 for(i = 0; i <= 3; ++i) { 390 for(i = 0; i <= 3; ++i) {
391 if(a>>i == b>>i) { 391 if(a>>i == b>>i) {
@@ -397,25 +397,25 @@ int affinity_distance(struct thread_context* ctx, int a, int b)
397 } 397 }
398 else { 398 else {
399 dist = 0; 399 dist = 0;
400 } 400 }
401 401
402out: 402out:
403 //printf("[%d]: distance: %d -> %d = %d\n", ctx->id, a, b, dist); 403 //printf("[%d]: distance: %d -> %d = %d\n", ctx->id, a, b, dist);
404 404
405 ++(ctx->mig_count[dist]); 405 ++(ctx->mig_count[dist]);
406 406
407 return dist; 407 return dist;
408 408
409// int groups[] = {2, 4, 8}; 409// int groups[] = {2, 4, 8};
410// int i; 410// int i;
411// 411//
412// if(a < 0 || b < 0) 412// if(a < 0 || b < 0)
413// return (sizeof(groups)/sizeof(groups[0])); // worst affinity 413// return (sizeof(groups)/sizeof(groups[0])); // worst affinity
414// 414//
415// // no migration 415// // no migration
416// if(a == b) 416// if(a == b)
417// return 0; 417// return 0;
418// 418//
419// for(i = 0; i < sizeof(groups)/sizeof(groups[0]); ++i) { 419// for(i = 0; i < sizeof(groups)/sizeof(groups[0]); ++i) {
420// if(a/groups[i] == b/groups[i]) 420// if(a/groups[i] == b/groups[i])
421// return (i+1); 421// return (i+1);
@@ -441,7 +441,7 @@ void* rt_thread(void* _ctx)
441{ 441{
442 int i; 442 int i;
443 int do_exit = 0; 443 int do_exit = 0;
444 int last_replica = -1; 444 int last_replica = -1;
445 445
446 struct thread_context *ctx = (struct thread_context*)_ctx; 446 struct thread_context *ctx = (struct thread_context*)_ctx;
447 447
@@ -472,13 +472,13 @@ void* rt_thread(void* _ctx)
472 IKGLP_OPTIMAL_FIFO_LEN : 472 IKGLP_OPTIMAL_FIFO_LEN :
473 IKGLP_UNLIMITED_FIFO_LEN, 473 IKGLP_UNLIMITED_FIFO_LEN,
474 ENABLE_AFFINITY 474 ENABLE_AFFINITY
475 ); 475 );
476 } 476 }
477 if(ctx->kexclu < 0) 477 if(ctx->kexclu < 0)
478 perror("open_kexclu_sem"); 478 perror("open_kexclu_sem");
479 else 479 else
480 printf("kexclu od = %d\n", ctx->kexclu); 480 printf("kexclu od = %d\n", ctx->kexclu);
481 481
482 for (i = 0; i < NUM_SEMS; ++i) { 482 for (i = 0; i < NUM_SEMS; ++i) {
483 if(!USE_PRIOQ) { 483 if(!USE_PRIOQ) {
484 ctx->od[i] = open_fifo_sem(ctx->fd, i + ctx->kexclu + 2); 484 ctx->od[i] = open_fifo_sem(ctx->fd, i + ctx->kexclu + 2);
@@ -508,21 +508,21 @@ void* rt_thread(void* _ctx)
508 int dgl_size = last - first + 1; 508 int dgl_size = last - first + 1;
509 int replica = -1; 509 int replica = -1;
510 int distance; 510 int distance;
511 511
512 int dgl[dgl_size]; 512 int dgl[dgl_size];
513 513
514 // construct the DGL 514 // construct the DGL
515 for(i = first; i <= last; ++i) { 515 for(i = first; i <= last; ++i) {
516 dgl[i-first] = ctx->od[i]; 516 dgl[i-first] = ctx->od[i];
517 } 517 }
518 518
519 replica = litmus_lock(ctx->kexclu); 519 replica = litmus_lock(ctx->kexclu);
520 520
521 //printf("[%d] got kexclu replica %d.\n", ctx->id, replica); 521 //printf("[%d] got kexclu replica %d.\n", ctx->id, replica);
522 //fflush(stdout); 522 //fflush(stdout);
523 523
524 distance = affinity_distance(ctx, replica, last_replica); 524 distance = affinity_distance(ctx, replica, last_replica);
525 525
526 if(USE_DYNAMIC_GROUP_LOCKS) { 526 if(USE_DYNAMIC_GROUP_LOCKS) {
527 litmus_dgl_lock(dgl, dgl_size); 527 litmus_dgl_lock(dgl, dgl_size);
528 } 528 }
@@ -531,24 +531,24 @@ void* rt_thread(void* _ctx)
531 litmus_lock(dgl[i]); 531 litmus_lock(dgl[i]);
532 } 532 }
533 } 533 }
534 534
535 //do_exit = nested_job(ctx, &count, &first, affinity_cost[distance]); 535 //do_exit = nested_job(ctx, &count, &first, affinity_cost[distance]);
536 do_exit = job(ctx, affinity_cost[distance]); 536 do_exit = job(ctx, affinity_cost[distance]);
537 537
538 if(USE_DYNAMIC_GROUP_LOCKS) { 538 if(USE_DYNAMIC_GROUP_LOCKS) {
539 litmus_dgl_unlock(dgl, dgl_size); 539 litmus_dgl_unlock(dgl, dgl_size);
540 } 540 }
541 else { 541 else {
542 for(i = dgl_size - 1; i >= 0; --i) { 542 for(i = dgl_size - 1; i >= 0; --i) {
543 litmus_unlock(dgl[i]); 543 litmus_unlock(dgl[i]);
544 } 544 }
545 } 545 }
546 546
547 //printf("[%d]: freeing kexclu replica %d.\n", ctx->id, replica); 547 //printf("[%d]: freeing kexclu replica %d.\n", ctx->id, replica);
548 //fflush(stdout); 548 //fflush(stdout);
549 549
550 litmus_unlock(ctx->kexclu); 550 litmus_unlock(ctx->kexclu);
551 551
552 last_replica = replica; 552 last_replica = replica;
553 553
554 if(SLEEP_BETWEEN_JOBS && !do_exit) { 554 if(SLEEP_BETWEEN_JOBS && !do_exit) {
@@ -567,7 +567,7 @@ void* rt_thread(void* _ctx)
567 */ 567 */
568 TH_CALL( task_mode(BACKGROUND_TASK) ); 568 TH_CALL( task_mode(BACKGROUND_TASK) );
569 569
570 for(i = 0; i < sizeof(ctx->mig_count)/sizeof(ctx->mig_count[0]); ++i) 570 for(i = 0; i < sizeof(ctx->mig_count)/sizeof(ctx->mig_count[0]); ++i)
571 { 571 {
572 printf("[%d]: mig_count[%d] = %d\n", ctx->id, i, ctx->mig_count[i]); 572 printf("[%d]: mig_count[%d] = %d\n", ctx->id, i, ctx->mig_count[i]);
573 } 573 }
@@ -608,15 +608,15 @@ void* rt_thread(void* _ctx)
608//} 608//}
609 609
610 610
611void dirty_kb(int kb) 611void dirty_kb(int kb)
612{ 612{
613 int32_t one_kb[256]; 613 int32_t one_kb[256];
614 int32_t sum = 0; 614 int32_t sum = 0;
615 int32_t i; 615 int32_t i;
616 616
617 if(!kb) 617 if(!kb)
618 return; 618 return;
619 619
620 for (i = 0; i < 256; i++) 620 for (i = 0; i < 256; i++)
621 sum += one_kb[i]; 621 sum += one_kb[i];
622 kb--; 622 kb--;
@@ -630,9 +630,9 @@ void dirty_kb(int kb)
630int job(struct thread_context* ctx, int runfactor) 630int job(struct thread_context* ctx, int runfactor)
631{ 631{
632 //struct timespec tosleep = {0, 100000}; // 0.1 ms 632 //struct timespec tosleep = {0, 100000}; // 0.1 ms
633 633
634 //printf("[%d]: runfactor = %d\n", ctx->id, runfactor); 634 //printf("[%d]: runfactor = %d\n", ctx->id, runfactor);
635 635
636 //dirty_kb(8 * runfactor); 636 //dirty_kb(8 * runfactor);
637 dirty_kb(1 * runfactor); 637 dirty_kb(1 * runfactor);
638 //nanosleep(&tosleep, NULL); 638 //nanosleep(&tosleep, NULL);
diff --git a/gpu/locktest.c b/gpu/locktest.c
index bc4fc54..6a1219a 100644
--- a/gpu/locktest.c
+++ b/gpu/locktest.c
@@ -177,7 +177,7 @@ void* rt_thread(void* _ctx)
177 return NULL; 177 return NULL;
178} 178}
179 179
180void dirty_kb(int kb) 180void dirty_kb(int kb)
181{ 181{
182 int32_t one_kb[256]; 182 int32_t one_kb[256];
183 int32_t sum = 0; 183 int32_t sum = 0;
diff --git a/gpu/nested.c b/gpu/nested.c
index 8c39152..edec46b 100644
--- a/gpu/nested.c
+++ b/gpu/nested.c
@@ -180,7 +180,7 @@ void* rt_thread(void* _ctx)
180 int first = (int)(NUM_SEMS * (rand_r(&(ctx->rand)) / (RAND_MAX + 1.0))); 180 int first = (int)(NUM_SEMS * (rand_r(&(ctx->rand)) / (RAND_MAX + 1.0)));
181 int count = NEST_DEPTH; 181 int count = NEST_DEPTH;
182 do_exit = nested_job(ctx, &count, &first); 182 do_exit = nested_job(ctx, &count, &first);
183 183
184 if(SLEEP_BETWEEN_JOBS && !do_exit) { 184 if(SLEEP_BETWEEN_JOBS && !do_exit) {
185 sleep_next_period(); 185 sleep_next_period();
186 } 186 }
@@ -226,7 +226,7 @@ int nested_job(struct thread_context* ctx, int *count, int *next)
226 226
227 227
228 228
229void dirty_kb(int kb) 229void dirty_kb(int kb)
230{ 230{
231 int32_t one_kb[256]; 231 int32_t one_kb[256];
232 int32_t sum = 0; 232 int32_t sum = 0;
diff --git a/gpu/rtspin_fake_cuda.cpp b/gpu/rtspin_fake_cuda.cpp
index 78e4f60..247a74c 100644
--- a/gpu/rtspin_fake_cuda.cpp
+++ b/gpu/rtspin_fake_cuda.cpp
@@ -119,7 +119,7 @@ char *h_state_data = 0;
119 mmap(NULL, s , \ 119 mmap(NULL, s , \
120 PROT_READ | PROT_WRITE, \ 120 PROT_READ | PROT_WRITE, \
121 MAP_PRIVATE | MAP_ANONYMOUS | MAP_LOCKED, \ 121 MAP_PRIVATE | MAP_ANONYMOUS | MAP_LOCKED, \
122 -1, 0) 122 -1, 0)
123#else 123#else
124#define c_malloc(s) malloc(s) 124#define c_malloc(s) malloc(s)
125#endif 125#endif
@@ -144,38 +144,38 @@ cudaError_t cudaGetLastError()
144//////////////////////////////////////////////////////////////////////// 144////////////////////////////////////////////////////////////////////////
145 145
146struct ce_lock_state 146struct ce_lock_state
147{ 147{
148 int locks[2]; 148 int locks[2];
149 size_t num_locks; 149 size_t num_locks;
150 size_t budget_remaining; 150 size_t budget_remaining;
151 bool locked; 151 bool locked;
152 152
153 ce_lock_state(int device_a, enum cudaMemcpyKind kind, size_t size, int device_b = -1) { 153 ce_lock_state(int device_a, enum cudaMemcpyKind kind, size_t size, int device_b = -1) {
154 num_locks = (device_a != -1) + (device_b != -1); 154 num_locks = (device_a != -1) + (device_b != -1);
155 155
156 if(device_a != -1) { 156 if(device_a != -1) {
157 locks[0] = (kind == cudaMemcpyHostToDevice) ? 157 locks[0] = (kind == cudaMemcpyHostToDevice) ?
158 CE_SEND_LOCKS[device_a] : CE_RECV_LOCKS[device_a]; 158 CE_SEND_LOCKS[device_a] : CE_RECV_LOCKS[device_a];
159 } 159 }
160 160
161 if(device_b != -1) { 161 if(device_b != -1) {
162 assert(kind == cudaMemcpyDeviceToDevice); 162 assert(kind == cudaMemcpyDeviceToDevice);
163 163
164 locks[1] = CE_RECV_LOCKS[device_b]; 164 locks[1] = CE_RECV_LOCKS[device_b];
165 165
166 if(locks[1] < locks[0]) { 166 if(locks[1] < locks[0]) {
167 int temp = locks[1]; 167 int temp = locks[1];
168 locks[1] = locks[0]; 168 locks[1] = locks[0];
169 locks[0] = temp; 169 locks[0] = temp;
170 } 170 }
171 } 171 }
172 172
173 if(!ENABLE_CHUNKING) 173 if(!ENABLE_CHUNKING)
174 budget_remaining = size; 174 budget_remaining = size;
175 else 175 else
176 budget_remaining = CHUNK_SIZE; 176 budget_remaining = CHUNK_SIZE;
177 } 177 }
178 178
179 void lock() { 179 void lock() {
180 if(USE_DYNAMIC_GROUP_LOCKS) { 180 if(USE_DYNAMIC_GROUP_LOCKS) {
181 litmus_dgl_lock(locks, num_locks); 181 litmus_dgl_lock(locks, num_locks);
@@ -189,7 +189,7 @@ struct ce_lock_state
189 } 189 }
190 locked = true; 190 locked = true;
191 } 191 }
192 192
193 void unlock() { 193 void unlock() {
194 if(USE_DYNAMIC_GROUP_LOCKS) { 194 if(USE_DYNAMIC_GROUP_LOCKS) {
195 litmus_dgl_unlock(locks, num_locks); 195 litmus_dgl_unlock(locks, num_locks);
@@ -204,15 +204,15 @@ struct ce_lock_state
204 } 204 }
205 locked = false; 205 locked = false;
206 } 206 }
207 207
208 void refresh() { 208 void refresh() {
209 budget_remaining = CHUNK_SIZE; 209 budget_remaining = CHUNK_SIZE;
210 } 210 }
211 211
212 bool budgetIsAvailable(size_t tosend) { 212 bool budgetIsAvailable(size_t tosend) {
213 return(tosend >= budget_remaining); 213 return(tosend >= budget_remaining);
214 } 214 }
215 215
216 void decreaseBudget(size_t spent) { 216 void decreaseBudget(size_t spent) {
217 budget_remaining -= spent; 217 budget_remaining -= spent;
218 } 218 }
@@ -225,53 +225,53 @@ cudaError_t __chunkMemcpy(void* a_dst, const void* a_src, size_t count,
225{ 225{
226 cudaError_t ret = cudaSuccess; 226 cudaError_t ret = cudaSuccess;
227 int remaining = count; 227 int remaining = count;
228 228
229 char* dst = (char*)a_dst; 229 char* dst = (char*)a_dst;
230 const char* src = (const char*)a_src; 230 const char* src = (const char*)a_src;
231 231
232 // disable chunking, if needed, by setting chunk_size equal to the 232 // disable chunking, if needed, by setting chunk_size equal to the
233 // amount of data to be copied. 233 // amount of data to be copied.
234 int chunk_size = (ENABLE_CHUNKING) ? CHUNK_SIZE : count; 234 int chunk_size = (ENABLE_CHUNKING) ? CHUNK_SIZE : count;
235 int i = 0; 235 int i = 0;
236 236
237 while(remaining != 0) 237 while(remaining != 0)
238 { 238 {
239 int bytesToCopy = std::min(remaining, chunk_size); 239 int bytesToCopy = std::min(remaining, chunk_size);
240 240
241 if(state && state->budgetIsAvailable(bytesToCopy) && state->locked) { 241 if(state && state->budgetIsAvailable(bytesToCopy) && state->locked) {
242 //cutilSafeCall( cudaStreamSynchronize(streams[CUR_DEVICE]) ); 242 //cutilSafeCall( cudaStreamSynchronize(streams[CUR_DEVICE]) );
243 ret = cudaGetLastError(); 243 ret = cudaGetLastError();
244 244
245 if(ret != cudaSuccess) 245 if(ret != cudaSuccess)
246 { 246 {
247 break; 247 break;
248 } 248 }
249 249
250 state->unlock(); 250 state->unlock();
251 state->refresh(); // replentish. 251 state->refresh(); // replentish.
252 // we can only run out of 252 // we can only run out of
253 // budget if chunking is enabled. 253 // budget if chunking is enabled.
254 // we presume that init budget would 254 // we presume that init budget would
255 // be set to cover entire memcpy 255 // be set to cover entire memcpy
256 // if chunking were disabled. 256 // if chunking were disabled.
257 } 257 }
258 258
259 if(state && !state->locked) { 259 if(state && !state->locked) {
260 state->lock(); 260 state->lock();
261 } 261 }
262 262
263 //ret = cudaMemcpy(dst+i*chunk_size, src+i*chunk_size, bytesToCopy, kind); 263 //ret = cudaMemcpy(dst+i*chunk_size, src+i*chunk_size, bytesToCopy, kind);
264 //cudaMemcpyAsync(dst+i*chunk_size, src+i*chunk_size, bytesToCopy, kind, streams[CUR_DEVICE]); 264 //cudaMemcpyAsync(dst+i*chunk_size, src+i*chunk_size, bytesToCopy, kind, streams[CUR_DEVICE]);
265 265
266 if(state) { 266 if(state) {
267 state->decreaseBudget(bytesToCopy); 267 state->decreaseBudget(bytesToCopy);
268 } 268 }
269 269
270// if(ret != cudaSuccess) 270// if(ret != cudaSuccess)
271// { 271// {
272// break; 272// break;
273// } 273// }
274 274
275 ++i; 275 ++i;
276 remaining -= bytesToCopy; 276 remaining -= bytesToCopy;
277 } 277 }
@@ -281,7 +281,7 @@ cudaError_t __chunkMemcpy(void* a_dst, const void* a_src, size_t count,
281cudaError_t chunkMemcpy(void* a_dst, const void* a_src, size_t count, 281cudaError_t chunkMemcpy(void* a_dst, const void* a_src, size_t count,
282 enum cudaMemcpyKind kind, 282 enum cudaMemcpyKind kind,
283 int device_a = -1, // device_a == -1 disables locking 283 int device_a = -1, // device_a == -1 disables locking
284 bool do_locking = true, 284 bool do_locking = true,
285 int device_b = -1) 285 int device_b = -1)
286{ 286{
287 cudaError_t ret; 287 cudaError_t ret;
@@ -317,7 +317,7 @@ inline uint64_t timespec_to_ns(const struct timespec& t)
317inline struct timespec ns_to_timespec(const uint64_t& ns) 317inline struct timespec ns_to_timespec(const uint64_t& ns)
318{ 318{
319 struct timespec temp = {ns/1e9, ns - ns/1e9}; 319 struct timespec temp = {ns/1e9, ns - ns/1e9};
320 return(temp); 320 return(temp);
321} 321}
322 322
323inline uint64_t clock_gettime_ns(clockid_t clk_id) 323inline uint64_t clock_gettime_ns(clockid_t clk_id)
@@ -366,9 +366,9 @@ static void allocate_locks()
366{ 366{
367 // allocate k-FMLP lock 367 // allocate k-FMLP lock
368 int fd = open("semaphores", O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR); 368 int fd = open("semaphores", O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR);
369 369
370 int base_name = GPU_PARTITION * 1000; 370 int base_name = GPU_PARTITION * 1000;
371 371
372 if(USE_KFMLP) { 372 if(USE_KFMLP) {
373 KEXCLU_LOCK = open_kfmlp_gpu_sem(fd, 373 KEXCLU_LOCK = open_kfmlp_gpu_sem(fd,
374 base_name, /* name */ 374 base_name, /* name */
@@ -397,7 +397,7 @@ static void allocate_locks()
397// NUM_SIMULT_USERS, 397// NUM_SIMULT_USERS,
398// ENABLE_AFFINITY, 398// ENABLE_AFFINITY,
399// RELAX_FIFO_MAX_LEN 399// RELAX_FIFO_MAX_LEN
400// ); 400// );
401 } 401 }
402 if(KEXCLU_LOCK < 0) 402 if(KEXCLU_LOCK < 0)
403 perror("open_kexclu_sem"); 403 perror("open_kexclu_sem");
@@ -406,31 +406,31 @@ static void allocate_locks()
406 { 406 {
407 open_sem_t opensem = (!USE_PRIOQ) ? open_fifo_sem : open_prioq_sem; 407 open_sem_t opensem = (!USE_PRIOQ) ? open_fifo_sem : open_prioq_sem;
408 const char* opensem_label = (!USE_PRIOQ) ? "open_fifo_sem" : "open_prioq_sem"; 408 const char* opensem_label = (!USE_PRIOQ) ? "open_fifo_sem" : "open_prioq_sem";
409 409
410 // allocate the engine locks. 410 // allocate the engine locks.
411 for (int i = 0; i < MAX_GPUS; ++i) 411 for (int i = 0; i < MAX_GPUS; ++i)
412 { 412 {
413 EE_LOCKS[i] = opensem(fd, (i+1)*10 + base_name); 413 EE_LOCKS[i] = opensem(fd, (i+1)*10 + base_name);
414 if(EE_LOCKS[i] < 0) 414 if(EE_LOCKS[i] < 0)
415 perror(opensem_label); 415 perror(opensem_label);
416 416
417 CE_SEND_LOCKS[i] = opensem(fd, (i+1)*10 + base_name + 1); 417 CE_SEND_LOCKS[i] = opensem(fd, (i+1)*10 + base_name + 1);
418 if(CE_SEND_LOCKS[i] < 0) 418 if(CE_SEND_LOCKS[i] < 0)
419 perror(opensem_label); 419 perror(opensem_label);
420 420
421 if(NUM_SIMULT_USERS == 3) 421 if(NUM_SIMULT_USERS == 3)
422 { 422 {
423 // allocate a separate lock for the second copy engine 423 // allocate a separate lock for the second copy engine
424 CE_RECV_LOCKS[i] = opensem(fd, (i+1)*10 + base_name + 2); 424 CE_RECV_LOCKS[i] = opensem(fd, (i+1)*10 + base_name + 2);
425 if(CE_RECV_LOCKS[i] < 0) 425 if(CE_RECV_LOCKS[i] < 0)
426 perror(opensem_label); 426 perror(opensem_label);
427 } 427 }
428 else 428 else
429 { 429 {
430 // share a single lock for the single copy engine 430 // share a single lock for the single copy engine
431 CE_RECV_LOCKS[i] = CE_SEND_LOCKS[i]; 431 CE_RECV_LOCKS[i] = CE_SEND_LOCKS[i];
432 } 432 }
433 } 433 }
434 } 434 }
435} 435}
436 436
@@ -449,22 +449,22 @@ static void allocate_host_memory()
449// h_send_data = (char *)c_malloc(send_alloc_bytes); 449// h_send_data = (char *)c_malloc(send_alloc_bytes);
450// memset(h_send_data, 0x55, send_alloc_bytes); // write some random value 450// memset(h_send_data, 0x55, send_alloc_bytes); // write some random value
451// // this will open a connection to GPU 0 if there is no active context, so 451// // this will open a connection to GPU 0 if there is no active context, so
452// // expect long stalls. LAME. 452// // expect long stalls. LAME.
453// cutilSafeCall( cudaHostRegister(h_send_data, send_alloc_bytes, cudaHostRegisterPortable) ); 453// cutilSafeCall( cudaHostRegister(h_send_data, send_alloc_bytes, cudaHostRegisterPortable) );
454// } 454// }
455// 455//
456// if(recv_alloc_bytes > 0) 456// if(recv_alloc_bytes > 0)
457// { 457// {
458// h_recv_data = (char *)c_malloc(recv_alloc_bytes); 458// h_recv_data = (char *)c_malloc(recv_alloc_bytes);
459// memset(h_recv_data, 0xAA, recv_alloc_bytes); 459// memset(h_recv_data, 0xAA, recv_alloc_bytes);
460// cutilSafeCall( cudaHostRegister(h_recv_data, recv_alloc_bytes, cudaHostRegisterPortable) ); 460// cutilSafeCall( cudaHostRegister(h_recv_data, recv_alloc_bytes, cudaHostRegisterPortable) );
461// } 461// }
462// 462//
463// if(state_alloc_bytes > 0) 463// if(state_alloc_bytes > 0)
464// { 464// {
465// h_state_data = (char *)c_malloc(state_alloc_bytes); 465// h_state_data = (char *)c_malloc(state_alloc_bytes);
466// memset(h_state_data, 0xCC, state_alloc_bytes); // write some random value 466// memset(h_state_data, 0xCC, state_alloc_bytes); // write some random value
467// cutilSafeCall( cudaHostRegister(h_state_data, state_alloc_bytes, cudaHostRegisterPortable) ); 467// cutilSafeCall( cudaHostRegister(h_state_data, state_alloc_bytes, cudaHostRegisterPortable) );
468// } 468// }
469 469
470 printf("Host memory allocated.\n"); 470 printf("Host memory allocated.\n");
@@ -477,28 +477,28 @@ static void allocate_device_memory()
477// for(int i = 0; i < GPU_PARTITION_SIZE; ++i) 477// for(int i = 0; i < GPU_PARTITION_SIZE; ++i)
478// { 478// {
479// int which_device = GPU_PARTITION*GPU_PARTITION_SIZE + i; 479// int which_device = GPU_PARTITION*GPU_PARTITION_SIZE + i;
480// 480//
481// if(ENABLE_WAIT) gpu_mgmt_mutexes[which_device].lock(); 481// if(ENABLE_WAIT) gpu_mgmt_mutexes[which_device].lock();
482// 482//
483// cutilSafeCall( cudaSetDevice(which_device) ); 483// cutilSafeCall( cudaSetDevice(which_device) );
484// cutilSafeCall( cudaDeviceSetLimit(cudaLimitPrintfFifoSize, 0) ); 484// cutilSafeCall( cudaDeviceSetLimit(cudaLimitPrintfFifoSize, 0) );
485// cutilSafeCall( cudaDeviceSetLimit(cudaLimitMallocHeapSize, 0) ); 485// cutilSafeCall( cudaDeviceSetLimit(cudaLimitMallocHeapSize, 0) );
486// 486//
487// cutilSafeCall( cudaStreamCreate(&streams[which_device]) ); 487// cutilSafeCall( cudaStreamCreate(&streams[which_device]) );
488// 488//
489// /* pre-allocate memory, pray there's enough to go around */ 489// /* pre-allocate memory, pray there's enough to go around */
490// if(SEND_SIZE > 0) { 490// if(SEND_SIZE > 0) {
491// cutilSafeCall( cudaMalloc((void**)&d_send_data[which_device], SEND_SIZE) ); 491// cutilSafeCall( cudaMalloc((void**)&d_send_data[which_device], SEND_SIZE) );
492// } 492// }
493// if(RECV_SIZE > 0) { 493// if(RECV_SIZE > 0) {
494// cutilSafeCall( cudaMalloc((void**)&h_recv_data[which_device], RECV_SIZE) ); 494// cutilSafeCall( cudaMalloc((void**)&h_recv_data[which_device], RECV_SIZE) );
495// } 495// }
496// if(STATE_SIZE > 0) { 496// if(STATE_SIZE > 0) {
497// cutilSafeCall( cudaMalloc((void**)&h_state_data[which_device], STATE_SIZE) ); 497// cutilSafeCall( cudaMalloc((void**)&h_state_data[which_device], STATE_SIZE) );
498// } 498// }
499// 499//
500// if(ENABLE_WAIT) gpu_mgmt_mutexes[which_device].unlock(); 500// if(ENABLE_WAIT) gpu_mgmt_mutexes[which_device].unlock();
501// } 501// }
502 printf("Device memory allocated.\n"); 502 printf("Device memory allocated.\n");
503} 503}
504 504
@@ -508,39 +508,39 @@ static void configure_gpus()
508 508
509// // SUSPEND WHEN BLOCKED!! 509// // SUSPEND WHEN BLOCKED!!
510// cutilSafeCall( cudaSetDeviceFlags(cudaDeviceScheduleBlockingSync) ); 510// cutilSafeCall( cudaSetDeviceFlags(cudaDeviceScheduleBlockingSync) );
511// 511//
512// // establish a connection to each GPU. 512// // establish a connection to each GPU.
513// for(int i = 0; i < GPU_PARTITION_SIZE; ++i) 513// for(int i = 0; i < GPU_PARTITION_SIZE; ++i)
514// { 514// {
515// int which_device = GPU_PARTITION*GPU_PARTITION_SIZE + i; 515// int which_device = GPU_PARTITION*GPU_PARTITION_SIZE + i;
516// 516//
517// if(ENABLE_WAIT) gpu_mgmt_mutexes[which_device].lock(); 517// if(ENABLE_WAIT) gpu_mgmt_mutexes[which_device].lock();
518// 518//
519// cutilSafeCall( cudaSetDevice(which_device) ); 519// cutilSafeCall( cudaSetDevice(which_device) );
520// cutilSafeCall( cudaDeviceSetLimit(cudaLimitPrintfFifoSize, 0) ); 520// cutilSafeCall( cudaDeviceSetLimit(cudaLimitPrintfFifoSize, 0) );
521// cutilSafeCall( cudaDeviceSetLimit(cudaLimitMallocHeapSize, 0) ); 521// cutilSafeCall( cudaDeviceSetLimit(cudaLimitMallocHeapSize, 0) );
522// 522//
523// cutilSafeCall( cudaStreamCreate(&streams[which_device]) ); 523// cutilSafeCall( cudaStreamCreate(&streams[which_device]) );
524// 524//
525// // enable P2P migrations. 525// // enable P2P migrations.
526// // we assume all GPUs are on the same I/O hub. 526// // we assume all GPUs are on the same I/O hub.
527// for(int j = 0; j < GPU_PARTITION_SIZE; ++j) 527// for(int j = 0; j < GPU_PARTITION_SIZE; ++j)
528// { 528// {
529// int other_device = GPU_PARTITION*GPU_PARTITION_SIZE + j; 529// int other_device = GPU_PARTITION*GPU_PARTITION_SIZE + j;
530// 530//
531// if(which_device != other_device) 531// if(which_device != other_device)
532// { 532// {
533// cutilSafeCall( cudaDeviceEnablePeerAccess(other_device, 0) ); 533// cutilSafeCall( cudaDeviceEnablePeerAccess(other_device, 0) );
534// } 534// }
535// } 535// }
536// 536//
537// if(i == 0) 537// if(i == 0)
538// { 538// {
539// struct cudaDeviceProp pi; 539// struct cudaDeviceProp pi;
540// cudaGetDeviceProperties(&pi, i); 540// cudaGetDeviceProperties(&pi, i);
541// gpuCyclesPerSecond = pi.clockRate * 1000; /* khz -> hz */ 541// gpuCyclesPerSecond = pi.clockRate * 1000; /* khz -> hz */
542// } 542// }
543// 543//
544// if(ENABLE_WAIT) gpu_mgmt_mutexes[which_device].unlock(); 544// if(ENABLE_WAIT) gpu_mgmt_mutexes[which_device].unlock();
545// } 545// }
546 546
@@ -580,7 +580,7 @@ static void catchExit(void)
580 for(int i = 0; i < GPU_PARTITION_SIZE; ++i) 580 for(int i = 0; i < GPU_PARTITION_SIZE; ++i)
581 { 581 {
582 int which_device = GPU_PARTITION*GPU_PARTITION_SIZE + i; 582 int which_device = GPU_PARTITION*GPU_PARTITION_SIZE + i;
583 583
584 litmus_unlock(EE_LOCKS[which_device]); 584 litmus_unlock(EE_LOCKS[which_device]);
585 litmus_unlock(CE_SEND_LOCKS[which_device]); 585 litmus_unlock(CE_SEND_LOCKS[which_device]);
586 if(NUM_SIMULT_USERS == 2) { 586 if(NUM_SIMULT_USERS == 2) {
@@ -588,11 +588,11 @@ static void catchExit(void)
588 } 588 }
589 } 589 }
590 } 590 }
591 591
592 if(CUR_DEVICE >= 0) { 592 if(CUR_DEVICE >= 0) {
593 unregister_nv_device(CUR_DEVICE); 593 unregister_nv_device(CUR_DEVICE);
594 } 594 }
595 595
596 litmus_unlock(KEXCLU_LOCK); 596 litmus_unlock(KEXCLU_LOCK);
597 } 597 }
598} 598}
@@ -604,18 +604,18 @@ static void migrateToGPU(int destination)
604 if(MIGRATE_VIA_SYSMEM) 604 if(MIGRATE_VIA_SYSMEM)
605 { 605 {
606 chunkMemcpy(h_state_data, d_state_data[LAST_DEVICE], STATE_SIZE, 606 chunkMemcpy(h_state_data, d_state_data[LAST_DEVICE], STATE_SIZE,
607 cudaMemcpyDeviceToHost, LAST_DEVICE, useEngineLocks()); 607 cudaMemcpyDeviceToHost, LAST_DEVICE, useEngineLocks());
608 } 608 }
609 } 609 }
610 610
611// cutilSafeCall( cudaSetDevice(destination) ); 611// cutilSafeCall( cudaSetDevice(destination) );
612 612
613 if(!BROADCAST_STATE && STATE_SIZE > 0) 613 if(!BROADCAST_STATE && STATE_SIZE > 0)
614 { 614 {
615 if(MIGRATE_VIA_SYSMEM) 615 if(MIGRATE_VIA_SYSMEM)
616 { 616 {
617 chunkMemcpy(d_state_data[CUR_DEVICE], h_state_data, STATE_SIZE, 617 chunkMemcpy(d_state_data[CUR_DEVICE], h_state_data, STATE_SIZE,
618 cudaMemcpyHostToDevice, CUR_DEVICE, useEngineLocks()); 618 cudaMemcpyHostToDevice, CUR_DEVICE, useEngineLocks());
619 } 619 }
620 else 620 else
621 { 621 {
@@ -633,15 +633,15 @@ static void migrateToGPU(int destination)
633static void broadcastState(int from) 633static void broadcastState(int from)
634{ 634{
635 if(STATE_SIZE > 0) 635 if(STATE_SIZE > 0)
636 { 636 {
637 assert(CUR_DEVICE == from); 637 assert(CUR_DEVICE == from);
638 638
639 if(MIGRATE_VIA_SYSMEM) 639 if(MIGRATE_VIA_SYSMEM)
640 { 640 {
641 chunkMemcpy(h_state_data, d_state_data[from], STATE_SIZE, 641 chunkMemcpy(h_state_data, d_state_data[from], STATE_SIZE,
642 cudaMemcpyDeviceToHost, from, useEngineLocks()); 642 cudaMemcpyDeviceToHost, from, useEngineLocks());
643 } 643 }
644 644
645 for(int i = 0; i < GPU_PARTITION_SIZE; ++i) 645 for(int i = 0; i < GPU_PARTITION_SIZE; ++i)
646 { 646 {
647 int which_device = GPU_PARTITION*GPU_PARTITION_SIZE + i; 647 int which_device = GPU_PARTITION*GPU_PARTITION_SIZE + i;
@@ -652,7 +652,7 @@ static void broadcastState(int from)
652// cutilSafeCall( cudaSetDevice(which_device) ); 652// cutilSafeCall( cudaSetDevice(which_device) );
653 CUR_DEVICE = which_device; // temporary 653 CUR_DEVICE = which_device; // temporary
654 chunkMemcpy(d_state_data[which_device], h_state_data, STATE_SIZE, 654 chunkMemcpy(d_state_data[which_device], h_state_data, STATE_SIZE,
655 cudaMemcpyHostToDevice, which_device, useEngineLocks()); 655 cudaMemcpyHostToDevice, which_device, useEngineLocks());
656 } 656 }
657 else 657 else
658 { 658 {
@@ -662,11 +662,11 @@ static void broadcastState(int from)
662 cudaMemcpyDeviceToDevice, 662 cudaMemcpyDeviceToDevice,
663 from, 663 from,
664 useEngineLocks(), 664 useEngineLocks(),
665 which_device); 665 which_device);
666 } 666 }
667 } 667 }
668 } 668 }
669 669
670 if(MIGRATE_VIA_SYSMEM && CUR_DEVICE != from) 670 if(MIGRATE_VIA_SYSMEM && CUR_DEVICE != from)
671 { 671 {
672// cutilSafeCall( cudaSetDevice(from) ); 672// cutilSafeCall( cudaSetDevice(from) );
@@ -714,18 +714,18 @@ static void gpu_loop_for(double gpu_sec_time, double emergency_exit)
714 } 714 }
715 715
716 if(useEngineLocks()) litmus_lock(EE_LOCKS[CUR_DEVICE]); 716 if(useEngineLocks()) litmus_lock(EE_LOCKS[CUR_DEVICE]);
717 717
718// docudaspin <<<numblocks,blocksz, 0, streams[CUR_DEVICE]>>> (numcycles); 718// docudaspin <<<numblocks,blocksz, 0, streams[CUR_DEVICE]>>> (numcycles);
719// cutilSafeCall( cudaStreamSynchronize(streams[CUR_DEVICE]) ); 719// cutilSafeCall( cudaStreamSynchronize(streams[CUR_DEVICE]) );
720 720
721 if(useEngineLocks()) litmus_unlock(EE_LOCKS[CUR_DEVICE]); 721 if(useEngineLocks()) litmus_unlock(EE_LOCKS[CUR_DEVICE]);
722 722
723 if(RECV_SIZE > 0) 723 if(RECV_SIZE > 0)
724 { 724 {
725 chunkMemcpy(h_recv_data, d_recv_data[CUR_DEVICE], RECV_SIZE, 725 chunkMemcpy(h_recv_data, d_recv_data[CUR_DEVICE], RECV_SIZE,
726 cudaMemcpyDeviceToHost, CUR_DEVICE, useEngineLocks()); 726 cudaMemcpyDeviceToHost, CUR_DEVICE, useEngineLocks());
727 } 727 }
728 728
729 if(BROADCAST_STATE) 729 if(BROADCAST_STATE)
730 { 730 {
731 broadcastState(CUR_DEVICE); 731 broadcastState(CUR_DEVICE);
@@ -802,7 +802,7 @@ int main(int argc, char** argv)
802 int num_tasks = 0; 802 int num_tasks = 0;
803 803
804 double gpu_sec_ms = 0; 804 double gpu_sec_ms = 0;
805 805
806 while ((opt = getopt(argc, argv, OPTSTR)) != -1) { 806 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
807// printf("opt = %c optarg = %s\n", opt, optarg); 807// printf("opt = %c optarg = %s\n", opt, optarg);
808 switch (opt) { 808 switch (opt) {
@@ -858,7 +858,7 @@ int main(int argc, char** argv)
858 break; 858 break;
859 case 'r': 859 case 'r':
860 RELAX_FIFO_MAX_LEN = true; 860 RELAX_FIFO_MAX_LEN = true;
861 break; 861 break;
862 case 'L': 862 case 'L':
863 USE_KFMLP = true; 863 USE_KFMLP = true;
864 break; 864 break;
@@ -949,13 +949,13 @@ int main(int argc, char** argv)
949 { 949 {
950 printf("%d creating release shared memory\n", getpid()); 950 printf("%d creating release shared memory\n", getpid());
951 shared_memory_object::remove("release_barrier_memory"); 951 shared_memory_object::remove("release_barrier_memory");
952 release_segment_ptr = new managed_shared_memory(create_only, "release_barrier_memory", 4*1024); 952 release_segment_ptr = new managed_shared_memory(create_only, "release_barrier_memory", 4*1024);
953 953
954 printf("%d creating release barrier for %d users\n", getpid(), num_tasks); 954 printf("%d creating release barrier for %d users\n", getpid(), num_tasks);
955 release_barrier = release_segment_ptr->construct<barrier>("barrier release_barrier")(num_tasks); 955 release_barrier = release_segment_ptr->construct<barrier>("barrier release_barrier")(num_tasks);
956 956
957 init_release_time = release_segment_ptr->construct<uint64_t>("uint64_t instance")(); 957 init_release_time = release_segment_ptr->construct<uint64_t>("uint64_t instance")();
958 *init_release_time = 0; 958 *init_release_time = 0;
959 } 959 }
960 else 960 else
961 { 961 {
@@ -972,13 +972,13 @@ int main(int argc, char** argv)
972 sleep(1); 972 sleep(1);
973 } 973 }
974 }while(segment_ptr == NULL); 974 }while(segment_ptr == NULL);
975 975
976 release_barrier = segment_ptr->find<barrier>("barrier release_barrier").first; 976 release_barrier = segment_ptr->find<barrier>("barrier release_barrier").first;
977 init_release_time = segment_ptr->find<uint64_t>("uint64_t instance").first; 977 init_release_time = segment_ptr->find<uint64_t>("uint64_t instance").first;
978 } 978 }
979 } 979 }
980 980
981 981
982 if(GPU_TASK) 982 if(GPU_TASK)
983 { 983 {
984 if(ENABLE_WAIT) 984 if(ENABLE_WAIT)
@@ -1019,7 +1019,7 @@ int main(int argc, char** argv)
1019 SEND_SIZE *= scale; 1019 SEND_SIZE *= scale;
1020 RECV_SIZE *= scale; 1020 RECV_SIZE *= scale;
1021 STATE_SIZE *= scale; 1021 STATE_SIZE *= scale;
1022 1022
1023 init_cuda(); 1023 init_cuda();
1024 } 1024 }
1025 1025
@@ -1036,16 +1036,16 @@ int main(int argc, char** argv)
1036 if (ret != 0) 1036 if (ret != 0)
1037 bail_out("could not become RT task"); 1037 bail_out("could not become RT task");
1038 1038
1039 1039
1040 1040
1041 uint64_t jobCount = 0; 1041 uint64_t jobCount = 0;
1042 blitz::Array<uint64_t, 1> responseTimeLog(num_jobs+1); 1042 blitz::Array<uint64_t, 1> responseTimeLog(num_jobs+1);
1043 1043
1044 struct timespec spec; 1044 struct timespec spec;
1045 uint64_t release; 1045 uint64_t release;
1046 uint64_t finish; 1046 uint64_t finish;
1047 1047
1048 1048
1049 if (ENABLE_WAIT) { 1049 if (ENABLE_WAIT) {
1050 printf("Waiting for release.\n"); 1050 printf("Waiting for release.\n");
1051 ret = wait_for_ts_release(); 1051 ret = wait_for_ts_release();
@@ -1056,14 +1056,14 @@ int main(int argc, char** argv)
1056 { 1056 {
1057 sleep_next_period(); 1057 sleep_next_period();
1058 } 1058 }
1059 1059
1060 clock_gettime(CLOCK_MONOTONIC, &spec); 1060 clock_gettime(CLOCK_MONOTONIC, &spec);
1061 release = timespec_to_ns(spec); 1061 release = timespec_to_ns(spec);
1062 if (!__sync_bool_compare_and_swap(init_release_time, 0, release)) 1062 if (!__sync_bool_compare_and_swap(init_release_time, 0, release))
1063 { 1063 {
1064 release = *init_release_time; 1064 release = *init_release_time;
1065 } 1065 }
1066 1066
1067 releaseTime = wctime(); 1067 releaseTime = wctime();
1068 double failsafeEnd = releaseTime + duration; 1068 double failsafeEnd = releaseTime + duration;
1069 1069
@@ -1087,7 +1087,7 @@ int main(int argc, char** argv)
1087 clock_gettime(CLOCK_MONOTONIC, &spec); 1087 clock_gettime(CLOCK_MONOTONIC, &spec);
1088 finish = timespec_to_ns(spec); 1088 finish = timespec_to_ns(spec);
1089 1089
1090 responseTimeLog(min(num_jobs,jobCount++)) = finish - release; 1090 responseTimeLog(min(num_jobs,jobCount++)) = finish - release;
1091 1091
1092 // this is an estimated upper-bound on release time. it may be off by several microseconds. 1092 // this is an estimated upper-bound on release time. it may be off by several microseconds.
1093#ifdef RESET_RELEASE_ON_MISS 1093#ifdef RESET_RELEASE_ON_MISS
@@ -1097,11 +1097,11 @@ int main(int argc, char** argv)
1097#else 1097#else
1098 release = release + period; // allow things to get progressively later. 1098 release = release + period; // allow things to get progressively later.
1099#endif 1099#endif
1100 1100
1101 sleep_next_period(); 1101 sleep_next_period();
1102 clock_gettime(CLOCK_MONOTONIC, &spec); 1102 clock_gettime(CLOCK_MONOTONIC, &spec);
1103 release = min(timespec_to_ns(spec), release); 1103 release = min(timespec_to_ns(spec), release);
1104 1104
1105 } while(keepGoing); 1105 } while(keepGoing);
1106 } 1106 }
1107 1107
@@ -1147,13 +1147,13 @@ int main(int argc, char** argv)
1147 } 1147 }
1148 } 1148 }
1149 1149
1150 1150
1151 if (ENABLE_WAIT) 1151 if (ENABLE_WAIT)
1152 { 1152 {
1153 printf("%d waiting at exit barrier\n", getpid()); 1153 printf("%d waiting at exit barrier\n", getpid());
1154 release_barrier->wait(); 1154 release_barrier->wait();
1155 } 1155 }
1156 1156
1157 1157
1158 char gpu_using_str[] = "GPU\n"; 1158 char gpu_using_str[] = "GPU\n";
1159 char cpu_only_str[] = "CPU\n"; 1159 char cpu_only_str[] = "CPU\n";
@@ -1166,7 +1166,7 @@ int main(int argc, char** argv)
1166 // average 1166 // average
1167 blitz::mean(USED(responseTimeLog)), 1167 blitz::mean(USED(responseTimeLog)),
1168 // average pct of period 1168 // average pct of period
1169 100.0*(blitz::mean(USED(responseTimeLog))/period), 1169 100.0*(blitz::mean(USED(responseTimeLog))/period),
1170 // min 1170 // min
1171 blitz::min(USED(responseTimeLog)), 1171 blitz::min(USED(responseTimeLog)),
1172 // max 1172 // max
@@ -1182,6 +1182,6 @@ int main(int argc, char** argv)
1182 // flag gpu-using tasks 1182 // flag gpu-using tasks
1183 ((GPU_TASK) ? gpu_using_str : cpu_only_str) 1183 ((GPU_TASK) ? gpu_using_str : cpu_only_str)
1184 ); 1184 );
1185 1185
1186 return 0; 1186 return 0;
1187} 1187}
diff --git a/include/litmus.h b/include/litmus.h
index a4f6c61..0b2c407 100644
--- a/include/litmus.h
+++ b/include/litmus.h
@@ -77,12 +77,12 @@ typedef enum {
77 FIFO_MUTEX = 6, 77 FIFO_MUTEX = 6,
78 IKGLP_SEM = 7, 78 IKGLP_SEM = 7,
79 KFMLP_SEM = 8, 79 KFMLP_SEM = 8,
80 80
81 IKGLP_SIMPLE_GPU_AFF_OBS = 9, 81 IKGLP_SIMPLE_GPU_AFF_OBS = 9,
82 IKGLP_GPU_AFF_OBS = 10, 82 IKGLP_GPU_AFF_OBS = 10,
83 KFMLP_SIMPLE_GPU_AFF_OBS = 11, 83 KFMLP_SIMPLE_GPU_AFF_OBS = 11,
84 KFMLP_GPU_AFF_OBS = 12, 84 KFMLP_GPU_AFF_OBS = 12,
85 85
86 PRIOQ_MUTEX = 13, 86 PRIOQ_MUTEX = 13,
87} obj_type_t; 87} obj_type_t;
88 88
@@ -97,6 +97,13 @@ static inline int od_open(int fd, obj_type_t type, int obj_id)
97 return od_openx(fd, type, obj_id, 0); 97 return od_openx(fd, type, obj_id, 0);
98} 98}
99 99
100int litmus_open_lock(
101 obj_type_t protocol, /* which locking protocol to use, e.g., FMLP_SEM */
102 int lock_id, /* numerical id of the lock, user-specified */
103 const char* namespace, /* path to a shared file */
104 void *config_param); /* any extra info needed by the protocol (such
105 * as CPU under SRP and PCP), may be NULL */
106
100/* real-time locking protocol support */ 107/* real-time locking protocol support */
101int litmus_lock(int od); 108int litmus_lock(int od);
102int litmus_unlock(int od); 109int litmus_unlock(int od);
@@ -109,7 +116,7 @@ int litmus_unlock(int od);
109 * litmus_dgl_unlock({A, B, C, D}, 4); 116 * litmus_dgl_unlock({A, B, C, D}, 4);
110 */ 117 */
111int litmus_dgl_lock(int* ods, int dgl_size); 118int litmus_dgl_lock(int* ods, int dgl_size);
112int litmus_dgl_unlock(int* ods, int dgl_size); 119int litmus_dgl_unlock(int* ods, int dgl_size);
113 120
114/* nvidia graphics cards */ 121/* nvidia graphics cards */
115int register_nv_device(int nv_device_id); 122int register_nv_device(int nv_device_id);
@@ -129,9 +136,9 @@ void exit_litmus(void);
129typedef int (*rt_fn_t)(void*); 136typedef int (*rt_fn_t)(void*);
130 137
131/* These two functions configure the RT task to use enforced exe budgets */ 138/* These two functions configure the RT task to use enforced exe budgets */
132int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period); 139int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, lt_t wcet, lt_t period, unsigned int prio);
133int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, 140int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, lt_t wcet,
134 int period, task_class_t cls); 141 lt_t period, unsigned int priority, task_class_t cls);
135 142
136/* per-task modes */ 143/* per-task modes */
137enum rt_task_mode_t { 144enum rt_task_mode_t {
@@ -153,6 +160,7 @@ int wait_for_ts_release();
153int wait_for_ts_release2(struct timespec *release); 160int wait_for_ts_release2(struct timespec *release);
154int release_ts(lt_t *delay); 161int release_ts(lt_t *delay);
155int get_nr_ts_release_waiters(void); 162int get_nr_ts_release_waiters(void);
163int read_litmus_stats(int *ready, int *total);
156 164
157 165
158int enable_aux_rt_tasks(int flags); 166int enable_aux_rt_tasks(int flags);
@@ -177,7 +185,7 @@ double wctime(void);
177/* semaphore allocation */ 185/* semaphore allocation */
178 186
179typedef int (*open_sem_t)(int fd, int name); 187typedef int (*open_sem_t)(int fd, int name);
180 188
181static inline int open_fmlp_sem(int fd, int name) 189static inline int open_fmlp_sem(int fd, int name)
182{ 190{
183 return od_open(fd, FMLP_SEM, name); 191 return od_open(fd, FMLP_SEM, name);
@@ -214,7 +222,7 @@ static inline int open_fifo_sem(int fd, int name)
214{ 222{
215 return od_open(fd, FIFO_MUTEX, name); 223 return od_open(fd, FIFO_MUTEX, name);
216} 224}
217 225
218static inline int open_prioq_sem(int fd, int name) 226static inline int open_prioq_sem(int fd, int name)
219{ 227{
220 return od_open(fd, PRIOQ_MUTEX, name); 228 return od_open(fd, PRIOQ_MUTEX, name);
@@ -228,7 +236,7 @@ int open_ikglp_sem(int fd, int name, unsigned int nr_replicas);
228int open_kfmlp_gpu_sem(int fd, int name, 236int open_kfmlp_gpu_sem(int fd, int name,
229 unsigned int num_gpus, unsigned int gpu_offset, unsigned int rho, 237 unsigned int num_gpus, unsigned int gpu_offset, unsigned int rho,
230 int affinity_aware /* bool */); 238 int affinity_aware /* bool */);
231 239
232/* -- Example Configurations -- 240/* -- Example Configurations --
233 * 241 *
234 * Optimal IKGLP Configuration: 242 * Optimal IKGLP Configuration:
@@ -262,13 +270,13 @@ int open_kfmlp_gpu_sem(int fd, int name,
262 * - rho > 0 270 * - rho > 0
263 * - num_gpus > 0 271 * - num_gpus > 0
264 */ 272 */
265// takes names 'name' and 'name+1' 273// takes names 'name' and 'name+1'
266int open_gpusync_token_lock(int fd, int name, 274int open_gpusync_token_lock(int fd, int name,
267 unsigned int num_gpus, unsigned int gpu_offset, 275 unsigned int num_gpus, unsigned int gpu_offset,
268 unsigned int rho, unsigned int max_in_fifos, 276 unsigned int rho, unsigned int max_in_fifos,
269 unsigned int max_fifo_len, 277 unsigned int max_fifo_len,
270 int enable_affinity_heuristics /* bool */); 278 int enable_affinity_heuristics /* bool */);
271 279
272/* syscall overhead measuring */ 280/* syscall overhead measuring */
273int null_call(cycles_t *timestamp); 281int null_call(cycles_t *timestamp);
274 282
@@ -296,11 +304,11 @@ printf("%s:%d:%d\n",__FUNCTION__,__LINE__,temp); \
296__inject_action(temp); \ 304__inject_action(temp); \
297}while(0); 305}while(0);
298*/ 306*/
299 307
300#define inject_action(COUNT) \ 308#define inject_action(COUNT) \
301do { \ 309do { \
302}while(0); 310}while(0);
303 311
304 312
305/* Litmus signal handling */ 313/* Litmus signal handling */
306 314
diff --git a/include/tests.h b/include/tests.h
index ed2b409..4ca21f8 100644
--- a/include/tests.h
+++ b/include/tests.h
@@ -7,8 +7,11 @@
7 7
8#define fail(fmt, args...) \ 8#define fail(fmt, args...) \
9 do { \ 9 do { \
10 fprintf(stderr, "\n!! TEST FAILURE " fmt "\n at %s:%d (%s)\n", \ 10 fprintf(stderr, "\n!! TEST FAILURE " fmt \
11 ## args, __FILE__, __LINE__, __FUNCTION__); \ 11 "\n at %s:%d (%s)" \
12 "\n in task PID=%d\n", \
13 ## args, __FILE__, __LINE__, __FUNCTION__, \
14 getpid()); \
12 fflush(stderr); \ 15 fflush(stderr); \
13 exit(200); \ 16 exit(200); \
14 } while (0) 17 } while (0)
diff --git a/src/kernel_iface.c b/src/kernel_iface.c
index 4cc1af5..e446102 100644
--- a/src/kernel_iface.c
+++ b/src/kernel_iface.c
@@ -56,9 +56,8 @@ ssize_t read_file(const char* fname, void* buf, size_t maxlen)
56 return got; 56 return got;
57} 57}
58 58
59int get_nr_ts_release_waiters(void) 59int read_litmus_stats(int *ready, int *all)
60{ 60{
61 int ready = 0, all = 0;
62 char buf[100]; 61 char buf[100];
63 ssize_t len; 62 ssize_t len;
64 63
@@ -67,11 +66,17 @@ int get_nr_ts_release_waiters(void)
67 len = sscanf(buf, 66 len = sscanf(buf,
68 "real-time tasks = %d\n" 67 "real-time tasks = %d\n"
69 "ready for release = %d\n", 68 "ready for release = %d\n",
70 &all, &ready); 69 all, ready);
71 if (len == 2) 70 return len == 2;
71}
72
73int get_nr_ts_release_waiters(void)
74{
75 int ready, all;
76 if (read_litmus_stats(&ready, &all))
72 return ready; 77 return ready;
73 else 78 else
74 return len; 79 return -1;
75} 80}
76 81
77/* thread-local pointer to control page */ 82/* thread-local pointer to control page */
diff --git a/src/litmus.c b/src/litmus.c
index ba47e45..7cdffcc 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
@@ -32,7 +35,7 @@ static struct {
32 {IKGLP_GPU_AFF_OBS, "IKGLP-GPU"}, 35 {IKGLP_GPU_AFF_OBS, "IKGLP-GPU"},
33 {KFMLP_SIMPLE_GPU_AFF_OBS, "KFMLP-GPU-SIMPLE"}, 36 {KFMLP_SIMPLE_GPU_AFF_OBS, "KFMLP-GPU-SIMPLE"},
34 {KFMLP_GPU_AFF_OBS, "KFMLP-GPU"}, 37 {KFMLP_GPU_AFF_OBS, "KFMLP-GPU"},
35 38
36 {PRIOQ_MUTEX, "PRIOQ"}, 39 {PRIOQ_MUTEX, "PRIOQ"},
37}; 40};
38 41
@@ -60,6 +63,23 @@ const char* name_for_lock_protocol(int id)
60 return "<UNKNOWN>"; 63 return "<UNKNOWN>";
61} 64}
62 65
66int litmus_open_lock(
67 obj_type_t protocol,
68 int lock_id,
69 const char* namespace,
70 void *config_param)
71{
72 int fd, od;
73
74 fd = open(namespace, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
75 if (fd < 0)
76 return -1;
77 od = od_openx(fd, protocol, lock_id, config_param);
78 close(fd);
79 return od;
80}
81
82
63 83
64void show_rt_param(struct rt_task* tp) 84void show_rt_param(struct rt_task* tp)
65{ 85{
@@ -171,7 +191,7 @@ int open_kfmlp_gpu_sem(int fd, int name,
171 unsigned int num_replicas; 191 unsigned int num_replicas;
172 struct gpu_affinity_observer_args aff_args; 192 struct gpu_affinity_observer_args aff_args;
173 int aff_type; 193 int aff_type;
174 194
175 // number of GPU tokens 195 // number of GPU tokens
176 num_replicas = num_gpus * rho; 196 num_replicas = num_gpus * rho;
177 197
@@ -181,20 +201,20 @@ int open_kfmlp_gpu_sem(int fd, int name,
181 perror("open_kfmlp_sem"); 201 perror("open_kfmlp_sem");
182 return -1; 202 return -1;
183 } 203 }
184 204
185 // create the affinity method to use. 205 // create the affinity method to use.
186 // "no affinity" -> KFMLP_SIMPLE_GPU_AFF_OBS 206 // "no affinity" -> KFMLP_SIMPLE_GPU_AFF_OBS
187 aff_args.obs.lock_od = lock_od; 207 aff_args.obs.lock_od = lock_od;
188 aff_args.replica_to_gpu_offset = gpu_offset; 208 aff_args.replica_to_gpu_offset = gpu_offset;
189 aff_args.rho = rho; 209 aff_args.rho = rho;
190 210
191 aff_type = (affinity_aware) ? KFMLP_GPU_AFF_OBS : KFMLP_SIMPLE_GPU_AFF_OBS; 211 aff_type = (affinity_aware) ? KFMLP_GPU_AFF_OBS : KFMLP_SIMPLE_GPU_AFF_OBS;
192 affinity_od = od_openx(fd, aff_type, name+1, &aff_args); 212 affinity_od = od_openx(fd, aff_type, name+1, &aff_args);
193 if(affinity_od < 0) { 213 if(affinity_od < 0) {
194 perror("open_kfmlp_aff"); 214 perror("open_kfmlp_aff");
195 return -1; 215 return -1;
196 } 216 }
197 217
198 return lock_od; 218 return lock_od;
199} 219}
200 220
@@ -209,28 +229,28 @@ int open_kfmlp_gpu_sem(int fd, int name,
209// 229//
210// // number of GPU tokens 230// // number of GPU tokens
211// num_replicas = num_gpus * num_simult_users; 231// num_replicas = num_gpus * num_simult_users;
212// 232//
213// // create the GPU token lock 233// // create the GPU token lock
214// lock_od = open_ikglp_sem(fd, name, (void*)&num_replicas); 234// lock_od = open_ikglp_sem(fd, name, (void*)&num_replicas);
215// if(lock_od < 0) { 235// if(lock_od < 0) {
216// perror("open_ikglp_sem"); 236// perror("open_ikglp_sem");
217// return -1; 237// return -1;
218// } 238// }
219// 239//
220// // create the affinity method to use. 240// // create the affinity method to use.
221// // "no affinity" -> KFMLP_SIMPLE_GPU_AFF_OBS 241// // "no affinity" -> KFMLP_SIMPLE_GPU_AFF_OBS
222// aff_args.obs.lock_od = lock_od; 242// aff_args.obs.lock_od = lock_od;
223// aff_args.replica_to_gpu_offset = gpu_offset; 243// aff_args.replica_to_gpu_offset = gpu_offset;
224// aff_args.nr_simult_users = num_simult_users; 244// aff_args.nr_simult_users = num_simult_users;
225// aff_args.relaxed_rules = (relax_max_fifo_len) ? 1 : 0; 245// aff_args.relaxed_rules = (relax_max_fifo_len) ? 1 : 0;
226// 246//
227// aff_type = (affinity_aware) ? IKGLP_GPU_AFF_OBS : IKGLP_SIMPLE_GPU_AFF_OBS; 247// aff_type = (affinity_aware) ? IKGLP_GPU_AFF_OBS : IKGLP_SIMPLE_GPU_AFF_OBS;
228// affinity_od = od_openx(fd, aff_type, name+1, &aff_args); 248// affinity_od = od_openx(fd, aff_type, name+1, &aff_args);
229// if(affinity_od < 0) { 249// if(affinity_od < 0) {
230// perror("open_ikglp_aff"); 250// perror("open_ikglp_aff");
231// return -1; 251// return -1;
232// } 252// }
233// 253//
234// return lock_od; 254// return lock_od;
235//} 255//}
236 256
@@ -243,7 +263,7 @@ int open_ikglp_sem(int fd, int name, unsigned int nr_replicas)
243 .nr_replicas = nr_replicas, 263 .nr_replicas = nr_replicas,
244 .max_in_fifos = IKGLP_M_IN_FIFOS, 264 .max_in_fifos = IKGLP_M_IN_FIFOS,
245 .max_fifo_len = IKGLP_OPTIMAL_FIFO_LEN}; 265 .max_fifo_len = IKGLP_OPTIMAL_FIFO_LEN};
246 266
247 return od_openx(fd, IKGLP_SEM, name, &args); 267 return od_openx(fd, IKGLP_SEM, name, &args);
248} 268}
249 269
@@ -257,7 +277,7 @@ int open_gpusync_token_lock(int fd, int name,
257{ 277{
258 int lock_od; 278 int lock_od;
259 int affinity_od; 279 int affinity_od;
260 280
261 struct ikglp_args args = { 281 struct ikglp_args args = {
262 .nr_replicas = num_gpus*rho, 282 .nr_replicas = num_gpus*rho,
263 .max_in_fifos = max_in_fifos, 283 .max_in_fifos = max_in_fifos,
@@ -265,41 +285,37 @@ int open_gpusync_token_lock(int fd, int name,
265 }; 285 };
266 struct gpu_affinity_observer_args aff_args; 286 struct gpu_affinity_observer_args aff_args;
267 int aff_type; 287 int aff_type;
268 288
269 if (!num_gpus || !rho) { 289 if (!num_gpus || !rho) {
270 perror("open_gpusync_sem"); 290 perror("open_gpusync_sem");
271 return -1; 291 return -1;
272 } 292 }
273 293
274 if ((max_in_fifos != IKGLP_UNLIMITED_IN_FIFOS) && 294 if ((max_in_fifos != IKGLP_UNLIMITED_IN_FIFOS) &&
275 (max_fifo_len != IKGLP_UNLIMITED_FIFO_LEN) && 295 (max_fifo_len != IKGLP_UNLIMITED_FIFO_LEN) &&
276 (max_in_fifos > args.nr_replicas * max_fifo_len)) { 296 (max_in_fifos > args.nr_replicas * max_fifo_len)) {
277 perror("open_gpusync_sem"); 297 perror("open_gpusync_sem");
278 return(-1); 298 return(-1);
279 } 299 }
280 300
281 lock_od = od_openx(fd, IKGLP_SEM, name, &args); 301 lock_od = od_openx(fd, IKGLP_SEM, name, &args);
282 if(lock_od < 0) { 302 if(lock_od < 0) {
283 perror("open_gpusync_sem"); 303 perror("open_gpusync_sem");
284 return -1; 304 return -1;
285 } 305 }
286 306
287 // create the affinity method to use. 307 // create the affinity method to use.
288 aff_args.obs.lock_od = lock_od; 308 aff_args.obs.lock_od = lock_od;
289 aff_args.replica_to_gpu_offset = gpu_offset; 309 aff_args.replica_to_gpu_offset = gpu_offset;
290 aff_args.rho = rho; 310 aff_args.rho = rho;
291 aff_args.relaxed_rules = (max_fifo_len == IKGLP_UNLIMITED_FIFO_LEN) ? 1 : 0; 311 aff_args.relaxed_rules = (max_fifo_len == IKGLP_UNLIMITED_FIFO_LEN) ? 1 : 0;
292 312
293 aff_type = (enable_affinity_heuristics) ? IKGLP_GPU_AFF_OBS : IKGLP_SIMPLE_GPU_AFF_OBS; 313 aff_type = (enable_affinity_heuristics) ? IKGLP_GPU_AFF_OBS : IKGLP_SIMPLE_GPU_AFF_OBS;
294 affinity_od = od_openx(fd, aff_type, name+1, &aff_args); 314 affinity_od = od_openx(fd, aff_type, name+1, &aff_args);
295 if(affinity_od < 0) { 315 if(affinity_od < 0) {
296 perror("open_gpusync_affinity"); 316 perror("open_gpusync_affinity");
297 return -1; 317 return -1;
298 } 318 }
299 319
300 return lock_od; 320 return lock_od;
301} 321}
302
303
304
305
diff --git a/src/signal.c b/src/signal.c
index bfe18b9..397a797 100644
--- a/src/signal.c
+++ b/src/signal.c
@@ -28,7 +28,7 @@ static void reg_litmus_signals(unsigned long litmus_sig_mask,
28{ 28{
29 int ret; 29 int ret;
30 30
31 if (litmus_sig_mask | SIG_BUDGET_MASK) { 31 if (litmus_sig_mask | SIG_BUDGET_MASK) {
32 ret = sigaction(SIG_BUDGET, pAction, NULL); 32 ret = sigaction(SIG_BUDGET, pAction, NULL);
33 check("SIG_BUDGET"); 33 check("SIG_BUDGET");
34 } 34 }
diff --git a/src/task.c b/src/task.c
index 26fc15a..9317cc7 100644
--- a/src/task.c
+++ b/src/task.c
@@ -40,15 +40,16 @@ int __launch_rt_task(rt_fn_t rt_prog, void *rt_arg, rt_setup_fn_t setup,
40 return rt_task; 40 return rt_task;
41} 41}
42 42
43int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period, 43int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, lt_t wcet, lt_t period,
44 task_class_t rt_class) 44 unsigned int priority, task_class_t cls)
45{ 45{
46 struct rt_task params; 46 struct rt_task params;
47 params.cpu = cpu; 47 params.cpu = cpu;
48 params.period = period; 48 params.period = period;
49 params.exec_cost = wcet; 49 params.exec_cost = wcet;
50 params.cls = rt_class; 50 params.cls = cls;
51 params.phase = 0; 51 params.phase = 0;
52 params.priority = priority;
52 /* enforce budget for tasks that might not use sleep_next_period() */ 53 /* enforce budget for tasks that might not use sleep_next_period() */
53 params.budget_policy = QUANTUM_ENFORCEMENT; 54 params.budget_policy = QUANTUM_ENFORCEMENT;
54 55
@@ -56,8 +57,9 @@ int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period,
56 (rt_setup_fn_t) set_rt_task_param, &params); 57 (rt_setup_fn_t) set_rt_task_param, &params);
57} 58}
58 59
59int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period) { 60int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, lt_t wcet, lt_t period,
60 return __create_rt_task(rt_prog, arg, cpu, wcet, period, RT_CLASS_HARD); 61 unsigned int priority) {
62 return __create_rt_task(rt_prog, arg, cpu, wcet, period, priority, RT_CLASS_HARD);
61} 63}
62 64
63 65
diff --git a/tests/fdso.c b/tests/fdso.c
index 8e320cf..c06e28c 100644
--- a/tests/fdso.c
+++ b/tests/fdso.c
@@ -16,7 +16,7 @@ TESTCASE(fmlp_not_active, C_EDF | PFAIR | LINUX,
16{ 16{
17 int fd; 17 int fd;
18 18
19 SYSCALL( fd = open(".fmlp_locks", O_RDONLY | O_CREAT) ); 19 SYSCALL( fd = open(".fmlp_locks", O_RDONLY | O_CREAT, S_IRUSR) );
20 20
21 ASSERT(fd != -1); 21 ASSERT(fd != -1);
22 22
@@ -57,7 +57,7 @@ TESTCASE(not_inherit_od, GSN_EDF | PSN_EDF,
57{ 57{
58 int fd, od, pid, status; 58 int fd, od, pid, status;
59 59
60 SYSCALL( fd = open(".fmlp_locks", O_RDONLY | O_CREAT) ); 60 SYSCALL( fd = open(".fmlp_locks", O_RDONLY | O_CREAT, S_IRUSR) );
61 61
62 SYSCALL( od = open_fmlp_sem(fd, 0) ); 62 SYSCALL( od = open_fmlp_sem(fd, 0) );
63 63
diff --git a/tests/locks.c b/tests/locks.c
index d7ebfe2..9a928b3 100644
--- a/tests/locks.c
+++ b/tests/locks.c
@@ -11,7 +11,7 @@ TESTCASE(not_lock_fmlp_be, GSN_EDF | PSN_EDF | P_FP,
11{ 11{
12 int fd, od; 12 int fd, od;
13 13
14 SYSCALL( fd = open(".fmlp_locks", O_RDONLY | O_CREAT) ); 14 SYSCALL( fd = open(".fmlp_locks", O_RDONLY | O_CREAT, S_IRUSR) );
15 15
16 SYSCALL( od = open_fmlp_sem(fd, 0) ); 16 SYSCALL( od = open_fmlp_sem(fd, 0) );
17 17
@@ -34,7 +34,7 @@ TESTCASE(not_lock_srp_be, PSN_EDF | P_FP,
34{ 34{
35 int fd, od; 35 int fd, od;
36 36
37 SYSCALL( fd = open(".srp_locks", O_RDONLY | O_CREAT) ); 37 SYSCALL( fd = open(".srp_locks", O_RDONLY | O_CREAT, S_IRUSR) );
38 38
39 /* BE tasks may not open SRP semaphores */ 39 /* BE tasks may not open SRP semaphores */
40 40
@@ -51,7 +51,7 @@ TESTCASE(lock_srp, PSN_EDF | P_FP,
51{ 51{
52 int fd, od; 52 int fd, od;
53 53
54 SYSCALL( fd = open(".srp_locks", O_RDONLY | O_CREAT) ); 54 SYSCALL( fd = open(".srp_locks", O_RDONLY | O_CREAT, S_IRUSR) );
55 55
56 SYSCALL( sporadic_partitioned(10, 100, 0) ); 56 SYSCALL( sporadic_partitioned(10, 100, 0) );
57 SYSCALL( task_mode(LITMUS_RT_TASK) ); 57 SYSCALL( task_mode(LITMUS_RT_TASK) );
@@ -83,7 +83,7 @@ TESTCASE(lock_fmlp, PSN_EDF | GSN_EDF | P_FP,
83{ 83{
84 int fd, od; 84 int fd, od;
85 85
86 SYSCALL( fd = open(".fmlp_locks", O_RDONLY | O_CREAT) ); 86 SYSCALL( fd = open(".fmlp_locks", O_RDONLY | O_CREAT, S_IRUSR) );
87 87
88 SYSCALL( sporadic_partitioned(10, 100, 0) ); 88 SYSCALL( sporadic_partitioned(10, 100, 0) );
89 SYSCALL( task_mode(LITMUS_RT_TASK) ); 89 SYSCALL( task_mode(LITMUS_RT_TASK) );
diff --git a/tests/nesting.c b/tests/nesting.c
new file mode 100644
index 0000000..b294334
--- /dev/null
+++ b/tests/nesting.c
@@ -0,0 +1,468 @@
1#include <fcntl.h>
2#include <unistd.h>
3#include <stdio.h>
4
5#include "tests.h"
6#include "litmus.h"
7
8TESTCASE(lock_fmlp_nesting, PSN_EDF | GSN_EDF | P_FP,
9 "FMLP no nesting allowed")
10{
11 int fd, od, od2;
12
13 SYSCALL( fd = open(".fmlp_locks", O_RDONLY | O_CREAT, S_IRUSR) );
14
15 SYSCALL( sporadic_partitioned(10, 100, 0) );
16 SYSCALL( task_mode(LITMUS_RT_TASK) );
17
18 SYSCALL( od = open_fmlp_sem(fd, 0) );
19 SYSCALL( od2 = open_fmlp_sem(fd, 1) );
20
21 SYSCALL( litmus_lock(od) );
22 SYSCALL( litmus_unlock(od) );
23
24 SYSCALL( litmus_lock(od2) );
25 SYSCALL( litmus_unlock(od2) );
26
27 SYSCALL( litmus_lock(od) );
28 SYSCALL_FAILS(EBUSY, litmus_lock(od2));
29 SYSCALL( litmus_unlock(od) );
30
31 SYSCALL( litmus_lock(od2) );
32 SYSCALL_FAILS(EBUSY, litmus_lock(od));
33 SYSCALL( litmus_unlock(od2) );
34
35 SYSCALL( od_close(od) );
36 SYSCALL( od_close(od2) );
37
38 SYSCALL( close(fd) );
39
40 SYSCALL( remove(".fmlp_locks") );
41}
42
43TESTCASE(lock_fmlp_srp_nesting, PSN_EDF | P_FP,
44 "FMLP no nesting with SRP resources allowed")
45{
46 int fd, od, od2;
47
48 SYSCALL( fd = open(".fmlp_locks", O_RDONLY | O_CREAT, S_IRUSR) );
49
50 SYSCALL( sporadic_partitioned(10, 100, 0) );
51 SYSCALL( task_mode(LITMUS_RT_TASK) );
52
53 SYSCALL( od = open_fmlp_sem(fd, 0) );
54 SYSCALL( od2 = open_srp_sem(fd, 1) );
55
56 SYSCALL( litmus_lock(od) );
57 SYSCALL( litmus_unlock(od) );
58
59 SYSCALL( litmus_lock(od2) );
60 SYSCALL( litmus_unlock(od2) );
61
62 SYSCALL( litmus_lock(od) );
63 SYSCALL_FAILS(EBUSY, litmus_lock(od2));
64 SYSCALL( litmus_unlock(od) );
65
66 SYSCALL( litmus_lock(od2) );
67 SYSCALL_FAILS(EBUSY, litmus_lock(od));
68 SYSCALL( litmus_unlock(od2) );
69
70 SYSCALL( od_close(od) );
71 SYSCALL( od_close(od2) );
72
73 SYSCALL( close(fd) );
74
75 SYSCALL( remove(".fmlp_locks") );
76}
77
78TESTCASE(lock_srp_nesting, PSN_EDF | P_FP,
79 "SRP nesting allowed")
80{
81 int fd, od, od2;
82
83 SYSCALL( fd = open(".fmlp_locks", O_RDONLY | O_CREAT, S_IRUSR) );
84
85 SYSCALL( sporadic_partitioned(10, 100, 0) );
86 SYSCALL( task_mode(LITMUS_RT_TASK) );
87
88 SYSCALL( od = open_srp_sem(fd, 0) );
89 SYSCALL( od2 = open_srp_sem(fd, 1) );
90
91 SYSCALL( litmus_lock(od) );
92 SYSCALL( litmus_unlock(od) );
93
94 SYSCALL( litmus_lock(od2) );
95 SYSCALL( litmus_unlock(od2) );
96
97 SYSCALL( litmus_lock(od) );
98 SYSCALL( litmus_lock(od2) );
99 SYSCALL( litmus_unlock(od2) );
100 SYSCALL( litmus_unlock(od) );
101
102 SYSCALL( litmus_lock(od2) );
103 SYSCALL( litmus_lock(od) );
104 SYSCALL( litmus_unlock(od) );
105 SYSCALL( litmus_unlock(od2) );
106
107 SYSCALL( od_close(od) );
108 SYSCALL( od_close(od2) );
109
110 SYSCALL( close(fd) );
111
112 SYSCALL( remove(".fmlp_locks") );
113}
114
115TESTCASE(lock_pcp_nesting, P_FP,
116 "PCP nesting allowed")
117{
118 int od, od2;
119 const char* namespace = ".pcp_locks";
120
121 SYSCALL( sporadic_partitioned(10, 100, 0) );
122 SYSCALL( task_mode(LITMUS_RT_TASK) );
123
124 SYSCALL( od = litmus_open_lock(PCP_SEM, 0, namespace, NULL) );
125 SYSCALL( od2 = litmus_open_lock(PCP_SEM, 1, namespace, NULL) );
126
127 SYSCALL( litmus_lock(od) );
128 SYSCALL( litmus_unlock(od) );
129
130 SYSCALL( litmus_lock(od2) );
131 SYSCALL( litmus_unlock(od2) );
132
133 SYSCALL( litmus_lock(od) );
134 SYSCALL( litmus_lock(od2) );
135 SYSCALL( litmus_unlock(od2) );
136 SYSCALL( litmus_unlock(od) );
137
138 SYSCALL( litmus_lock(od2) );
139 SYSCALL( litmus_lock(od) );
140 SYSCALL( litmus_unlock(od) );
141 SYSCALL( litmus_unlock(od2) );
142
143 SYSCALL( od_close(od) );
144 SYSCALL( od_close(od2) );
145
146 SYSCALL( remove(namespace) );
147}
148
149TESTCASE(lock_mpcp_pcp_no_nesting, P_FP,
150 "PCP and MPCP nesting not allowed")
151{
152 int od, od2;
153 const char* namespace = ".pcp_locks";
154
155 SYSCALL( sporadic_partitioned(10, 100, 0) );
156 SYSCALL( task_mode(LITMUS_RT_TASK) );
157
158 SYSCALL( od = litmus_open_lock(PCP_SEM, 0, namespace, NULL) );
159 SYSCALL( od2 = litmus_open_lock(MPCP_SEM, 1, namespace, NULL) );
160
161 SYSCALL( litmus_lock(od) );
162 SYSCALL( litmus_unlock(od) );
163
164 SYSCALL( litmus_lock(od2) );
165 SYSCALL( litmus_unlock(od2) );
166
167 SYSCALL( litmus_lock(od) );
168 SYSCALL_FAILS(EBUSY, litmus_lock(od2));
169 SYSCALL( litmus_unlock(od) );
170
171 SYSCALL( litmus_lock(od2) );
172 SYSCALL_FAILS(EBUSY, litmus_lock(od));
173 SYSCALL( litmus_unlock(od2) );
174
175 SYSCALL( od_close(od) );
176 SYSCALL( od_close(od2) );
177
178 SYSCALL( remove(namespace) );
179}
180
181TESTCASE(lock_fmlp_pcp_no_nesting, P_FP,
182 "PCP and FMLP nesting not allowed")
183{
184 int od, od2;
185 const char* namespace = ".pcp_locks";
186
187 SYSCALL( sporadic_partitioned(10, 100, 0) );
188 SYSCALL( task_mode(LITMUS_RT_TASK) );
189
190 SYSCALL( od = litmus_open_lock(PCP_SEM, 0, namespace, NULL) );
191 SYSCALL( od2 = litmus_open_lock(FMLP_SEM, 1, namespace, NULL) );
192
193 SYSCALL( litmus_lock(od) );
194 SYSCALL( litmus_unlock(od) );
195
196 SYSCALL( litmus_lock(od2) );
197 SYSCALL( litmus_unlock(od2) );
198
199 SYSCALL( litmus_lock(od) );
200 SYSCALL_FAILS(EBUSY, litmus_lock(od2));
201 SYSCALL( litmus_unlock(od) );
202
203 SYSCALL( litmus_lock(od2) );
204 SYSCALL_FAILS(EBUSY, litmus_lock(od));
205 SYSCALL( litmus_unlock(od2) );
206
207 SYSCALL( od_close(od) );
208 SYSCALL( od_close(od2) );
209
210 SYSCALL( remove(namespace) );
211}
212
213TESTCASE(lock_dpcp_pcp_no_nesting, P_FP,
214 "PCP and DPCP nesting not allowed")
215{
216 int od, od2;
217 int cpu = 0;
218 const char* namespace = ".pcp_locks";
219
220 SYSCALL( sporadic_partitioned(10, 100, 0) );
221 SYSCALL( task_mode(LITMUS_RT_TASK) );
222
223 SYSCALL( od = litmus_open_lock(PCP_SEM, 0, namespace, NULL) );
224 SYSCALL( od2 = litmus_open_lock(DPCP_SEM, 1, namespace, &cpu) );
225
226 SYSCALL( litmus_lock(od) );
227 SYSCALL( litmus_unlock(od) );
228
229 SYSCALL( litmus_lock(od2) );
230 SYSCALL( litmus_unlock(od2) );
231
232 SYSCALL( litmus_lock(od) );
233 SYSCALL_FAILS(EBUSY, litmus_lock(od2));
234 SYSCALL( litmus_unlock(od) );
235
236 SYSCALL( litmus_lock(od2) );
237 SYSCALL_FAILS(EBUSY, litmus_lock(od));
238 SYSCALL( litmus_unlock(od2) );
239
240 SYSCALL( od_close(od) );
241 SYSCALL( od_close(od2) );
242
243 SYSCALL( remove(namespace) );
244}
245
246TESTCASE(lock_mpcp_srp_no_nesting, P_FP,
247 "SRP and MPCP nesting not allowed")
248{
249 int od, od2;
250 const char* namespace = ".pcp_locks";
251
252 SYSCALL( sporadic_partitioned(10, 100, 0) );
253 SYSCALL( task_mode(LITMUS_RT_TASK) );
254
255 SYSCALL( od = litmus_open_lock(SRP_SEM, 0, namespace, NULL) );
256 SYSCALL( od2 = litmus_open_lock(MPCP_SEM, 1, namespace, NULL) );
257
258 SYSCALL( litmus_lock(od) );
259 SYSCALL( litmus_unlock(od) );
260
261 SYSCALL( litmus_lock(od2) );
262 SYSCALL( litmus_unlock(od2) );
263
264 SYSCALL( litmus_lock(od) );
265 SYSCALL_FAILS(EBUSY, litmus_lock(od2));
266 SYSCALL( litmus_unlock(od) );
267
268 SYSCALL( litmus_lock(od2) );
269 SYSCALL_FAILS(EBUSY, litmus_lock(od));
270 SYSCALL( litmus_unlock(od2) );
271
272 SYSCALL( od_close(od) );
273 SYSCALL( od_close(od2) );
274
275 SYSCALL( remove(namespace) );
276}
277
278TESTCASE(lock_dpcp_srp_no_nesting, P_FP,
279 "SRP and DPCP nesting not allowed")
280{
281 int od, od2;
282 int cpu = 0;
283 const char* namespace = ".pcp_locks";
284
285 SYSCALL( sporadic_partitioned(10, 100, 0) );
286 SYSCALL( task_mode(LITMUS_RT_TASK) );
287
288 SYSCALL( od = litmus_open_lock(SRP_SEM, 0, namespace, NULL) );
289 SYSCALL( od2 = litmus_open_lock(DPCP_SEM, 1, namespace, &cpu) );
290
291 SYSCALL( litmus_lock(od) );
292 SYSCALL( litmus_unlock(od) );
293
294 SYSCALL( litmus_lock(od2) );
295 SYSCALL( litmus_unlock(od2) );
296
297 SYSCALL( litmus_lock(od) );
298 SYSCALL_FAILS(EBUSY, litmus_lock(od2));
299 SYSCALL( litmus_unlock(od) );
300
301 SYSCALL( litmus_lock(od2) );
302 SYSCALL_FAILS(EBUSY, litmus_lock(od));
303 SYSCALL( litmus_unlock(od2) );
304
305 SYSCALL( od_close(od) );
306 SYSCALL( od_close(od2) );
307
308 SYSCALL( remove(namespace) );
309}
310
311TESTCASE(lock_fmlp_mpcp_no_nesting, P_FP,
312 "MPCP and FMLP nesting not allowed")
313{
314 int od, od2;
315 const char* namespace = ".pcp_locks";
316
317 SYSCALL( sporadic_partitioned(10, 100, 0) );
318 SYSCALL( task_mode(LITMUS_RT_TASK) );
319
320 SYSCALL( od = litmus_open_lock(MPCP_SEM, 0, namespace, NULL) );
321 SYSCALL( od2 = litmus_open_lock(FMLP_SEM, 1, namespace, NULL) );
322
323 SYSCALL( litmus_lock(od) );
324 SYSCALL( litmus_unlock(od) );
325
326 SYSCALL( litmus_lock(od2) );
327 SYSCALL( litmus_unlock(od2) );
328
329 SYSCALL( litmus_lock(od) );
330 SYSCALL_FAILS(EBUSY, litmus_lock(od2));
331 SYSCALL( litmus_unlock(od) );
332
333 SYSCALL( litmus_lock(od2) );
334 SYSCALL_FAILS(EBUSY, litmus_lock(od));
335 SYSCALL( litmus_unlock(od2) );
336
337 SYSCALL( od_close(od) );
338 SYSCALL( od_close(od2) );
339
340 SYSCALL( remove(namespace) );
341}
342
343TESTCASE(lock_fmlp_dpcp_no_nesting, P_FP,
344 "DPCP and FMLP nesting not allowed")
345{
346 int od, od2;
347 const char* namespace = ".pcp_locks";
348 int cpu = 0;
349
350 SYSCALL( sporadic_partitioned(10, 100, 0) );
351 SYSCALL( task_mode(LITMUS_RT_TASK) );
352
353 SYSCALL( od = litmus_open_lock(DPCP_SEM, 0, namespace, &cpu) );
354 SYSCALL( od2 = litmus_open_lock(FMLP_SEM, 1, namespace, NULL) );
355
356 SYSCALL( litmus_lock(od) );
357 SYSCALL( litmus_unlock(od) );
358
359 SYSCALL( litmus_lock(od2) );
360 SYSCALL( litmus_unlock(od2) );
361
362 SYSCALL( litmus_lock(od) );
363 SYSCALL_FAILS(EBUSY, litmus_lock(od2));
364 SYSCALL( litmus_unlock(od) );
365
366 SYSCALL( litmus_lock(od2) );
367 SYSCALL_FAILS(EBUSY, litmus_lock(od));
368 SYSCALL( litmus_unlock(od2) );
369
370 SYSCALL( od_close(od) );
371 SYSCALL( od_close(od2) );
372
373 SYSCALL( remove(namespace) );
374}
375
376TESTCASE(mpcp_nesting, P_FP,
377 "MPCP no nesting allowed")
378{
379 int od, od2;
380
381 SYSCALL( sporadic_partitioned(10, 100, 0) );
382 SYSCALL( task_mode(LITMUS_RT_TASK) );
383
384 SYSCALL( od = litmus_open_lock(MPCP_SEM, 0, ".mpcp_locks", NULL) );
385 SYSCALL( od2 = litmus_open_lock(MPCP_SEM, 1, ".mpcp_locks", NULL) );
386
387 SYSCALL( litmus_lock(od) );
388 SYSCALL( litmus_unlock(od) );
389
390 SYSCALL( litmus_lock(od2) );
391 SYSCALL( litmus_unlock(od2) );
392
393 SYSCALL( litmus_lock(od) );
394 SYSCALL_FAILS(EBUSY, litmus_lock(od2));
395 SYSCALL( litmus_unlock(od) );
396
397 SYSCALL( litmus_lock(od2) );
398 SYSCALL_FAILS(EBUSY, litmus_lock(od));
399 SYSCALL( litmus_unlock(od2) );
400
401 SYSCALL( od_close(od) );
402 SYSCALL( od_close(od2) );
403
404 SYSCALL( remove(".mpcp_locks") );
405}
406
407TESTCASE(mpcpvs_nesting, P_FP,
408 "MPCP-VS no nesting allowed")
409{
410 int od, od2;
411
412 SYSCALL( sporadic_partitioned(10, 100, 0) );
413 SYSCALL( task_mode(LITMUS_RT_TASK) );
414
415 SYSCALL( od = litmus_open_lock(MPCP_VS_SEM, 0, ".mpcp_locks", NULL) );
416 SYSCALL( od2 = litmus_open_lock(MPCP_VS_SEM, 1, ".mpcp_locks", NULL) );
417
418 SYSCALL( litmus_lock(od) );
419 SYSCALL( litmus_unlock(od) );
420
421 SYSCALL( litmus_lock(od2) );
422 SYSCALL( litmus_unlock(od2) );
423
424 SYSCALL( litmus_lock(od) );
425 SYSCALL_FAILS(EBUSY, litmus_lock(od2));
426 SYSCALL( litmus_unlock(od) );
427
428 SYSCALL( litmus_lock(od2) );
429 SYSCALL_FAILS(EBUSY, litmus_lock(od));
430 SYSCALL( litmus_unlock(od2) );
431
432 SYSCALL( od_close(od) );
433 SYSCALL( od_close(od2) );
434
435 SYSCALL( remove(".mpcp_locks") );
436}
437
438TESTCASE(dpcp_nesting, P_FP,
439 "DPCP no nesting allowed")
440{
441 int od, od2;
442 int cpu = 0;
443
444 SYSCALL( sporadic_partitioned(10, 100, 0) );
445 SYSCALL( task_mode(LITMUS_RT_TASK) );
446
447 SYSCALL( od = litmus_open_lock(DPCP_SEM, 0, ".dpcp_locks", &cpu) );
448 SYSCALL( od2 = litmus_open_lock(DPCP_SEM, 1, ".dpcp_locks", &cpu) );
449
450 SYSCALL( litmus_lock(od) );
451 SYSCALL( litmus_unlock(od) );
452
453 SYSCALL( litmus_lock(od2) );
454 SYSCALL( litmus_unlock(od2) );
455
456 SYSCALL( litmus_lock(od) );
457 SYSCALL_FAILS(EBUSY, litmus_lock(od2));
458 SYSCALL( litmus_unlock(od) );
459
460 SYSCALL( litmus_lock(od2) );
461 SYSCALL_FAILS(EBUSY, litmus_lock(od));
462 SYSCALL( litmus_unlock(od2) );
463
464 SYSCALL( od_close(od) );
465 SYSCALL( od_close(od2) );
466
467 SYSCALL( remove(".dpcp_locks") );
468}
diff --git a/tests/pcp.c b/tests/pcp.c
index 88d1be3..8e1204f 100644
--- a/tests/pcp.c
+++ b/tests/pcp.c
@@ -1,6 +1,8 @@
1#include <fcntl.h> 1#include <fcntl.h>
2#include <unistd.h> 2#include <unistd.h>
3#include <stdio.h> 3#include <stdio.h>
4#include <sys/wait.h> /* for waitpid() */
5
4 6
5#include "tests.h" 7#include "tests.h"
6#include "litmus.h" 8#include "litmus.h"
@@ -11,7 +13,7 @@ TESTCASE(lock_pcp, P_FP,
11{ 13{
12 int fd, od, cpu = 0; 14 int fd, od, cpu = 0;
13 15
14 SYSCALL( fd = open(".pcp_locks", O_RDONLY | O_CREAT) ); 16 SYSCALL( fd = open(".pcp_locks", O_RDONLY | O_CREAT, S_IRUSR) );
15 17
16 SYSCALL( sporadic_partitioned(10, 100, cpu) ); 18 SYSCALL( sporadic_partitioned(10, 100, cpu) );
17 SYSCALL( task_mode(LITMUS_RT_TASK) ); 19 SYSCALL( task_mode(LITMUS_RT_TASK) );
@@ -37,12 +39,218 @@ TESTCASE(lock_pcp, P_FP,
37 SYSCALL( remove(".pcp_locks") ); 39 SYSCALL( remove(".pcp_locks") );
38} 40}
39 41
42TESTCASE(pcp_inheritance, P_FP,
43 "PCP priority inheritance")
44{
45 int fd, od, cpu = 0;
46
47 int child_hi, child_lo, child_middle, status, waiters;
48 lt_t delay = ms2lt(100);
49 double start, stop;
50
51 struct rt_task params;
52 params.cpu = 0;
53 params.exec_cost = ms2lt(10000);
54 params.period = ms2lt(100000);
55 params.relative_deadline = params.period;
56 params.phase = 0;
57 params.cls = RT_CLASS_HARD;
58 params.budget_policy = NO_ENFORCEMENT;
59
60 SYSCALL( fd = open(".pcp_locks", O_RDONLY | O_CREAT, S_IRUSR) );
61
62
63 child_lo = FORK_TASK(
64 params.priority = LITMUS_LOWEST_PRIORITY;
65 params.phase = 0;
66 SYSCALL( set_rt_task_param(gettid(), &params) );
67 SYSCALL( be_migrate_to(params.cpu) );
68 SYSCALL( task_mode(LITMUS_RT_TASK) );
69
70 SYSCALL( od = open_pcp_sem(fd, 0, cpu) );
71
72 SYSCALL( wait_for_ts_release() );
73
74 SYSCALL( litmus_lock(od) );
75 start = cputime();
76 while (cputime() - start < 0.25)
77 ;
78 SYSCALL( litmus_unlock(od) );
79
80 SYSCALL(sleep_next_period() );
81 );
82
83 child_middle = FORK_TASK(
84 params.priority = LITMUS_HIGHEST_PRIORITY + 1;
85 params.phase = ms2lt(100);
86
87 SYSCALL( set_rt_task_param(gettid(), &params) );
88 SYSCALL( be_migrate_to(params.cpu) );
89 SYSCALL( task_mode(LITMUS_RT_TASK) );
90
91
92 SYSCALL( wait_for_ts_release() );
93
94 start = cputime();
95 while (cputime() - start < 5)
96 ;
97 SYSCALL( sleep_next_period() );
98 );
99
100 child_hi = FORK_TASK(
101 params.priority = LITMUS_HIGHEST_PRIORITY;
102 params.phase = ms2lt(50);
103
104 SYSCALL( set_rt_task_param(gettid(), &params) );
105 SYSCALL( be_migrate_to(params.cpu) );
106 SYSCALL( task_mode(LITMUS_RT_TASK) );
107
108 SYSCALL( od = open_pcp_sem(fd, 0, cpu) );
109
110 SYSCALL( wait_for_ts_release() );
111
112 start = wctime();
113 /* block on semaphore */
114 SYSCALL( litmus_lock(od) );
115 SYSCALL( litmus_unlock(od) );
116 stop = wctime();
117
118 /* Assert we had some blocking. */
119 ASSERT( stop - start > 0.1);
120
121 /* Assert we woke up 'soonish' after the sleep. */
122 ASSERT( stop - start < 1 );
123
124 SYSCALL( kill(child_middle, SIGUSR2) );
125 SYSCALL( kill(child_lo, SIGUSR2) );
126 );
127
128 do {
129 waiters = get_nr_ts_release_waiters();
130 ASSERT( waiters >= 0 );
131 } while (waiters != 3);
132
133 SYSCALL( be_migrate_to(1) );
134
135 waiters = release_ts(&delay);
136
137 SYSCALL( waitpid(child_hi, &status, 0) );
138 ASSERT( status == 0 );
139
140 SYSCALL( waitpid(child_lo, &status, 0) );
141 ASSERT( status == SIGUSR2);
142
143 SYSCALL( waitpid(child_middle, &status, 0) );
144 ASSERT( status == SIGUSR2);
145}
146
147TESTCASE(srp_ceiling_blocking, P_FP | PSN_EDF,
148 "SRP ceiling blocking")
149{
150 int fd, od;
151
152 int child_hi, child_lo, child_middle, status, waiters;
153 lt_t delay = ms2lt(100);
154 double start, stop;
155
156 struct rt_task params;
157 params.cpu = 0;
158 params.exec_cost = ms2lt(10000);
159 params.period = ms2lt(100000);
160 params.relative_deadline = params.period;
161 params.phase = 0;
162 params.cls = RT_CLASS_HARD;
163 params.budget_policy = NO_ENFORCEMENT;
164
165 SYSCALL( fd = open(".srp_locks", O_RDONLY | O_CREAT, S_IRUSR) );
166
167
168 child_lo = FORK_TASK(
169 params.priority = LITMUS_LOWEST_PRIORITY;
170 params.phase = 0;
171 SYSCALL( set_rt_task_param(gettid(), &params) );
172 SYSCALL( be_migrate_to(params.cpu) );
173 SYSCALL( task_mode(LITMUS_RT_TASK) );
174
175 SYSCALL( od = open_srp_sem(fd, 0) );
176
177 SYSCALL( wait_for_ts_release() );
178
179 SYSCALL( litmus_lock(od) );
180 start = cputime();
181 while (cputime() - start < 0.25)
182 ;
183 SYSCALL( litmus_unlock(od) );
184 );
185
186 child_middle = FORK_TASK(
187 params.priority = LITMUS_HIGHEST_PRIORITY + 1;
188 params.phase = ms2lt(100);
189 params.relative_deadline -= ms2lt(110);
190
191 SYSCALL( set_rt_task_param(gettid(), &params) );
192 SYSCALL( be_migrate_to(params.cpu) );
193 SYSCALL( task_mode(LITMUS_RT_TASK) );
194
195
196 SYSCALL( wait_for_ts_release() );
197
198 start = cputime();
199 while (cputime() - start < 5)
200 ;
201 );
202
203 child_hi = FORK_TASK(
204 params.priority = LITMUS_HIGHEST_PRIORITY;
205 params.phase = ms2lt(50);
206 params.relative_deadline -= ms2lt(200);
207
208 SYSCALL( set_rt_task_param(gettid(), &params) );
209 SYSCALL( be_migrate_to(params.cpu) );
210 SYSCALL( task_mode(LITMUS_RT_TASK) );
211
212 SYSCALL( od = open_srp_sem(fd, 0) );
213
214 SYSCALL( wait_for_ts_release() );
215
216 start = wctime();
217 /* block on semaphore */
218 SYSCALL( litmus_lock(od) );
219 SYSCALL( litmus_unlock(od) );
220 stop = wctime();
221
222 /* Assert we had "no" blocking (modulo qemu overheads). */
223 ASSERT( stop - start < 0.01);
224
225 SYSCALL( kill(child_middle, SIGUSR2) );
226 SYSCALL( kill(child_lo, SIGUSR2) );
227 );
228
229 do {
230 waiters = get_nr_ts_release_waiters();
231 ASSERT( waiters >= 0 );
232 } while (waiters != 3);
233
234 SYSCALL( be_migrate_to(1) );
235
236 waiters = release_ts(&delay);
237
238 SYSCALL( waitpid(child_hi, &status, 0) );
239 ASSERT( status == 0 );
240
241 SYSCALL( waitpid(child_lo, &status, 0) );
242 ASSERT( status == SIGUSR2);
243
244 SYSCALL( waitpid(child_middle, &status, 0) );
245 ASSERT( status == SIGUSR2);
246}
247
40TESTCASE(lock_dpcp, P_FP, 248TESTCASE(lock_dpcp, P_FP,
41 "DPCP acquisition and release") 249 "DPCP acquisition and release")
42{ 250{
43 int fd, od, cpu = 1; 251 int fd, od, cpu = 1;
44 252
45 SYSCALL( fd = open(".pcp_locks", O_RDONLY | O_CREAT) ); 253 SYSCALL( fd = open(".pcp_locks", O_RDONLY | O_CREAT, S_IRUSR) );
46 254
47 SYSCALL( sporadic_partitioned(10, 100, 0) ); 255 SYSCALL( sporadic_partitioned(10, 100, 0) );
48 SYSCALL( task_mode(LITMUS_RT_TASK) ); 256 SYSCALL( task_mode(LITMUS_RT_TASK) );
@@ -73,7 +281,7 @@ TESTCASE(not_lock_pcp_be, P_FP,
73{ 281{
74 int fd, od; 282 int fd, od;
75 283
76 SYSCALL( fd = open(".pcp_locks", O_RDONLY | O_CREAT) ); 284 SYSCALL( fd = open(".pcp_locks", O_RDONLY | O_CREAT, S_IRUSR) );
77 285
78 /* BE tasks are not even allowed to open a PCP semaphore */ 286 /* BE tasks are not even allowed to open a PCP semaphore */
79 SYSCALL_FAILS(EPERM, od = open_pcp_sem(fd, 0, 1) ); 287 SYSCALL_FAILS(EPERM, od = open_pcp_sem(fd, 0, 1) );
@@ -95,7 +303,7 @@ TESTCASE(lock_mpcp, P_FP,
95{ 303{
96 int fd, od; 304 int fd, od;
97 305
98 SYSCALL( fd = open(".pcp_locks", O_RDONLY | O_CREAT) ); 306 SYSCALL( fd = open(".pcp_locks", O_RDONLY | O_CREAT, S_IRUSR) );
99 307
100 SYSCALL( sporadic_partitioned(10, 100, 0) ); 308 SYSCALL( sporadic_partitioned(10, 100, 0) );
101 SYSCALL( task_mode(LITMUS_RT_TASK) ); 309 SYSCALL( task_mode(LITMUS_RT_TASK) );