105 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			105 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C
		
	
	
	
// RUN: %libomp-compile-and-run
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <omp.h>
 | 
						|
#include "omp_my_sleep.h"
 | 
						|
 | 
						|
int a = 0, b = 0;
 | 
						|
int task_grabbed = 0, task_can_proceed = 0;
 | 
						|
int task2_grabbed = 0, task2_can_proceed = 0;
 | 
						|
 | 
						|
static void wait_on_flag(int *flag) {
 | 
						|
  int flag_value;
 | 
						|
  int timelimit = 30;
 | 
						|
  int secs = 0;
 | 
						|
  do {
 | 
						|
    #pragma omp atomic read
 | 
						|
    flag_value = *flag;
 | 
						|
    my_sleep(1.0);
 | 
						|
    secs++;
 | 
						|
    if (secs == timelimit) {
 | 
						|
      fprintf(stderr, "error: timeout in wait_on_flag()\n");
 | 
						|
      exit(EXIT_FAILURE);
 | 
						|
    }
 | 
						|
  } while (flag_value == 0);
 | 
						|
}
 | 
						|
 | 
						|
static void signal_flag(int *flag) {
 | 
						|
  #pragma omp atomic
 | 
						|
  (*flag)++;
 | 
						|
}
 | 
						|
 | 
						|
int main(int argc, char** argv) {
 | 
						|
 | 
						|
  // Ensure two threads are running
 | 
						|
  int num_threads = omp_get_max_threads();
 | 
						|
  if (num_threads < 2)
 | 
						|
    omp_set_num_threads(2);
 | 
						|
 | 
						|
  #pragma omp parallel shared(a)
 | 
						|
  {
 | 
						|
    int a_value;
 | 
						|
    // Let us be extra safe here
 | 
						|
    if (omp_get_num_threads() > 1) {
 | 
						|
      #pragma omp single nowait
 | 
						|
      {
 | 
						|
        // Schedule independent child task that
 | 
						|
        // waits to be flagged after sebsequent taskwait depend()
 | 
						|
        #pragma omp task
 | 
						|
        {
 | 
						|
          signal_flag(&task_grabbed);
 | 
						|
          wait_on_flag(&task_can_proceed);
 | 
						|
        }
 | 
						|
        // Let another worker thread grab the task to execute
 | 
						|
        wait_on_flag(&task_grabbed);
 | 
						|
        // This should be ignored since the task above has
 | 
						|
        // no dependency information
 | 
						|
        #pragma omp task if(0) depend(inout: a)
 | 
						|
        {}
 | 
						|
        // Signal the independent task to proceed
 | 
						|
        signal_flag(&task_can_proceed);
 | 
						|
 | 
						|
        // Schedule child task with dependencies that taskwait does
 | 
						|
        // not care about
 | 
						|
        #pragma omp task depend(inout: b)
 | 
						|
        {
 | 
						|
          signal_flag(&task2_grabbed);
 | 
						|
          wait_on_flag(&task2_can_proceed);
 | 
						|
          #pragma omp atomic
 | 
						|
          b++;
 | 
						|
        }
 | 
						|
        // Let another worker thread grab the task to execute
 | 
						|
        wait_on_flag(&task2_grabbed);
 | 
						|
        // This should be ignored since the task above has
 | 
						|
        // dependency information on b instead of a
 | 
						|
        #pragma omp task if(0) depend(inout: a)
 | 
						|
        {}
 | 
						|
        // Signal the task to proceed
 | 
						|
        signal_flag(&task2_can_proceed);
 | 
						|
 | 
						|
        // Generate one child task for taskwait
 | 
						|
        #pragma omp task shared(a) depend(inout: a)
 | 
						|
        {
 | 
						|
          my_sleep(1.0);
 | 
						|
          #pragma omp atomic
 | 
						|
          a++;
 | 
						|
        }
 | 
						|
        #pragma omp task if(0) depend(inout: a)
 | 
						|
        {}
 | 
						|
 | 
						|
        #pragma omp atomic read
 | 
						|
        a_value = a;
 | 
						|
 | 
						|
        if (a_value != 1) {
 | 
						|
          fprintf(stderr, "error: dependent task was not executed before "
 | 
						|
                          "taskwait finished\n");
 | 
						|
          exit(EXIT_FAILURE);
 | 
						|
        }
 | 
						|
      } // #pragma omp single
 | 
						|
    } // if (num_threads > 1)
 | 
						|
  } // #pragma omp parallel
 | 
						|
 | 
						|
  return EXIT_SUCCESS;
 | 
						|
}
 |