335 lines · c
1// RUN: %libomp-compile-and-run2// The runtime currently does not get dependency information from GCC.3// UNSUPPORTED: gcc4 5// Tests OMP 5.x task dependence "omp_all_memory",6// emulates compiler codegen versions for new dep kind7//8// Task tree created:9// task0 - task1 (in: i1, i2)10// \11// task2 (inoutset: i2), (in: i1)12// /13// task3 (omp_all_memory) via flag=0x8014// /15// task4 - task5 (in: i1, i2)16// /17// task6 (omp_all_memory) via addr=-118// /19// task7 (omp_all_memory) via flag=0x8020// /21// task8 (in: i3)22// /23// task9 - no dependences24// /25// taskwait (omp_all_memory) (should not wait for task9, see prints)26//27#include <stdio.h>28#include <omp.h>29 30#ifdef _WIN3231#include <windows.h>32#define mysleep(n) Sleep(n)33#else34#include <unistd.h>35#define mysleep(n) usleep((n)*1000)36#endif37 38// to check the # of concurrent tasks (must be 1 for MTX, <3 for other kinds)39static int checker = 0;40static int err = 0;41static int taskwait_flag = 0;42#ifndef DELAY43// set delay interval in ms for dependent tasks44#define DELAY 10045#endif46 47// ---------------------------------------------------------------------------48// internal data to emulate compiler codegen49typedef struct DEP {50 size_t addr;51 size_t len;52 unsigned char flags;53} dep;54#define DEP_ALL_MEM 0x8055typedef struct task {56 void** shareds;57 void* entry;58 int part_id;59 void* destr_thunk;60 int priority;61 long long device_id;62 int f_priv;63} task_t;64#define TIED 165typedef int(*entry_t)(int, task_t*);66typedef struct ID {67 int reserved_1;68 int flags;69 int reserved_2;70 int reserved_3;71 char *psource;72} id;73// thunk routine for tasks with ALL dependency74int thunk_m(int gtid, task_t* ptask) {75 int lcheck, th;76 #pragma omp atomic capture77 lcheck = ++checker;78 th = omp_get_thread_num();79 printf("task m_%d, th %d, checker %d\n", ptask->f_priv, th, lcheck);80 if (lcheck != 1) { // no more than 1 task at a time81 err++;82 printf("Error m1, checker %d != 1\n", lcheck);83 }84 mysleep(DELAY);85 #pragma omp atomic read86 lcheck = checker; // must still be equal to 187 if (lcheck != 1) {88 err++;89 printf("Error m2, checker %d != 1\n", lcheck);90 }91 #pragma omp atomic92 --checker;93 return 0;94}95// thunk routine for tasks with inoutset dependency96int thunk_s(int gtid, task_t* ptask) {97 int lcheck, th;98 #pragma omp atomic capture99 lcheck = ++checker; // 1100 th = omp_get_thread_num();101 printf("task 2_%d, th %d, checker %d\n", ptask->f_priv, th, lcheck);102 if (lcheck != 1) { // no more than 1 task at a time103 err++;104 printf("Error s1, checker %d != 1\n", lcheck);105 }106 mysleep(DELAY);107 #pragma omp atomic read108 lcheck = checker; // must still be equal to 1109 if (lcheck != 1) {110 err++;111 printf("Error s2, checker %d != 1\n", lcheck);112 }113 #pragma omp atomic114 --checker;115 return 0;116}117 118#ifdef __cplusplus119extern "C" {120#endif121int __kmpc_global_thread_num(id*);122task_t *__kmpc_omp_task_alloc(id *loc, int gtid, int flags,123 size_t sz, size_t shar, entry_t rtn);124int __kmpc_omp_task_with_deps(id *loc, int gtid, task_t *task, int ndeps,125 dep *dep_lst, int nd_noalias, dep *noalias_lst);126void __kmpc_omp_wait_deps(id *loc, int gtid, int ndeps, dep *dep_lst,127 int ndeps_noalias, dep *noalias_dep_lst);128static id loc = {0, 2, 0, 0, ";file;func;0;0;;"};129#ifdef __cplusplus130} // extern "C"131#endif132// End of internal data133// ---------------------------------------------------------------------------134 135int main()136{137 int i1,i2,i3;138 omp_set_num_threads(8);139 omp_set_dynamic(0);140 #pragma omp parallel141 {142 #pragma omp single nowait143 {144 dep sdep[2];145 task_t *ptr;146 int gtid = __kmpc_global_thread_num(&loc);147 int t = omp_get_thread_num();148 // Create longest task first to ensure it is stolen.149 // The test may hang if the task created last and150 // executed by a thread which executes taskwait.151 #pragma omp task152 { // task 9 - long running task153 int flag;154 int th = omp_get_thread_num();155 printf("signalled independent task 9_%d, th %d started....\n", t, th);156 // Wait for taskwait depend() to finish157 // If the taskwait depend() improperly depends on this task158 // to finish, then the test will hang and a timeout should trigger159 while (1) {160 #pragma omp atomic read161 flag = taskwait_flag;162 if (flag == 1)163 break;164 }165 printf("signalled independent task 9_%d, th %d finished....\n", t, th);166 }167 #pragma omp task depend(in: i1, i2)168 { // task 0169 int lcheck, th;170 #pragma omp atomic capture171 lcheck = ++checker; // 1 or 2172 th = omp_get_thread_num();173 printf("task 0_%d, th %d, checker %d\n", t, th, lcheck);174 if (lcheck > 2 || lcheck < 1) {175 err++; // no more than 2 tasks concurrently176 printf("Error1, checker %d, not 1 or 2\n", lcheck);177 }178 mysleep(DELAY);179 #pragma omp atomic read180 lcheck = checker; // 1 or 2181 if (lcheck > 2 || lcheck < 1) {182 #pragma omp atomic183 err++;184 printf("Error2, checker %d, not 1 or 2\n", lcheck);185 }186 #pragma omp atomic187 --checker;188 }189 #pragma omp task depend(in: i1, i2)190 { // task 1191 int lcheck, th;192 #pragma omp atomic capture193 lcheck = ++checker; // 1 or 2194 th = omp_get_thread_num();195 printf("task 1_%d, th %d, checker %d\n", t, th, lcheck);196 if (lcheck > 2 || lcheck < 1) {197 err++; // no more than 2 tasks concurrently198 printf("Error3, checker %d, not 1 or 2\n", lcheck);199 }200 mysleep(DELAY);201 #pragma omp atomic read202 lcheck = checker; // 1 or 2203 if (lcheck > 2 || lcheck < 1) {204 err++;205 printf("Error4, checker %d, not 1 or 2\n", lcheck);206 }207 #pragma omp atomic208 --checker;209 }210// compiler codegen start211 // task2212 ptr = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(task_t), 0, thunk_s);213 sdep[0].addr = (size_t)&i1;214 sdep[0].len = 0; // not used215 sdep[0].flags = 1; // IN216 sdep[1].addr = (size_t)&i2;217 sdep[1].len = 0; // not used218 sdep[1].flags = 8; // INOUTSET219 ptr->f_priv = t + 10; // init single first-private variable220 __kmpc_omp_task_with_deps(&loc, gtid, ptr, 2, sdep, 0, 0);221 222 // task3223 ptr = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(task_t), 0, thunk_m);224 sdep[0].addr = (size_t)&i1; // to be ignored225 sdep[0].len = 0; // not used226 sdep[0].flags = 1; // IN227 sdep[1].addr = 0;228 sdep[1].len = 0; // not used229 sdep[1].flags = DEP_ALL_MEM; // omp_all_memory230 ptr->f_priv = t + 20; // init single first-private variable231 __kmpc_omp_task_with_deps(&loc, gtid, ptr, 2, sdep, 0, 0);232// compiler codegen end233 #pragma omp task depend(in: i1, i2)234 { // task 4235 int lcheck, th;236 #pragma omp atomic capture237 lcheck = ++checker; // 1 or 2238 th = omp_get_thread_num();239 printf("task 4_%d, th %d, checker %d\n", t, th, lcheck);240 if (lcheck > 2 || lcheck < 1) {241 err++; // no more than 2 tasks concurrently242 printf("Error5, checker %d, not 1 or 2\n", lcheck);243 }244 mysleep(DELAY);245 #pragma omp atomic read246 lcheck = checker; // 1 or 2247 if (lcheck > 2 || lcheck < 1) {248 err++;249 printf("Error6, checker %d, not 1 or 2\n", lcheck);250 }251 #pragma omp atomic252 --checker;253 }254 #pragma omp task depend(in: i1, i2)255 { // task 5256 int lcheck, th;257 #pragma omp atomic capture258 lcheck = ++checker; // 1 or 2259 th = omp_get_thread_num();260 printf("task 5_%d, th %d, checker %d\n", t, th, lcheck);261 if (lcheck > 2 || lcheck < 1) {262 err++; // no more than 2 tasks concurrently263 printf("Error7, checker %d, not 1 or 2\n", lcheck);264 }265 mysleep(DELAY);266 #pragma omp atomic read267 lcheck = checker; // 1 or 2268 if (lcheck > 2 || lcheck < 1) {269 err++;270 printf("Error8, checker %d, not 1 or 2\n", lcheck);271 }272 #pragma omp atomic273 --checker;274 }275// compiler codegen start276 // task6277 ptr = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(task_t), 0, thunk_m);278 sdep[0].addr = (size_t)(-1); // omp_all_memory279 sdep[0].len = 0; // not used280 sdep[0].flags = 2; // OUT281 ptr->f_priv = t + 30; // init single first-private variable282 __kmpc_omp_task_with_deps(&loc, gtid, ptr, 1, sdep, 0, 0);283 284 // task7285 ptr = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(task_t), 0, thunk_m);286 sdep[0].addr = 0;287 sdep[0].len = 0; // not used288 sdep[0].flags = DEP_ALL_MEM; // omp_all_memory289 sdep[1].addr = (size_t)&i3; // to be ignored290 sdep[1].len = 0; // not used291 sdep[1].flags = 4; // MUTEXINOUTSET292 ptr->f_priv = t + 40; // init single first-private variable293 __kmpc_omp_task_with_deps(&loc, gtid, ptr, 2, sdep, 0, 0);294// compiler codegen end295 #pragma omp task depend(in: i3)296 { // task 8297 int lcheck, th;298 #pragma omp atomic capture299 lcheck = ++checker; // 1300 th = omp_get_thread_num();301 printf("task 8_%d, th %d, checker %d\n", t, th, lcheck);302 if (lcheck != 1) {303 err++;304 printf("Error9, checker %d, != 1\n", lcheck);305 }306 mysleep(DELAY);307 #pragma omp atomic read308 lcheck = checker;309 if (lcheck != 1) {310 err++;311 printf("Error10, checker %d, != 1\n", lcheck);312 }313 #pragma omp atomic314 --checker;315 }316 mysleep(1); // wait a bit to ensure at least first task is stolen317// #pragma omp taskwait depend(omp_all_memory: out)318 printf("all 10 tasks generated;\n"319 "taskwait depend(omp_all_memory: out) started, th %d\n", t);320 __kmpc_omp_wait_deps(&loc, gtid, 1, sdep, 0, 0);321 #pragma omp atomic write322 taskwait_flag = 1;323 printf("taskwait depend(omp_all_memory: out) passed, th %d\n", t);324 fflush(0);325 } // single326 } // parallel327 if (err == 0 && checker == 0) {328 printf("passed\n");329 return 0;330 } else {331 printf("failed, err = %d, checker = %d\n", err, checker);332 return 1;333 }334}335