|
Lines 41-47
static pthread_mutex_t race_mut;
|
Link Here
|
|---|
|
| 41 |
static pthread_cond_t sig1, sig2, sig3; |
41 |
static pthread_cond_t sig1, sig2, sig3; |
| 42 |
static pthread_mutex_t m1, m2, m3; |
42 |
static pthread_mutex_t m1, m2, m3; |
| 43 |
|
43 |
|
|
|
44 |
static pthread_barrier_t bar; |
| 45 |
|
| 44 |
static volatile unsigned int done = 0; |
46 |
static volatile unsigned int done = 0; |
|
|
47 |
static unsigned int test_result = 0; |
| 48 |
|
| 49 |
static void * |
| 50 |
watchdog_tf (void *p) |
| 51 |
{ |
| 52 |
int err; |
| 53 |
|
| 54 |
err = pthread_barrier_wait (&bar); |
| 55 |
if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD) |
| 56 |
error (EXIT_FAILURE, err, "watchdog_tf: barrier wait failed"); |
| 57 |
|
| 58 |
/* Allow time for high_tf to set done=1 indicating a successful run. If |
| 59 |
it is hung waiting on race_var, we set done=2 indicating failure. med_tf |
| 60 |
will detect the 2 and indicate a failure in test_result. */ |
| 61 |
usleep (1000); |
| 62 |
if (done != 1) |
| 63 |
{ |
| 64 |
usleep (500000); |
| 65 |
done = 2; |
| 66 |
} |
| 67 |
return NULL; |
| 68 |
} |
| 45 |
|
69 |
|
| 46 |
static void * |
70 |
static void * |
| 47 |
low_tf (void *p) |
71 |
low_tf (void *p) |
|
|
| 148 |
while (!done) |
172 |
while (!done) |
| 149 |
/* Busy wait to block low threads. */; |
173 |
/* Busy wait to block low threads. */; |
| 150 |
|
174 |
|
|
|
175 |
/* If watchdog_tf has set done to 2 before high_tf has set it to 1, |
| 176 |
then the test has failed. */ |
| 177 |
if (done == 2) |
| 178 |
{ |
| 179 |
puts ("med_tf: unbounded priority inversion detected."); |
| 180 |
|
| 181 |
/* low_tf and high_tf are now waiting on race_var, having missed |
| 182 |
the broadcast issued in do_test(). Wake them up now and exit |
| 183 |
gracefully. */ |
| 184 |
err = pthread_mutex_lock (&race_mut); |
| 185 |
if (err != 0) |
| 186 |
error (EXIT_FAILURE, err, "med_tf: failed to lock race_mut"); |
| 187 |
err = pthread_cond_broadcast (&race_var); |
| 188 |
if (err != 0) |
| 189 |
error (EXIT_FAILURE, err, "med_tf: broadcast to race_var failed"); |
| 190 |
err = pthread_mutex_unlock (&race_mut); |
| 191 |
if (err != 0) |
| 192 |
error (EXIT_FAILURE, err, "med_tf: failed to unlock race_mut"); |
| 193 |
|
| 194 |
test_result = 1; |
| 195 |
} |
| 196 |
|
| 151 |
puts ("med_tf: done spinning"); |
197 |
puts ("med_tf: done spinning"); |
| 152 |
|
198 |
|
| 153 |
return NULL; |
199 |
return NULL; |
|
|
| 159 |
pthread_t low_thread; |
205 |
pthread_t low_thread; |
| 160 |
pthread_t med_thread; |
206 |
pthread_t med_thread; |
| 161 |
pthread_t high_thread; |
207 |
pthread_t high_thread; |
|
|
208 |
pthread_t watchdog_thread; |
| 162 |
struct sched_param param; |
209 |
struct sched_param param; |
| 163 |
pthread_attr_t attr; |
210 |
pthread_attr_t attr; |
| 164 |
pthread_mutexattr_t m_attr; |
211 |
pthread_mutexattr_t m_attr; |
|
|
| 168 |
int err; |
215 |
int err; |
| 169 |
|
216 |
|
| 170 |
|
217 |
|
| 171 |
/* Initialize mutexes and condvars. */ |
218 |
/* Initialize barrier, mutexes, and condvars. */ |
|
|
219 |
err = pthread_barrier_init (&bar, NULL, 2); |
| 220 |
if (err != 0) |
| 221 |
error (EXIT_FAILURE, err, "parent: failed to init barrier"); |
| 172 |
|
222 |
|
| 173 |
err = pthread_attr_init (&attr); |
223 |
err = pthread_attr_init (&attr); |
| 174 |
if (err != 0) |
224 |
if (err != 0) |
|
|
| 232 |
if (err != 0) |
282 |
if (err != 0) |
| 233 |
error (EXIT_FAILURE, err, "parent: failed to set CPU affinity"); |
283 |
error (EXIT_FAILURE, err, "parent: failed to set CPU affinity"); |
| 234 |
|
284 |
|
|
|
285 |
err = pthread_create (&watchdog_thread, &attr, watchdog_tf, (void*)NULL); |
| 286 |
if (err != 0) |
| 287 |
error (EXIT_FAILURE, err, "parent: failed to create watchdog_tf"); |
| 288 |
|
| 235 |
param.sched_priority = LOW_PRIO; |
289 |
param.sched_priority = LOW_PRIO; |
| 236 |
err = pthread_attr_setschedparam (&attr, ¶m); |
290 |
err = pthread_attr_setschedparam (&attr, ¶m); |
| 237 |
if (err != 0) |
291 |
if (err != 0) |
|
|
| 266 |
PTHREAD_PRIO_INHERIT, low_tf will not have released the race_var cond_lock |
320 |
PTHREAD_PRIO_INHERIT, low_tf will not have released the race_var cond_lock |
| 267 |
and neither thread will have waited on race_var. */ |
321 |
and neither thread will have waited on race_var. */ |
| 268 |
usleep (1000); |
322 |
usleep (1000); |
|
|
323 |
|
| 324 |
err = pthread_barrier_wait (&bar); |
| 325 |
if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD) |
| 326 |
error (EXIT_FAILURE, err, "parent: barrier wait failed"); |
| 269 |
err = pthread_cond_broadcast (&race_var); |
327 |
err = pthread_cond_broadcast (&race_var); |
| 270 |
if (err != 0) |
328 |
if (err != 0) |
| 271 |
error (EXIT_FAILURE, err, "parent: failed to broadcast condition"); |
329 |
error (EXIT_FAILURE, err, "parent: failed to broadcast condition"); |
| 272 |
|
330 |
|
| 273 |
/* Wait for threads to complete. */ |
331 |
/* Wait for threads to complete. */ |
|
|
332 |
err = pthread_join (watchdog_thread, (void**) NULL); |
| 333 |
if (err != 0) |
| 334 |
error (EXIT_FAILURE, err, "join of watchdog_tf failed"); |
| 274 |
err = pthread_join (low_thread, (void**) NULL); |
335 |
err = pthread_join (low_thread, (void**) NULL); |
| 275 |
if (err != 0) |
336 |
if (err != 0) |
| 276 |
error (EXIT_FAILURE, err, "join of low_tf failed"); |
337 |
error (EXIT_FAILURE, err, "join of low_tf failed"); |
|
|
| 283 |
|
344 |
|
| 284 |
puts ("done"); |
345 |
puts ("done"); |
| 285 |
|
346 |
|
| 286 |
return 0; |
347 |
return test_result; |
| 287 |
} |
348 |
} |
| 288 |
|
349 |
|
| 289 |
|
350 |
|
| 290 |
- |
|
|