259 lines · c
1// RUN: %libomp-compile-and-run2// RUN: %libomp-cxx-compile-and-run3// UNSUPPORTED: gcc4 5// Tests OMP 5.0 task dependences "mutexinoutset" and 5.1 "inoutset",6// emulates compiler codegen for new dep kinds7// Mutually exclusive tasks get same input dependency info array8//9// Task tree created:10// task0 - task1 (in)11// \12// task2 - task3 (inoutset)13// /14// task3 - task4 (in)15// /16// task6 <-->task7 (mutexinoutset)17// \ /18// task8 (in)19//20#include <stdio.h>21#include <omp.h>22 23#ifdef _WIN3224#include <windows.h>25#define mysleep(n) Sleep(n)26#else27#include <unistd.h>28#define mysleep(n) usleep((n)*1000)29#endif30 31// to check the # of concurrent tasks (must be 1 for MTX, <3 for other kinds)32static int volatile checker = 0;33static int err = 0;34#ifndef DELAY35#define DELAY 10036#endif37 38// ---------------------------------------------------------------------------39// internal data to emulate compiler codegen40typedef struct DEP {41 size_t addr;42 size_t len;43 unsigned char flags;44} dep;45typedef struct task {46 void** shareds;47 void* entry;48 int part_id;49 void* destr_thunk;50 int priority;51 long long device_id;52 int f_priv;53} task_t;54#define TIED 155typedef int(*entry_t)(int, task_t*);56typedef struct ID {57 int reserved_1;58 int flags;59 int reserved_2;60 int reserved_3;61 char *psource;62} id;63// thunk routine for tasks with MTX dependency64int thunk_m(int gtid, task_t* ptask) {65 int th = omp_get_thread_num();66 #pragma omp atomic67 ++checker;68 printf("task _%d, th %d\n", ptask->f_priv, th);69 if (checker != 1) { // no more than 1 task at a time70 err++;71 printf("Error1, checker %d != 1\n", checker);72 }73 mysleep(DELAY);74 if (checker != 1) { // no more than 1 task at a time75 err++;76 printf("Error2, checker %d != 1\n", checker);77 }78 #pragma omp atomic79 --checker;80 return 0;81}82// thunk routine for tasks with inoutset dependency83int thunk_s(int gtid, task_t* ptask) {84 int th = omp_get_thread_num();85 #pragma omp atomic86 ++checker;87 printf("task _%d, th %d\n", ptask->f_priv, th);88 if (checker > 2) { // no more than 2 tasks concurrently89 err++;90 printf("Error1, checker %d > 2\n", checker);91 }92 mysleep(DELAY);93 if (checker > 2) { // no more than 2 tasks concurrently94 err++;95 printf("Error2, checker %d > 2\n", checker);96 }97 #pragma omp atomic98 --checker;99 return 0;100}101 102#ifdef __cplusplus103extern "C" {104#endif105int __kmpc_global_thread_num(id*);106extern task_t* __kmpc_omp_task_alloc(id *loc, int gtid, int flags,107 size_t sz, size_t shar, entry_t rtn);108int109__kmpc_omp_task_with_deps(id *loc, int gtid, task_t *task, int nd, dep *dep_lst,110 int nd_noalias, dep *noalias_dep_lst);111static id loc = {0, 2, 0, 0, ";file;func;0;0;;"};112#ifdef __cplusplus113} // extern "C"114#endif115// End of internal data116// ---------------------------------------------------------------------------117 118int main()119{120 int i1,i2,i3;121 omp_set_num_threads(4);122 omp_set_dynamic(0);123 #pragma omp parallel124 {125 #pragma omp single nowait126 {127 dep sdep[2];128 task_t *ptr;129 int gtid = __kmpc_global_thread_num(&loc);130 int t = omp_get_thread_num();131 #pragma omp task depend(in: i1, i2)132 { int th = omp_get_thread_num();133 printf("task 0_%d, th %d\n", t, th);134 #pragma omp atomic135 ++checker;136 if (checker > 2) { // no more than 2 tasks concurrently137 err++;138 printf("Error1, checker %d > 2\n", checker);139 }140 mysleep(DELAY);141 if (checker > 2) { // no more than 2 tasks concurrently142 err++;143 printf("Error1, checker %d > 2\n", checker);144 }145 #pragma omp atomic146 --checker;147 }148 #pragma omp task depend(in: i1, i2)149 { int th = omp_get_thread_num();150 printf("task 1_%d, th %d\n", t, th);151 #pragma omp atomic152 ++checker;153 if (checker > 2) { // no more than 2 tasks concurrently154 err++;155 printf("Error1, checker %d > 2\n", checker);156 }157 mysleep(DELAY);158 if (checker > 2) { // no more than 2 tasks concurrently159 err++;160 printf("Error1, checker %d > 2\n", checker);161 }162 #pragma omp atomic163 --checker;164 }165// compiler codegen start166 // task2167 ptr = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(task_t), 0, thunk_s);168 sdep[0].addr = (size_t)&i1;169 sdep[0].len = 0; // not used170 sdep[0].flags = 1; // IN171 sdep[1].addr = (size_t)&i2;172 sdep[1].len = 0; // not used173 sdep[1].flags = 8; // INOUTSET174 ptr->f_priv = t + 10; // init single first-private variable175 __kmpc_omp_task_with_deps(&loc, gtid, ptr, 2, sdep, 0, 0);176 177 // task3178 ptr = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(task_t), 0, thunk_s);179 ptr->f_priv = t + 20; // init single first-private variable180 __kmpc_omp_task_with_deps(&loc, gtid, ptr, 2, sdep, 0, 0);181// compiler codegen end182 t = omp_get_thread_num();183 #pragma omp task depend(in: i1, i2)184 { int th = omp_get_thread_num();185 printf("task 4_%d, th %d\n", t, th);186 #pragma omp atomic187 ++checker;188 if (checker > 2) { // no more than 2 tasks concurrently189 err++;190 printf("Error1, checker %d > 2\n", checker);191 }192 mysleep(DELAY);193 if (checker > 2) { // no more than 2 tasks concurrently194 err++;195 printf("Error1, checker %d > 2\n", checker);196 }197 #pragma omp atomic198 --checker;199 }200 #pragma omp task depend(in: i1, i2)201 { int th = omp_get_thread_num();202 printf("task 5_%d, th %d\n", t, th);203 #pragma omp atomic204 ++checker;205 if (checker > 2) { // no more than 2 tasks concurrently206 err++;207 printf("Error1, checker %d > 2\n", checker);208 }209 mysleep(DELAY);210 if (checker > 2) { // no more than 2 tasks concurrently211 err++;212 printf("Error1, checker %d > 2\n", checker);213 }214 #pragma omp atomic215 --checker;216 }217// compiler codegen start218 // task6219 ptr = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(task_t), 0, thunk_m);220 sdep[0].addr = (size_t)&i1;221 sdep[0].len = 0; // not used222 sdep[0].flags = 4; // MUTEXINOUTSET223 sdep[1].addr = (size_t)&i3;224 sdep[1].len = 0; // not used225 sdep[1].flags = 4; // MUTEXINOUTSET226 ptr->f_priv = t + 30; // init single first-private variable227 __kmpc_omp_task_with_deps(&loc, gtid, ptr, 2, sdep, 0, 0);228 229 // task7230 ptr = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(task_t), 0, thunk_m);231 ptr->f_priv = t + 40; // init single first-private variable232 __kmpc_omp_task_with_deps(&loc, gtid, ptr, 2, sdep, 0, 0);233// compiler codegen end234 #pragma omp task depend(in: i3)235 { int th = omp_get_thread_num();236 printf("task 8_%d, th %d\n", t, th);237 #pragma omp atomic238 ++checker;239 if (checker != 1) { // last task should run exclusively240 err++;241 printf("Error1, checker %d != 1\n", checker); }242 mysleep(DELAY);243 if (checker != 1) { // last task should run exclusively244 err++;245 printf("Error1, checker %d != 1\n", checker); }246 #pragma omp atomic247 --checker;248 }249 } // single250 } // parallel251 if (err == 0) {252 printf("passed\n");253 return 0;254 } else {255 printf("failed\n");256 return 1;257 }258}259