aboutsummaryrefslogtreecommitdiff
path: root/final/runtime/test/misc_bugs/omp_foreign_thread_team_reuse.c
diff options
context:
space:
mode:
Diffstat (limited to 'final/runtime/test/misc_bugs/omp_foreign_thread_team_reuse.c')
-rw-r--r--final/runtime/test/misc_bugs/omp_foreign_thread_team_reuse.c81
1 files changed, 81 insertions, 0 deletions
diff --git a/final/runtime/test/misc_bugs/omp_foreign_thread_team_reuse.c b/final/runtime/test/misc_bugs/omp_foreign_thread_team_reuse.c
new file mode 100644
index 0000000..4d70d47
--- /dev/null
+++ b/final/runtime/test/misc_bugs/omp_foreign_thread_team_reuse.c
@@ -0,0 +1,81 @@
+// RUN: %libomp-compile -lpthread && %libomp-run
+#include <stdio.h>
+#include "omp_testsuite.h"
+
+#define NUM_THREADS 10
+
+/*
+ After hot teams were enabled by default, the library started using levels
+ kept in the team structure. The levels are broken in case foreign thread
+ exits and puts its team into the pool which is then re-used by another foreign
+ thread. The broken behavior observed is when printing the levels for each
+ new team, one gets 1, 2, 1, 2, 1, 2, etc. This makes the library believe that
+ every other team is nested which is incorrect. What is wanted is for the
+ levels to be 1, 1, 1, etc.
+*/
+
+int a = 0;
+int level;
+
+typedef struct thread_arg_t {
+ int iterations;
+} thread_arg_t;
+
+void* thread_function(void* arg) {
+ int i;
+ thread_arg_t* targ = (thread_arg_t*)arg;
+ int iterations = targ->iterations;
+ #pragma omp parallel private(i)
+ {
+ // level should always be 1
+ #pragma omp single
+ level = omp_get_level();
+
+ #pragma omp for
+ for(i = 0; i < iterations; i++) {
+ #pragma omp atomic
+ a++;
+ }
+ }
+}
+
+int test_omp_team_reuse()
+{
+ int i;
+ int success = 1;
+ pthread_t thread[NUM_THREADS];
+ thread_arg_t thread_arg[NUM_THREADS];
+ // launch NUM_THREADS threads, one at a time to perform thread_function()
+ for(i = 0; i < NUM_THREADS; i++) {
+ thread_arg[i].iterations = i + 1;
+ pthread_create(thread+i, NULL, thread_function, thread_arg+i);
+ pthread_join(*(thread+i), NULL);
+ // level read in thread_function()'s parallel region should be 1
+ if(level != 1) {
+ fprintf(stderr, "error: for pthread %d level should be 1 but "
+ "instead equals %d\n", i, level);
+ success = 0;
+ }
+ }
+ // make sure the for loop works
+ int known_sum = (NUM_THREADS * (NUM_THREADS+1)) / 2;
+ if(a != known_sum) {
+ fprintf(stderr, "a should be %d but instead equals %d\n", known_sum, a);
+ success = 0;
+ }
+ return success;
+}
+
+int main()
+{
+ int i;
+ int num_failed=0;
+
+ for(i = 0; i < REPETITIONS; i++) {
+ a = 0;
+ if(!test_omp_team_reuse()) {
+ num_failed++;
+ }
+ }
+ return num_failed;
+}