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