// RUN: %libomp-compile && env OMP_MAX_TASK_PRIORITY='2' %libomp-run
// Test OMP 4.5 task priorities
// Higher priority task supposed to be executed before lower priority task.
#include <stdio.h>
#include <omp.h>
#include "omp_my_sleep.h"
// delay(n) - sleep n ms
#define delay(n) my_sleep(((double)n)/1000.0)
int main ( void ) {
int passed;
passed = (omp_get_max_task_priority() == 2);
printf("Got %d max priority via env\n", omp_get_max_task_priority());
if(!passed) {
printf( "failed\n" );
return 1;
}
printf("parallel 1 spawns 4 tasks for primary thread to execute\n");
#pragma omp parallel num_threads(2)
{
int th = omp_get_thread_num();
if (th == 0) // primary thread
{
#pragma omp task priority(1)
{ // middle priority
int val, t = omp_get_thread_num();
#pragma omp atomic capture
val = passed++;
printf("P1: val = %d, thread gen %d, thread exe %d\n", val, th, t);
delay(10); // sleep 10 ms
}
#pragma omp task priority(2)
{ // high priority
int val, t = omp_get_thread_num();
#pragma omp atomic capture
val = passed++;
printf("P2: val = %d, thread gen %d, thread exe %d\n", val, th, t);
delay(20); // sleep 20 ms
}
#pragma omp task priority(0)
{ // low priority specified explicitly
int val, t = omp_get_thread_num();
#pragma omp atomic capture
val = passed++;
printf("P0exp: val = %d, thread gen %d, thread exe %d\n", val, th, t);
delay(1); // sleep 1 ms
}
#pragma omp task
{ // low priority by default
int val, t = omp_get_thread_num();
#pragma omp atomic capture
val = passed++;
printf("P0imp: val = %d, thread gen %d, thread exe %d\n", val, th, t);
delay(1); // sleep 1 ms
}
} else {
// wait for the primary thread to finish all tasks
int wait = 0;
do {
delay(5);
#pragma omp atomic read
wait = passed;
} while (wait < 5);
}
}
printf("parallel 2 spawns 4 tasks for worker thread to execute\n");
#pragma omp parallel num_threads(2)
{
int th = omp_get_thread_num();
if (th == 0) // primary thread
{
#pragma omp task priority(1)
{ // middle priority
int val, t = omp_get_thread_num();
#pragma omp atomic capture
val = passed++;
printf("P1: val = %d, thread gen %d, thread exe %d\n", val, th, t);
delay(10); // sleep 10 ms
}
#pragma omp task priority(2)
{ // high priority
int val, t = omp_get_thread_num();
#pragma omp atomic capture
val = passed++;
printf("P2: val = %d, thread gen %d, thread exe %d\n", val, th, t);
delay(20); // sleep 20 ms
}
#pragma omp task priority(0)
{ // low priority specified explicitly
int val, t = omp_get_thread_num();
#pragma omp atomic capture
val = passed++;
printf("P0exp: val = %d, thread gen %d, thread exe %d\n", val, th, t);
delay(1); // sleep 1 ms
}
#pragma omp task
{ // low priority by default
int val, t = omp_get_thread_num();
#pragma omp atomic capture
val = passed++;
printf("P0imp: val = %d, thread gen %d, thread exe %d\n", val, th, t);
delay(1); // sleep 1 ms
}
// signal creation of all tasks: passed = 5 + 1 = 6
#pragma omp atomic
passed++;
// wait for completion of all 4 tasks
int wait = 0;
do {
delay(5);
#pragma omp atomic read
wait = passed;
} while (wait < 10); // passed = 6 + 4 = 10
} else {
// wait for the primary thread to create all tasks
int wait = 0;
do {
delay(5);
#pragma omp atomic read
wait = passed;
} while (wait < 6);
// go execute 4 tasks created by primary thread
}
}
if (passed != 10) {
printf("failed, passed = %d (should be 10)\n", passed);
return 1;
}
printf("passed\n");
return 0;
}
// CHECK: parallel 1
// CHECK-NEXT: P2
// CHECK-NEXT: P1
// CHECK-NEXT: P0
// CHECK-NEXT: P0
// CHECK-NEXT: parallel 2
// CHECK-NEXT: P2
// CHECK-NEXT: P1
// CHECK-NEXT: P0
// CHECK-NEXT: P0
// CHECK: passed