// 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 assignment of chunks to threads. We use the nowait
* clause to increase the probability to get an error. */
/* First we allocate some more memory */
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;
}