diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2013-01-10 17:48:39 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2013-01-10 17:48:39 -0500 |
commit | 629486d62ae22c33251d3c367af3febff5fe1e28 (patch) | |
tree | ef78fc8235c61f8ba37d109ea04266b6ce49b804 /gpu/locktest.c | |
parent | 1bf0f0094cd9671adfc07cf840bde67cd4cc0c38 (diff) |
Clean up GPU test code placement.
Diffstat (limited to 'gpu/locktest.c')
-rw-r--r-- | gpu/locktest.c | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/gpu/locktest.c b/gpu/locktest.c new file mode 100644 index 0000000..bc4fc54 --- /dev/null +++ b/gpu/locktest.c | |||
@@ -0,0 +1,206 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <stdint.h> | ||
4 | #include <unistd.h> | ||
5 | #include <assert.h> | ||
6 | #include <errno.h> | ||
7 | #include <sys/types.h> | ||
8 | #include <sys/stat.h> | ||
9 | #include <fcntl.h> | ||
10 | |||
11 | /* Include gettid() */ | ||
12 | #include <sys/types.h> | ||
13 | |||
14 | /* Include threading support. */ | ||
15 | #include <pthread.h> | ||
16 | |||
17 | /* Include the LITMUS^RT API.*/ | ||
18 | #include "litmus.h" | ||
19 | |||
20 | /* Catch errors. | ||
21 | */ | ||
22 | #define CALL( exp ) do { \ | ||
23 | int ret; \ | ||
24 | ret = exp; \ | ||
25 | if (ret != 0) \ | ||
26 | fprintf(stderr, "%s failed: %m\n", #exp);\ | ||
27 | else \ | ||
28 | fprintf(stderr, "%s ok.\n", #exp); \ | ||
29 | } while (0) | ||
30 | |||
31 | #define TH_CALL( exp ) do { \ | ||
32 | int ret; \ | ||
33 | ret = exp; \ | ||
34 | if (ret != 0) \ | ||
35 | fprintf(stderr, "[%d] %s failed: %m\n", ctx->id, #exp); \ | ||
36 | else \ | ||
37 | fprintf(stderr, "[%d] %s ok.\n", ctx->id, #exp); \ | ||
38 | } while (0) | ||
39 | |||
40 | #define TH_SAFE_CALL( exp ) do { \ | ||
41 | int ret; \ | ||
42 | fprintf(stderr, "[%d] calling %s...\n", ctx->id, #exp); \ | ||
43 | ret = exp; \ | ||
44 | if (ret != 0) \ | ||
45 | fprintf(stderr, "\t...[%d] %s failed: %m\n", ctx->id, #exp); \ | ||
46 | else \ | ||
47 | fprintf(stderr, "\t...[%d] %s ok.\n", ctx->id, #exp); \ | ||
48 | } while (0) | ||
49 | |||
50 | |||
51 | /* these are only default values */ | ||
52 | int NUM_THREADS=3; | ||
53 | int NUM_SEMS=10; | ||
54 | |||
55 | #define MAX_SEMS 1000 | ||
56 | |||
57 | #define EXEC_COST 10 | ||
58 | #define PERIOD 100 | ||
59 | |||
60 | /* The information passed to each thread. Could be anything. */ | ||
61 | struct thread_context { | ||
62 | int id; | ||
63 | int fd; | ||
64 | int od[MAX_SEMS]; | ||
65 | int count; | ||
66 | unsigned int rand; | ||
67 | }; | ||
68 | |||
69 | void* rt_thread(void* _ctx); | ||
70 | int nested_job(struct thread_context* ctx, int *count, int *next); | ||
71 | int job(struct thread_context*); | ||
72 | |||
73 | #define OPTSTR "t:s:" | ||
74 | |||
75 | int main(int argc, char** argv) | ||
76 | { | ||
77 | int i; | ||
78 | struct thread_context* ctx; | ||
79 | pthread_t* task; | ||
80 | int fd; | ||
81 | |||
82 | int opt; | ||
83 | while((opt = getopt(argc, argv, OPTSTR)) != -1) { | ||
84 | switch(opt) { | ||
85 | case 't': | ||
86 | NUM_THREADS = atoi(optarg); | ||
87 | break; | ||
88 | case 's': | ||
89 | NUM_SEMS = atoi(optarg); | ||
90 | assert(NUM_SEMS <= MAX_SEMS); | ||
91 | break; | ||
92 | default: | ||
93 | fprintf(stderr, "Unknown option: %c\n", opt); | ||
94 | exit(-1); | ||
95 | break; | ||
96 | } | ||
97 | } | ||
98 | |||
99 | ctx = (struct thread_context*) calloc(NUM_THREADS, sizeof(struct thread_context)); | ||
100 | task = (pthread_t*) calloc(NUM_THREADS, sizeof(pthread_t)); | ||
101 | |||
102 | srand(0); /* something repeatable for now */ | ||
103 | |||
104 | fd = open("semaphores", O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR); | ||
105 | |||
106 | CALL( init_litmus() ); | ||
107 | |||
108 | for (i = 0; i < NUM_THREADS; i++) { | ||
109 | ctx[i].id = i; | ||
110 | ctx[i].fd = fd; | ||
111 | ctx[i].rand = rand(); | ||
112 | CALL( pthread_create(task + i, NULL, rt_thread, ctx + i) ); | ||
113 | } | ||
114 | |||
115 | |||
116 | for (i = 0; i < NUM_THREADS; i++) | ||
117 | pthread_join(task[i], NULL); | ||
118 | |||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | void* rt_thread(void* _ctx) | ||
124 | { | ||
125 | int i; | ||
126 | int do_exit = 0; | ||
127 | |||
128 | struct thread_context *ctx = (struct thread_context*)_ctx; | ||
129 | |||
130 | TH_CALL( init_rt_thread() ); | ||
131 | |||
132 | /* Vary period a little bit. */ | ||
133 | TH_CALL( sporadic_global(EXEC_COST, PERIOD + 10*ctx->id) ); | ||
134 | |||
135 | for (i = 0; i < NUM_SEMS; i++) { | ||
136 | ctx->od[i] = open_fmlp_sem(ctx->fd, i); | ||
137 | if(ctx->od[i] < 0) | ||
138 | perror("open_fmlp_sem"); | ||
139 | } | ||
140 | |||
141 | TH_CALL( task_mode(LITMUS_RT_TASK) ); | ||
142 | |||
143 | |||
144 | printf("[%d] Waiting for TS release.\n ", ctx->id); | ||
145 | wait_for_ts_release(); | ||
146 | ctx->count = 0; | ||
147 | |||
148 | do { | ||
149 | int which_sem = (int)(NUM_SEMS * (rand_r(&(ctx->rand)) / (RAND_MAX + 1.0))); | ||
150 | |||
151 | printf("[%d]: trying to get semaphore %d.\n", ctx->id, which_sem); | ||
152 | fflush(stdout); | ||
153 | |||
154 | TH_SAFE_CALL ( litmus_lock(which_sem) ); | ||
155 | |||
156 | printf("[%d] got semaphore %d.\n", ctx->id, which_sem); | ||
157 | fflush(stdout); | ||
158 | |||
159 | do_exit = job(ctx); | ||
160 | |||
161 | printf("[%d]: freeing semaphore %d.\n", ctx->id, which_sem); | ||
162 | fflush(stdout); | ||
163 | |||
164 | TH_SAFE_CALL ( litmus_unlock(which_sem) ); | ||
165 | |||
166 | if(!do_exit) { | ||
167 | sleep_next_period(); | ||
168 | } | ||
169 | } while(!do_exit); | ||
170 | |||
171 | /***** | ||
172 | * 4) Transition to background mode. | ||
173 | */ | ||
174 | TH_CALL( task_mode(BACKGROUND_TASK) ); | ||
175 | |||
176 | |||
177 | return NULL; | ||
178 | } | ||
179 | |||
180 | void dirty_kb(int kb) | ||
181 | { | ||
182 | int32_t one_kb[256]; | ||
183 | int32_t sum = 0; | ||
184 | int32_t i; | ||
185 | |||
186 | for (i = 0; i < 256; i++) | ||
187 | sum += one_kb[i]; | ||
188 | kb--; | ||
189 | /* prevent tail recursion */ | ||
190 | if (kb) | ||
191 | dirty_kb(kb); | ||
192 | for (i = 0; i < 256; i++) | ||
193 | sum += one_kb[i]; | ||
194 | } | ||
195 | |||
196 | int job(struct thread_context* ctx) | ||
197 | { | ||
198 | /* Do real-time calculation. */ | ||
199 | dirty_kb(8); | ||
200 | |||
201 | /* Don't exit. */ | ||
202 | //return ctx->count++ > 100; | ||
203 | //return ctx->count++ > 12000; | ||
204 | //return ctx->count++ > 120000; | ||
205 | return ctx->count++ > 30000; // controls number of jobs per task | ||
206 | } | ||