| // RUN: %libomp-compile-and-run |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include "omp_testsuite.h" |
| #include "omp_my_sleep.h" |
| |
| #define CFSMAX_SIZE 1000 |
| #define MAX_TIME 0.01 |
| |
| #ifdef SLEEPTIME |
| #undef SLEEPTIME |
| #define SLEEPTIME 0.0005 |
| #endif |
| |
| #define VERBOSE 0 |
| |
| int test_omp_for_schedule_static_3() |
| { |
| int threads; |
| int i,lasttid; |
| |
| int * tids; |
| int * tids2; |
| int notout; |
| int maxiter; |
| int chunk_size; |
| |
| int counter = 0; |
| int tmp_count=1; |
| int lastthreadsstarttid = -1; |
| int result = 1; |
| chunk_size = 7; |
| |
| tids = (int *) malloc (sizeof (int) * (CFSMAX_SIZE + 1)); |
| notout = 1; |
| maxiter = 0; |
| |
| #pragma omp parallel shared(tids,counter) |
| { /* begin of parallel*/ |
| #pragma omp single |
| { |
| threads = omp_get_num_threads (); |
| } /* end of single */ |
| } /* end of parallel */ |
| |
| /* Ensure that at least two threads are created */ |
| if (threads < 2) { |
| omp_set_num_threads(2); |
| threads = 2; |
| } |
| fprintf (stderr,"Using an internal count of %d\nUsing a" |
| " specified chunksize of %d\n", CFSMAX_SIZE, chunk_size); |
| tids[CFSMAX_SIZE] = -1; /* setting endflag */ |
| |
| #pragma omp parallel shared(tids) |
| { /* begin of parallel */ |
| double count; |
| int tid; |
| int j; |
| |
| tid = omp_get_thread_num (); |
| |
| #pragma omp for nowait schedule(static,chunk_size) |
| for(j = 0; j < CFSMAX_SIZE; ++j) { |
| count = 0.; |
| #pragma omp flush(maxiter) |
| if (j > maxiter) { |
| #pragma omp critical |
| { |
| maxiter = j; |
| } |
| } |
| /*printf ("thread %d sleeping\n", tid);*/ |
| while (notout && (count < MAX_TIME) && (maxiter == j)) { |
| #pragma omp flush(maxiter,notout) |
| my_sleep (SLEEPTIME); |
| count += SLEEPTIME; |
| printf("."); |
| } |
| #ifdef VERBOSE |
| if (count > 0.) printf(" waited %lf s\n", count); |
| #endif |
| /*printf ("thread %d awake\n", tid);*/ |
| tids[j] = tid; |
| #ifdef VERBOSE |
| printf("%d finished by %d\n",j,tid); |
| #endif |
| } /* end of omp parallel for */ |
| |
| notout = 0; |
| #pragma omp flush(maxiter,notout) |
| } /* end of parallel */ |
| |
| /**** analysing the data in array tids ****/ |
| |
| lasttid = tids[0]; |
| tmp_count = 0; |
| |
| for (i = 0; i < CFSMAX_SIZE + 1; ++i) { |
| /* If the work was done by the same thread |
| increase tmp_count by one. */ |
| if (tids[i] == lasttid) { |
| tmp_count++; |
| #ifdef VERBOSE |
| fprintf (stderr, "%d: %d \n", i, tids[i]); |
| #endif |
| continue; |
| } |
| |
| /* Check if the next thread had has the right thread number. |
| * When finding threadnumber -1 the end should be reached. |
| */ |
| if (tids[i] == (lasttid + 1) % threads || tids[i] == -1) { |
| /* checking for the right chunk size */ |
| if (tmp_count == chunk_size) { |
| tmp_count = 1; |
| lasttid = tids[i]; |
| #ifdef VERBOSE |
| fprintf (stderr, "OK\n"); |
| #endif |
| } else { |
| /* If the chunk size was wrong, check if the end was reached */ |
| if (tids[i] == -1) { |
| if (i == CFSMAX_SIZE) { |
| fprintf (stderr, "Last thread had chunk size %d\n", |
| tmp_count); |
| break; |
| } else { |
| fprintf (stderr, "ERROR: Last thread (thread with" |
| " number -1) was found before the end.\n"); |
| result = 0; |
| } |
| } else { |
| fprintf (stderr, "ERROR: chunk size was %d. (assigned" |
| " was %d)\n", tmp_count, chunk_size); |
| result = 0; |
| } |
| } |
| } else { |
| fprintf(stderr, "ERROR: Found thread with number %d (should be" |
| " inbetween 0 and %d).", tids[i], threads - 1); |
| result = 0; |
| } |
| #ifdef VERBOSE |
| fprintf (stderr, "%d: %d \n", i, tids[i]); |
| #endif |
| } |
| |
| /* Now we check if several loop regions in one parallel region have the |
| * same logical assignement of chunks to threads. We use the nowait |
| * clause to increase the probability to get an error. */ |
| |
| /* First we allocate some more memmory */ |
| free (tids); |
| tids = (int *) malloc (sizeof (int) * LOOPCOUNT); |
| tids2 = (int *) malloc (sizeof (int) * LOOPCOUNT); |
| |
| #pragma omp parallel |
| { |
| { |
| int n; |
| #pragma omp for schedule(static) nowait |
| for (n = 0; n < LOOPCOUNT; n++) { |
| if (LOOPCOUNT == n + 1 ) |
| my_sleep(SLEEPTIME); |
| |
| tids[n] = omp_get_thread_num(); |
| } |
| } |
| { |
| int m; |
| #pragma omp for schedule(static) nowait |
| for (m = 1; m <= LOOPCOUNT; m++) { |
| tids2[m-1] = omp_get_thread_num(); |
| } |
| } |
| } |
| |
| for (i = 0; i < LOOPCOUNT; i++) |
| if (tids[i] != tids2[i]) { |
| fprintf (stderr, "Chunk no. %d was assigned once to thread %d and" |
| " later to thread %d.\n", i, tids[i],tids2[i]); |
| result = 0; |
| } |
| |
| free (tids); |
| free (tids2); |
| return result; |
| } |
| |
| int main() |
| { |
| int i; |
| int num_failed=0; |
| |
| for (i = 0; i < REPETITIONS; i++) { |
| if(!test_omp_for_schedule_static_3()) { |
| num_failed++; |
| } |
| } |
| return num_failed; |
| } |