1 // RUN: %libomp-compile && env KMP_ENABLE_TASK_THROTTLING=0 %libomp-run
2 // RUN: %libomp-compile && env KMP_ENABLE_TASK_THROTTLING=1 %libomp-run
3 
4 #include<omp.h>
5 #include<stdlib.h>
6 #include<string.h>
7 
8 /**
9  * Test the task throttling behavior of the runtime.
10  * Unless OMP_NUM_THREADS is 1, the master thread pushes tasks to its own tasks
11  * queue until either of the following happens:
12  *   - the task queue is full, and it starts serializing tasks
13  *   - all tasks have been pushed, and it can begin execution
14  * The idea is to create a huge number of tasks which execution are blocked
15  * until the master thread comes to execute tasks (they need to be blocking,
16  * otherwise the second thread will start emptying the queue).
17  * At this point we can check the number of enqueued tasks: iff all tasks have
18  * been enqueued, then there was no task throttling.
19  * Otherwise there has been some sort of task throttling.
20  * If what we detect doesn't match the value of the environment variable, the
21  * test is failed.
22  */
23 
24 
25 #define NUM_TASKS 2000
26 
27 
main()28 int main()
29 {
30   int i;
31   int block = 1;
32   int throttling = strcmp(getenv("KMP_ENABLE_TASK_THROTTLING"), "1") == 0;
33   int enqueued = 0;
34   int failed = -1;
35 
36   #pragma omp parallel num_threads(2)
37   #pragma omp master
38   {
39     for (i = 0; i < NUM_TASKS; i++) {
40       enqueued++;
41       #pragma omp task
42       {
43         int tid;
44         tid = omp_get_thread_num();
45         if (tid == 0) {
46           // As soon as the master thread starts executing task we should unlock
47           // all tasks, and detect the test failure if it has not been done yet.
48           if (failed < 0)
49             failed = throttling ? enqueued == NUM_TASKS : enqueued < NUM_TASKS;
50 #pragma omp atomic write
51           block = 0;
52         }
53         int wait = 0;
54         do {
55 #pragma omp atomic read
56           wait = block;
57         } while (wait);
58       }
59     }
60     block = 0;
61   }
62 
63   return failed;
64 }
65