1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3 * (C) 2008 by Argonne National Laboratory.
4 * See COPYRIGHT in top-level directory.
5 */
6
7 /*
8 * Uncomment this definition to disable the OPA library and instead use naive
9 * (non-atomic) operations. This should cause failures.
10 */
11 /*
12 #define OPA_TEST_NAIVE
13 */
14
15 #include "opa_test.h"
16
17 /*
18 * Uncomment these lines to disable only memory barriers, while leaving the rest
19 * of the OPA functions intact.
20 */
21 /*
22 #ifdef OPA_write_barrier
23 #undef OPA_write_barrier
24 #endif
25 #define OPA_write_barrier() ((void) 0)
26 #ifdef OPA_read_barrier
27 #undef OPA_read_barrier
28 #endif
29 #define OPA_read_barrier() ((void) 0)
30 #ifdef OPA_read_write_barrier
31 #undef OPA_read_write_barrier
32 #endif
33 #define OPA_read_write_barrier() ((void) 0)
34 */
35
36 /* Definitions for test_barriers_linear_array */
37 #define LINEAR_ARRAY_NITER 4000000
38 #define LINEAR_ARRAY_LEN 100
39 typedef struct {
40 OPA_int_t *shared_array;
41 int master_thread; /* Whether this is the master thread */
42 } linear_array_t;
43
44 /* Definitions for test_barriers_variables */
45 #define VARIABLES_NITER 4000000
46 #define VARIABLES_NVAR 10
47 typedef struct {
48 OPA_int_t *v_0;
49 OPA_int_t *v_1;
50 OPA_int_t *v_2;
51 OPA_int_t *v_3;
52 OPA_int_t *v_4;
53 OPA_int_t *v_5;
54 OPA_int_t *v_6;
55 OPA_int_t *v_7;
56 OPA_int_t *v_8;
57 OPA_int_t *v_9;
58 int master_thread; /* Whether this is the master thread */
59 } variables_t;
60
61 /* Definitions for test_barriers_scattered_array */
62 #define SCATTERED_ARRAY_SIZE 100000
63 #define SCATTERED_ARRAY_LOCS {254, 85920, 255, 35529, 75948, 75947, 253, 99999, 11111, 11112}
64
65
66 /*-------------------------------------------------------------------------
67 * Function: test_barriers_sanity
68 *
69 * Purpose: Essentially tests that memory barriers don't interfere with
70 * normal single threaded operations. If this fails then
71 * something is *very* wrong.
72 *
73 * Return: Success: 0
74 * Failure: 1
75 *
76 * Programmer: Neil Fortner
77 * Wednesday, April 1, 2009
78 *
79 * Modifications:
80 * goodell@, December 1, 2011: load-acquire/store-release sanity test
81 *
82 *-------------------------------------------------------------------------
83 */
test_barriers_sanity(void)84 static int test_barriers_sanity(void)
85 {
86 OPA_int_t a;
87 int b;
88 OPA_ptr_t op;
89 void *p;
90 struct {int i;} obj = {0xabcdef};
91
92 TESTING("memory barrier sanity", 0);
93
94 /* Store 0 in a and b */
95 OPA_store_int(&a, 0);
96 OPA_write_barrier();
97 b = 0;
98
99 OPA_read_write_barrier();
100
101 /* Add INT_MIN */
102 OPA_add_int(&a, INT_MIN);
103 OPA_read_write_barrier();
104 b += INT_MIN;
105
106 OPA_read_write_barrier();
107
108 /* Increment */
109 OPA_incr_int(&a);
110 OPA_read_write_barrier();
111 b++;
112
113 OPA_read_write_barrier();
114
115 /* Add INT_MAX */
116 OPA_add_int(&a, INT_MAX);
117 OPA_read_write_barrier();
118 b += INT_MAX;
119
120 OPA_read_write_barrier();
121
122 /* Decrement */
123 OPA_decr_int(&a);
124 OPA_read_write_barrier();
125 b--;
126
127 OPA_read_write_barrier();
128
129 /* Load the result, verify it is correct */
130 if(OPA_load_int(&a) != INT_MIN + 1 + INT_MAX - 1) TEST_ERROR;
131 OPA_read_barrier();
132 if(b != OPA_load_int(&a)) TEST_ERROR;
133
134 OPA_read_write_barrier();
135
136 /* Barriers are now the opposite of what they were before */
137
138 /* Store 0 in a */
139 OPA_store_int(&a, 0);
140 OPA_read_barrier();
141 b = 0;
142
143 /* Add INT_MAX */
144 OPA_add_int(&a, INT_MAX);
145 b += INT_MAX;
146
147 /* Decrement */
148 OPA_decr_int(&a);
149 b--;
150
151 /* Add INT_MIN */
152 OPA_add_int(&a, INT_MIN);
153 b += INT_MIN;
154
155 /* Increment */
156 OPA_incr_int(&a);
157 b++;
158
159 /* Load the result, verify it is correct */
160 if(OPA_load_int(&a) != INT_MAX - 1 + INT_MIN + 1) TEST_ERROR;
161 OPA_write_barrier();
162 if(b != OPA_load_int(&a)) TEST_ERROR;
163
164 /* now provide a quick sanity check that the load-acquire/store-release code
165 * works (as in, successfully compiles and runs single-threaded, no
166 * multithreading is checked here) */
167
168 OPA_store_int(&a, 5);
169 b = OPA_load_acquire_int(&a);
170 if (b != 5) TEST_ERROR;
171 OPA_store_release_int(&a, 0);
172 b = OPA_load_acquire_int(&a);
173 if (b != 0) TEST_ERROR;
174
175 OPA_store_ptr(&op, &obj);
176 p = OPA_load_acquire_ptr(&op);
177 if (p != &obj) TEST_ERROR;
178 OPA_store_release_ptr(&op, NULL);
179 p = OPA_load_acquire_ptr(&op);
180 if (p != NULL) TEST_ERROR;
181
182 PASSED();
183 return 0;
184
185 error:
186 return 1;
187 } /* end test_barriers_sanity() */
188
189
190 #if defined(OPA_HAVE_PTHREAD_H)
191 /*-------------------------------------------------------------------------
192 * Function: test_barriers_linear_array_write
193 *
194 * Purpose: Helper (write thread) routine for test_barriers_linear_array.
195 * Writes successive increments to the shared array with memory
196 * barriers between each increment.
197 *
198 * Return: NULL
199 *
200 * Programmer: Neil Fortner
201 * Wednesday, April 1, 2009
202 *
203 * Modifications:
204 *
205 *-------------------------------------------------------------------------
206 */
test_barriers_linear_array_write(void * _udata)207 static void *test_barriers_linear_array_write(void *_udata)
208 {
209 linear_array_t *udata = (linear_array_t *)_udata;
210 OPA_int_t *shared_array = udata->shared_array;
211 int niter = LINEAR_ARRAY_NITER / LINEAR_ARRAY_LEN
212 / iter_reduction[curr_test];
213 int i, j;
214
215 /* Main loop */
216 for(i=0; i<niter; i++)
217 for(j=0; j<LINEAR_ARRAY_LEN; j++) {
218 /* Increment the value in the array */
219 OPA_incr_int(&shared_array[j]);
220
221 /* Write barrier */
222 OPA_write_barrier();
223 } /* end for */
224
225 /* Exit */
226 if(udata->master_thread)
227 return(NULL);
228 else
229 pthread_exit(NULL);
230 } /* end test_barriers_linear_array_write() */
231
232
233 /*-------------------------------------------------------------------------
234 * Function: test_barriers_linear_array_read
235 *
236 * Purpose: Helper (read thread) routine for test_barriers_linear_array.
237 * Reads successive increments from the shared array in reverse
238 * order with memory barriers between each read.
239 *
240 * Return: Success: NULL
241 * Failure: non-NULL
242 *
243 * Programmer: Neil Fortner
244 * Wednesday, April 1, 2009
245 *
246 * Modifications:
247 *
248 *-------------------------------------------------------------------------
249 */
test_barriers_linear_array_read(void * _udata)250 static void *test_barriers_linear_array_read(void *_udata)
251 {
252 linear_array_t *udata = (linear_array_t *)_udata;
253 OPA_int_t *shared_array = udata->shared_array;
254 int read_buffer[LINEAR_ARRAY_LEN];
255 int niter = LINEAR_ARRAY_NITER / LINEAR_ARRAY_LEN
256 / iter_reduction[curr_test];
257 int nerrors = 0; /* Number of errors */
258 int i, j;
259
260 /* Main loop */
261 for(i=0; i<niter; i++) {
262 /* Load the values from the array into the read buffer in reverse
263 * order */
264 for(j = LINEAR_ARRAY_LEN - 1; j >= 0; j--) {
265 read_buffer[j] = OPA_load_int(&shared_array[j]);
266
267 /* Read barrier */
268 OPA_read_barrier();
269 } /* end for */
270
271 /* Verify that the values never increase when read back in forward
272 * order */
273 for(j=1; j<LINEAR_ARRAY_LEN; j++)
274 if(read_buffer[j-1] < read_buffer[j]) {
275 printf(" Unexpected load: %d is less than %d\n",
276 read_buffer[j-1], read_buffer[j]);
277 nerrors++;
278 } /* end if */
279 } /* end for */
280
281 /* Any non-NULL exit value indicates an error, we use (void *) 1 here */
282 if(udata->master_thread)
283 return(nerrors ? (void *) 1 : NULL);
284 else
285 pthread_exit(nerrors ? (void *) 1 : NULL);
286 } /* end test_barriers_linear_array_read() */
287 #endif /* OPA_HAVE_PTHREAD_H */
288
289
290 /*-------------------------------------------------------------------------
291 * Function: test_barriers_linear_array
292 *
293 * Purpose: Tests memory barriers using simultaneous reads and writes to
294 * a linear array. Launches nthreads threads split into read
295 * and write threads.
296 *
297 * Return: Success: 0
298 * Failure: 1
299 *
300 * Programmer: Neil Fortner
301 * Wednesday, April 1, 2009
302 *
303 * Modifications:
304 *
305 *-------------------------------------------------------------------------
306 */
test_barriers_linear_array(void)307 static int test_barriers_linear_array(void)
308 {
309 #if defined(OPA_HAVE_PTHREAD_H)
310 pthread_t *threads = NULL; /* Threads */
311 pthread_attr_t ptattr; /* Thread attributes */
312 linear_array_t *thread_data = NULL; /* User data structs for each thread */
313 static OPA_int_t shared_array[LINEAR_ARRAY_LEN]; /* Array to operate on */
314 void *ret; /* Thread return value */
315 unsigned nthreads = num_threads[curr_test];
316 int nerrors = 0; /* number of errors */
317 int i;
318
319 TESTING("memory barriers with linear array", nthreads);
320
321 /* Allocate array of threads */
322 if(NULL == (threads = (pthread_t *) malloc(nthreads * sizeof(pthread_t))))
323 TEST_ERROR;
324
325 /* Allocate array of thread data */
326 if(NULL == (thread_data = (linear_array_t *) calloc(nthreads,
327 sizeof(linear_array_t)))) TEST_ERROR;
328
329 /* Set threads to be joinable */
330 pthread_attr_init(&ptattr);
331 pthread_attr_setdetachstate(&ptattr, PTHREAD_CREATE_JOINABLE);
332
333 /* Initialize shared array */
334 for(i=0; i<LINEAR_ARRAY_LEN; i++)
335 OPA_store_int(&shared_array[i], 0);
336
337 /* Initialize thread data structs */
338 for(i=0; i<nthreads; i++)
339 thread_data[i].shared_array = shared_array;
340 thread_data[nthreads-1].master_thread = 1;
341
342 /* Create the threads. */
343 for(i=0; i<(nthreads - 1); i++) {
344 if(pthread_create(&threads[i], &ptattr, test_barriers_linear_array_write,
345 &thread_data[i])) TEST_ERROR;
346 if(++i < (nthreads - 1))
347 if(pthread_create(&threads[i], &ptattr, test_barriers_linear_array_read,
348 &thread_data[i])) TEST_ERROR;
349 } /* end for */
350 if(nthreads % 2) {
351 if(test_barriers_linear_array_write(&thread_data[(nthreads - 1)]))
352 nerrors++;
353 } else
354 if(test_barriers_linear_array_read(&thread_data[(nthreads - 1)]))
355 nerrors++;
356
357 /* Free the attribute */
358 if(pthread_attr_destroy(&ptattr)) TEST_ERROR;
359
360 /* Join the threads */
361 for (i=0; i<(nthreads - 1); i++) {
362 if(pthread_join(threads[i], &ret)) TEST_ERROR;
363 if(ret)
364 nerrors++;
365 } /* end for */
366
367 /* Check for errors */
368 if(nerrors)
369 FAIL_OP_ERROR(printf(" Unexpected return from %d thread%s\n", nerrors,
370 nerrors == 1 ? "" : "s"));
371
372 /* Free memory */
373 free(threads);
374
375 PASSED();
376
377 #else /* OPA_HAVE_PTHREAD_H */
378 TESTING("memory barriers with linear array", 0);
379 SKIPPED();
380 puts(" pthread.h not available");
381 #endif /* OPA_HAVE_PTHREAD_H */
382
383 return 0;
384
385 #if defined(OPA_HAVE_PTHREAD_H)
386 error:
387 if(threads) free(threads);
388 return 1;
389 #endif /* OPA_HAVE_PTHREAD_H */
390 } /* end test_barriers_linear_array() */
391
392
393 #if defined(OPA_HAVE_PTHREAD_H)
394 /*-------------------------------------------------------------------------
395 * Function: test_barriers_variables_write
396 *
397 * Purpose: Helper (write thread) routine for test_barriers_variables.
398 * Writes successive increments to the shared variables with
399 * memory barriers between each increment.
400 *
401 * Return: NULL
402 *
403 * Programmer: Neil Fortner
404 * Wednesday, April 1, 2009
405 *
406 * Modifications:
407 *
408 *-------------------------------------------------------------------------
409 */
test_barriers_variables_write(void * _udata)410 static void *test_barriers_variables_write(void *_udata)
411 {
412 variables_t *udata = (variables_t *)_udata;
413 OPA_int_t *v_0, *v_1, *v_2, *v_3, *v_4, *v_5, *v_6, *v_7, *v_8, *v_9;
414 int niter = VARIABLES_NITER / VARIABLES_NVAR
415 / iter_reduction[curr_test];
416 int i;
417
418 /* Make local copies of the pointers in udata, to maximize the chance of the
419 * compiler reordering instructions (if the barriers don't work) */
420 v_0 = udata->v_0;
421 v_1 = udata->v_1;
422 v_2 = udata->v_2;
423 v_3 = udata->v_3;
424 v_4 = udata->v_4;
425 v_5 = udata->v_5;
426 v_6 = udata->v_6;
427 v_7 = udata->v_7;
428 v_8 = udata->v_8;
429 v_9 = udata->v_9;
430
431 /* Main loop */
432 for(i=0; i<niter; i++) {
433 /* Incrememnt the variables in forward order */
434 OPA_incr_int(v_0);
435 OPA_write_barrier();
436 OPA_incr_int(v_1);
437 OPA_write_barrier();
438 OPA_incr_int(v_2);
439 OPA_write_barrier();
440 OPA_incr_int(v_3);
441 OPA_write_barrier();
442 OPA_incr_int(v_4);
443 OPA_write_barrier();
444 OPA_incr_int(v_5);
445 OPA_write_barrier();
446 OPA_incr_int(v_6);
447 OPA_write_barrier();
448 OPA_incr_int(v_7);
449 OPA_write_barrier();
450 OPA_incr_int(v_8);
451 OPA_write_barrier();
452 OPA_incr_int(v_9);
453 OPA_write_barrier();
454 } /* end for */
455
456 /* Exit */
457 if(udata->master_thread)
458 return(NULL);
459 else
460 pthread_exit(NULL);
461 } /* end test_barriers_variables_write() */
462
463
464 /*-------------------------------------------------------------------------
465 * Function: test_barriers_variables_read
466 *
467 * Purpose: Helper (read thread) routine for test_barriers_variables.
468 * Reads successive increments from the variables in reverse
469 * order with memory barriers between each read.
470 *
471 * Return: Success: NULL
472 * Failure: non-NULL
473 *
474 * Programmer: Neil Fortner
475 * Wednesday, April 1, 2009
476 *
477 * Modifications:
478 *
479 *-------------------------------------------------------------------------
480 */
test_barriers_variables_read(void * _udata)481 static void *test_barriers_variables_read(void *_udata)
482 {
483 variables_t *udata = (variables_t *)_udata;
484 OPA_int_t *v_0, *v_1, *v_2, *v_3, *v_4, *v_5, *v_6, *v_7, *v_8, *v_9;
485 int read_buffer[VARIABLES_NVAR];
486 int niter = VARIABLES_NITER / VARIABLES_NVAR
487 / iter_reduction[curr_test];
488 int nerrors = 0; /* Number of errors */
489 int i, j;
490
491 /* Make local copies of the pointers in udata, to maximize the chance of the
492 * compiler reordering instructions (if the barriers don't work) */
493 v_0 = udata->v_0;
494 v_1 = udata->v_1;
495 v_2 = udata->v_2;
496 v_3 = udata->v_3;
497 v_4 = udata->v_4;
498 v_5 = udata->v_5;
499 v_6 = udata->v_6;
500 v_7 = udata->v_7;
501 v_8 = udata->v_8;
502 v_9 = udata->v_9;
503
504 /* Main loop */
505 for(i=0; i<niter; i++) {
506 /* Load the values from the array into the read buffer in reverse
507 * order*/
508 read_buffer[9] = OPA_load_int(v_9);
509 OPA_read_barrier();
510 read_buffer[8] = OPA_load_int(v_8);
511 OPA_read_barrier();
512 read_buffer[7] = OPA_load_int(v_7);
513 OPA_read_barrier();
514 read_buffer[6] = OPA_load_int(v_6);
515 OPA_read_barrier();
516 read_buffer[5] = OPA_load_int(v_5);
517 OPA_read_barrier();
518 read_buffer[4] = OPA_load_int(v_4);
519 OPA_read_barrier();
520 read_buffer[3] = OPA_load_int(v_3);
521 OPA_read_barrier();
522 read_buffer[2] = OPA_load_int(v_2);
523 OPA_read_barrier();
524 read_buffer[1] = OPA_load_int(v_1);
525 OPA_read_barrier();
526 read_buffer[0] = OPA_load_int(v_0);
527 OPA_read_barrier();
528
529 /* Verify that the values never increase when read back in forward
530 * order */
531 for(j=1; j<VARIABLES_NVAR; j++)
532 if(read_buffer[j-1] < read_buffer[j]) {
533 printf(" Unexpected load: %d is less than %d\n",
534 read_buffer[j-1], read_buffer[j]);
535 nerrors++;
536 } /* end if */
537 } /* end for */
538
539 /* Any non-NULL exit value indicates an error, we use (void *) 1 here */
540 if(udata->master_thread)
541 return(nerrors ? (void *) 1 : NULL);
542 else
543 pthread_exit(nerrors ? (void *) 1 : NULL);
544 } /* end test_barriers_variables_read() */
545 #endif /* OPA_HAVE_PTHREAD_H */
546
547
548 /*-------------------------------------------------------------------------
549 * Function: test_barriers_variables
550 *
551 * Purpose: Tests memory barriers using simultaneous reads and writes to
552 * a linear array. Launches nthreads threads split into read
553 * and write threads.
554 *
555 * Return: Success: 0
556 * Failure: 1
557 *
558 * Programmer: Neil Fortner
559 * Wednesday, April 1, 2009
560 *
561 * Modifications:
562 *
563 *-------------------------------------------------------------------------
564 */
test_barriers_variables(void)565 static int test_barriers_variables(void)
566 {
567 #if defined(OPA_HAVE_PTHREAD_H)
568 pthread_t *threads = NULL; /* Threads */
569 pthread_attr_t ptattr; /* Thread attributes */
570 variables_t *thread_data = NULL; /* User data structs for each thread */
571 OPA_int_t v_0, v_1, v_2, v_3, v_4, v_5, v_6, v_7, v_8, v_9;
572 void *ret; /* Thread return value */
573 unsigned nthreads = num_threads[curr_test];
574 int nerrors = 0; /* number of errors */
575 int i;
576
577 TESTING("memory barriers with local variables", nthreads);
578
579 /* Allocate array of threads */
580 if(NULL == (threads = (pthread_t *) malloc(nthreads * sizeof(pthread_t))))
581 TEST_ERROR;
582
583 /* Allocate array of thread data */
584 if(NULL == (thread_data = (variables_t *) calloc(nthreads,
585 sizeof(variables_t)))) TEST_ERROR;
586
587 /* Set threads to be joinable */
588 pthread_attr_init(&ptattr);
589 pthread_attr_setdetachstate(&ptattr, PTHREAD_CREATE_JOINABLE);
590
591 /* Initialize shared variables */
592 OPA_store_int(&v_0, 0);
593 OPA_store_int(&v_1, 0);
594 OPA_store_int(&v_2, 0);
595 OPA_store_int(&v_3, 0);
596 OPA_store_int(&v_4, 0);
597 OPA_store_int(&v_5, 0);
598 OPA_store_int(&v_6, 0);
599 OPA_store_int(&v_7, 0);
600 OPA_store_int(&v_8, 0);
601 OPA_store_int(&v_9, 0);
602
603 /* Initialize thread data structs */
604 for(i=0; i<nthreads; i++) {
605 thread_data[i].v_0 = &v_0;
606 thread_data[i].v_1 = &v_1;
607 thread_data[i].v_2 = &v_2;
608 thread_data[i].v_3 = &v_3;
609 thread_data[i].v_4 = &v_4;
610 thread_data[i].v_5 = &v_5;
611 thread_data[i].v_6 = &v_6;
612 thread_data[i].v_7 = &v_7;
613 thread_data[i].v_8 = &v_8;
614 thread_data[i].v_9 = &v_9;
615 } /* end for */
616 thread_data[nthreads-1].master_thread = 1;
617
618 /* Create the threads. */
619 for(i=0; i<(nthreads - 1); i++) {
620 if(pthread_create(&threads[i], &ptattr, test_barriers_variables_write,
621 &thread_data[i])) TEST_ERROR;
622 if(++i < (nthreads - 1))
623 if(pthread_create(&threads[i], &ptattr, test_barriers_variables_read,
624 &thread_data[i])) TEST_ERROR;
625 } /* end for */
626 if(nthreads % 2) {
627 if(test_barriers_variables_write(&thread_data[(nthreads - 1)]))
628 nerrors++;
629 } else
630 if(test_barriers_variables_read(&thread_data[(nthreads - 1)]))
631 nerrors++;
632
633 /* Free the attribute */
634 if(pthread_attr_destroy(&ptattr)) TEST_ERROR;
635
636 /* Join the threads */
637 for (i=0; i<(nthreads - 1); i++) {
638 if(pthread_join(threads[i], &ret)) TEST_ERROR;
639 if(ret)
640 nerrors++;
641 } /* end for */
642
643 /* Check for errors */
644 if(nerrors)
645 FAIL_OP_ERROR(printf(" Unexpected return from %d thread%s\n", nerrors,
646 nerrors == 1 ? "" : "s"));
647
648 /* Free memory */
649 free(threads);
650
651 PASSED();
652
653 #else /* OPA_HAVE_PTHREAD_H */
654 TESTING("memory barriers with local variables", 0);
655 SKIPPED();
656 puts(" pthread.h not available");
657 #endif /* OPA_HAVE_PTHREAD_H */
658
659 return 0;
660
661 #if defined(OPA_HAVE_PTHREAD_H)
662 error:
663 if(threads) free(threads);
664 return 1;
665 #endif /* OPA_HAVE_PTHREAD_H */
666 } /* end test_barriers_variables() */
667
668
669 /*-------------------------------------------------------------------------
670 * Function: test_barriers_scattered_array
671 *
672 * Purpose: Tests memory barriers using simultaneous reads and writes to
673 * locations scattered in an array. Launches nthreads threads
674 * split into read and write threads.
675 *
676 * Return: Success: 0
677 * Failure: 1
678 *
679 * Programmer: Neil Fortner
680 * Wednesday, April 1, 2009
681 *
682 * Modifications:
683 *
684 *-------------------------------------------------------------------------
685 */
test_barriers_scattered_array(void)686 static int test_barriers_scattered_array(void)
687 {
688 #if defined(OPA_HAVE_PTHREAD_H)
689 pthread_t *threads = NULL; /* Threads */
690 pthread_attr_t ptattr; /* Thread attributes */
691 variables_t *thread_data = NULL; /* User data structs for each thread */
692 static OPA_int_t shared_array[SCATTERED_ARRAY_SIZE];
693 int shared_locs[VARIABLES_NVAR] = SCATTERED_ARRAY_LOCS;
694 void *ret; /* Thread return value */
695 unsigned nthreads = num_threads[curr_test];
696 int nerrors = 0; /* number of errors */
697 int i;
698
699 TESTING("memory barriers with scattered array", nthreads);
700
701 /* Allocate array of threads */
702 if(NULL == (threads = (pthread_t *) malloc(nthreads * sizeof(pthread_t))))
703 TEST_ERROR;
704
705 /* Allocate array of thread data */
706 if(NULL == (thread_data = (variables_t *) calloc(nthreads,
707 sizeof(variables_t)))) TEST_ERROR;
708
709 /* Set threads to be joinable */
710 pthread_attr_init(&ptattr);
711 pthread_attr_setdetachstate(&ptattr, PTHREAD_CREATE_JOINABLE);
712
713 /* Initialize shared variables */
714 for(i=0; i<VARIABLES_NVAR; i++)
715 OPA_store_int(&shared_array[shared_locs[i]], 0);
716
717 /* Initialize thread data structs */
718 for(i=0; i<nthreads; i++) {
719 thread_data[i].v_0 = &shared_array[shared_locs[0]];
720 thread_data[i].v_1 = &shared_array[shared_locs[1]];
721 thread_data[i].v_2 = &shared_array[shared_locs[2]];
722 thread_data[i].v_3 = &shared_array[shared_locs[3]];
723 thread_data[i].v_4 = &shared_array[shared_locs[4]];
724 thread_data[i].v_5 = &shared_array[shared_locs[5]];
725 thread_data[i].v_6 = &shared_array[shared_locs[6]];
726 thread_data[i].v_7 = &shared_array[shared_locs[7]];
727 thread_data[i].v_8 = &shared_array[shared_locs[8]];
728 thread_data[i].v_9 = &shared_array[shared_locs[9]];
729 } /* end for */
730 thread_data[nthreads-1].master_thread = 1;
731
732 /* Create the threads. We will use the helper routines for
733 * test_barriers_variables. */
734 for(i=0; i<(nthreads - 1); i++) {
735 if(pthread_create(&threads[i], &ptattr, test_barriers_variables_write,
736 &thread_data[i])) TEST_ERROR;
737 if(++i < (nthreads - 1))
738 if(pthread_create(&threads[i], &ptattr, test_barriers_variables_read,
739 &thread_data[i])) TEST_ERROR;
740 } /* end for */
741 if(nthreads % 2) {
742 if(test_barriers_variables_write(&thread_data[(nthreads - 1)]))
743 nerrors++;
744 } else
745 if(test_barriers_variables_read(&thread_data[(nthreads - 1)]))
746 nerrors++;
747
748 /* Free the attribute */
749 if(pthread_attr_destroy(&ptattr)) TEST_ERROR;
750
751 /* Join the threads */
752 for (i=0; i<(nthreads - 1); i++) {
753 if(pthread_join(threads[i], &ret)) TEST_ERROR;
754 if(ret)
755 nerrors++;
756 } /* end for */
757
758 /* Check for errors */
759 if(nerrors)
760 FAIL_OP_ERROR(printf(" Unexpected return from %d thread%s\n", nerrors,
761 nerrors == 1 ? "" : "s"));
762
763 /* Free memory */
764 free(threads);
765
766 PASSED();
767
768 #else /* OPA_HAVE_PTHREAD_H */
769 TESTING("memory barriers with scattered array", 0);
770 SKIPPED();
771 puts(" pthread.h not available");
772 #endif /* OPA_HAVE_PTHREAD_H */
773
774 return 0;
775
776 #if defined(OPA_HAVE_PTHREAD_H)
777 error:
778 if(threads) free(threads);
779 return 1;
780 #endif /* OPA_HAVE_PTHREAD_H */
781 } /* end test_barriers_scattered_array() */
782
783
784 /*-------------------------------------------------------------------------
785 * Function: main
786 *
787 * Purpose: Tests the opa memory barriers
788 *
789 * Return: Success: exit(0)
790 *
791 * Failure: exit(1)
792 *
793 * Programmer: Neil Fortner
794 * Wednesday, April 1, 2009
795 *
796 * Modifications:
797 *
798 *-------------------------------------------------------------------------
799 */
main(int argc,char ** argv)800 int main(int argc, char **argv)
801 {
802 unsigned nerrors = 0;
803 #if defined(OPA_USE_LOCK_BASED_PRIMITIVES)
804 OPA_emulation_ipl_t shm_lock;
805 OPA_Interprocess_lock_init(&shm_lock, 1/*isLeader*/);
806 #endif
807
808 /* Simple tests */
809 nerrors += test_barriers_sanity();
810
811 /* Loop over test configurations */
812 for(curr_test=0; curr_test<num_thread_tests; curr_test++) {
813 /* Don't test with only 1 thread */
814 if(num_threads[curr_test] == 1)
815 continue;
816
817 /* Threaded tests */
818 nerrors += test_barriers_linear_array();
819 nerrors += test_barriers_variables();
820 nerrors += test_barriers_scattered_array();
821 } /* end for */
822
823 if(nerrors)
824 goto error;
825 printf("All barriers tests passed.\n");
826
827 return 0;
828
829 error:
830 if(!nerrors)
831 nerrors = 1;
832 printf("***** %d BARRIERS TEST%s FAILED! *****\n",
833 nerrors, 1 == nerrors ? "" : "S");
834 return 1;
835 } /* end main() */
836
837