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 Churbanovint 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