348 lines · c
1// clang-format off2// RUN: %libomp-compile-and-run | FileCheck %s3// REQUIRES: ompt4 5// RUN: %libomp-compile-and-run6// The runtime currently does not get dependency information from GCC.7// UNSUPPORTED: gcc8 9// Tests OMP 5.x task dependence "omp_all_memory",10// emulates compiler codegen versions for new dep kind11//12// Task tree created:13// task0 - task1 (in: i1, i2)14// \15// task2 (inoutset: i2), (in: i1)16// /17// task3 (omp_all_memory) via flag=0x8018// /19// task4 - task5 (in: i1, i2)20// /21// task6 (omp_all_memory) via addr=-122// /23// task7 (omp_all_memory) via flag=0x8024// /25// task8 (in: i3)26//27 28// CHECK: ompt_event_dependences:29// CHECK-SAME: ompt_dependence_type_in30// CHECK-SAME: ompt_dependence_type_in31// CHECK-SAME: ndeps=232 33// CHECK: ompt_event_dependences:34// CHECK-SAME: ompt_dependence_type_in35// CHECK-SAME: ompt_dependence_type_in36// CHECK-SAME: ndeps=237 38// CHECK: ompt_event_dependences:39// CHECK-SAME: ompt_dependence_type_in40// CHECK-SAME: ompt_dependence_type_inoutset41// CHECK-SAME: ndeps=242 43// CHECK: ompt_event_dependences:44// CHECK-SAME: ompt_dependence_type_in45// CHECK-SAME: ompt_dependence_type_out_all_memory46// CHECK-SAME: ndeps=247 48// CHECK: ompt_event_dependences:49// CHECK-SAME: ompt_dependence_type_in50// CHECK-SAME: ompt_dependence_type_in51// CHECK-SAME: ndeps=252 53// CHECK: ompt_event_dependences:54// CHECK-SAME: ompt_dependence_type_in55// CHECK-SAME: ompt_dependence_type_in56// CHECK-SAME: ndeps=257 58// CHECK: ompt_event_dependences:59// CHECK-SAME: ompt_dependence_type_out_all_memory60// CHECK-SAME: ndeps=161 62// CHECK: ompt_event_dependences:63// CHECK-SAME: ompt_dependence_type_out_all_memory64// CHECK-SAME: ompt_dependence_type_mutexinoutset65// CHECK-SAME: ndeps=266 67// CHECK: ompt_event_dependences:68// CHECK-SAME: ompt_dependence_type_in69// CHECK-SAME: ndeps=170// clang-format on71 72#include "callback.h"73#include <stdio.h>74#include <omp.h>75 76#ifdef _WIN3277#include <windows.h>78#define mysleep(n) Sleep(n)79#else80#include <unistd.h>81#define mysleep(n) usleep((n)*1000)82#endif83 84// to check the # of concurrent tasks (must be 1 for MTX, <3 for other kinds)85static int checker = 0;86static int err = 0;87#ifndef DELAY88#define DELAY 10089#endif90 91// ---------------------------------------------------------------------------92// internal data to emulate compiler codegen93typedef struct DEP {94 size_t addr;95 size_t len;96 unsigned char flags;97} dep;98#define DEP_ALL_MEM 0x8099typedef struct task {100 void **shareds;101 void *entry;102 int part_id;103 void *destr_thunk;104 int priority;105 long long device_id;106 int f_priv;107} task_t;108#define TIED 1109typedef int (*entry_t)(int, task_t *);110typedef struct ID {111 int reserved_1;112 int flags;113 int reserved_2;114 int reserved_3;115 char *psource;116} id;117// thunk routine for tasks with ALL dependency118int thunk_m(int gtid, task_t *ptask) {119 int lcheck, th;120#pragma omp atomic capture121 lcheck = ++checker;122 th = omp_get_thread_num();123 printf("task m_%d, th %d, checker %d\n", ptask->f_priv, th, lcheck);124 if (lcheck != 1) { // no more than 1 task at a time125 err++;126 printf("Error m1, checker %d != 1\n", lcheck);127 }128 mysleep(DELAY);129#pragma omp atomic read130 lcheck = checker; // must still be equal to 1131 if (lcheck != 1) {132 err++;133 printf("Error m2, checker %d != 1\n", lcheck);134 }135#pragma omp atomic136 --checker;137 return 0;138}139// thunk routine for tasks with inoutset dependency140int thunk_s(int gtid, task_t *ptask) {141 int lcheck, th;142#pragma omp atomic capture143 lcheck = ++checker; // 1144 th = omp_get_thread_num();145 printf("task 2_%d, th %d, checker %d\n", ptask->f_priv, th, lcheck);146 if (lcheck != 1) { // no more than 1 task at a time147 err++;148 printf("Error s1, checker %d != 1\n", lcheck);149 }150 mysleep(DELAY);151#pragma omp atomic read152 lcheck = checker; // must still be equal to 1153 if (lcheck != 1) {154 err++;155 printf("Error s2, checker %d != 1\n", lcheck);156 }157#pragma omp atomic158 --checker;159 return 0;160}161 162#ifdef __cplusplus163extern "C" {164#endif165int __kmpc_global_thread_num(id *);166task_t *__kmpc_omp_task_alloc(id *loc, int gtid, int flags, size_t sz,167 size_t shar, entry_t rtn);168int __kmpc_omp_task_with_deps(id *loc, int gtid, task_t *task, int ndeps,169 dep *dep_lst, int nd_noalias, dep *noalias_lst);170static id loc = {0, 2, 0, 0, ";file;func;0;0;;"};171#ifdef __cplusplus172} // extern "C"173#endif174// End of internal data175// ---------------------------------------------------------------------------176 177int main() {178 int i1, i2, i3;179 omp_set_num_threads(8);180 omp_set_dynamic(0);181#pragma omp parallel182 {183#pragma omp single nowait184 {185 dep sdep[2];186 task_t *ptr;187 int gtid = __kmpc_global_thread_num(&loc);188 int t = omp_get_thread_num();189#pragma omp task depend(in : i1, i2)190 { // task 0191 int lcheck, th;192#pragma omp atomic capture193 lcheck = ++checker; // 1 or 2194 th = omp_get_thread_num();195 printf("task 0_%d, th %d, checker %d\n", t, th, lcheck);196 if (lcheck > 2 || lcheck < 1) {197 err++; // no more than 2 tasks concurrently198 printf("Error1, 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#pragma omp atomic205 err++;206 printf("Error2, checker %d, not 1 or 2\n", lcheck);207 }208#pragma omp atomic209 --checker;210 }211#pragma omp task depend(in : i1, i2)212 { // task 1213 int lcheck, th;214#pragma omp atomic capture215 lcheck = ++checker; // 1 or 2216 th = omp_get_thread_num();217 printf("task 1_%d, th %d, checker %d\n", t, th, lcheck);218 if (lcheck > 2 || lcheck < 1) {219 err++; // no more than 2 tasks concurrently220 printf("Error3, checker %d, not 1 or 2\n", lcheck);221 }222 mysleep(DELAY);223#pragma omp atomic read224 lcheck = checker; // 1 or 2225 if (lcheck > 2 || lcheck < 1) {226 err++;227 printf("Error4, checker %d, not 1 or 2\n", lcheck);228 }229#pragma omp atomic230 --checker;231 }232 // compiler codegen start233 // task2234 ptr = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(task_t), 0, thunk_s);235 sdep[0].addr = (size_t)&i1;236 sdep[0].len = 0; // not used237 sdep[0].flags = 1; // IN238 sdep[1].addr = (size_t)&i2;239 sdep[1].len = 0; // not used240 sdep[1].flags = 8; // INOUTSET241 ptr->f_priv = t + 10; // init single first-private variable242 __kmpc_omp_task_with_deps(&loc, gtid, ptr, 2, sdep, 0, 0);243 244 // task3245 ptr = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(task_t), 0, thunk_m);246 sdep[0].addr = (size_t)&i1; // to be ignored247 sdep[0].len = 0; // not used248 sdep[0].flags = 1; // IN249 sdep[1].addr = 0;250 sdep[1].len = 0; // not used251 sdep[1].flags = DEP_ALL_MEM; // omp_all_memory252 ptr->f_priv = t + 20; // init single first-private variable253 __kmpc_omp_task_with_deps(&loc, gtid, ptr, 2, sdep, 0, 0);254 // compiler codegen end255#pragma omp task depend(in : i1, i2)256 { // task 4257 int lcheck, th;258#pragma omp atomic capture259 lcheck = ++checker; // 1 or 2260 th = omp_get_thread_num();261 printf("task 4_%d, th %d, checker %d\n", t, th, lcheck);262 if (lcheck > 2 || lcheck < 1) {263 err++; // no more than 2 tasks concurrently264 printf("Error5, checker %d, not 1 or 2\n", lcheck);265 }266 mysleep(DELAY);267#pragma omp atomic read268 lcheck = checker; // 1 or 2269 if (lcheck > 2 || lcheck < 1) {270 err++;271 printf("Error6, checker %d, not 1 or 2\n", lcheck);272 }273#pragma omp atomic274 --checker;275 }276#pragma omp task depend(in : i1, i2)277 { // task 5278 int lcheck, th;279#pragma omp atomic capture280 lcheck = ++checker; // 1 or 2281 th = omp_get_thread_num();282 printf("task 5_%d, th %d, checker %d\n", t, th, lcheck);283 if (lcheck > 2 || lcheck < 1) {284 err++; // no more than 2 tasks concurrently285 printf("Error7, checker %d, not 1 or 2\n", lcheck);286 }287 mysleep(DELAY);288#pragma omp atomic read289 lcheck = checker; // 1 or 2290 if (lcheck > 2 || lcheck < 1) {291 err++;292 printf("Error8, checker %d, not 1 or 2\n", lcheck);293 }294#pragma omp atomic295 --checker;296 }297 // compiler codegen start298 // task6299 ptr = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(task_t), 0, thunk_m);300 sdep[0].addr = (size_t)(-1); // omp_all_memory301 sdep[0].len = 0; // not used302 sdep[0].flags = 2; // OUT303 ptr->f_priv = t + 30; // init single first-private variable304 __kmpc_omp_task_with_deps(&loc, gtid, ptr, 1, sdep, 0, 0);305 306 // task7307 ptr = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(task_t), 0, thunk_m);308 sdep[0].addr = 0;309 sdep[0].len = 0; // not used310 sdep[0].flags = DEP_ALL_MEM; // omp_all_memory311 sdep[1].addr = (size_t)&i3; // to be ignored312 sdep[1].len = 0; // not used313 sdep[1].flags = 4; // MUTEXINOUTSET314 ptr->f_priv = t + 40; // init single first-private variable315 __kmpc_omp_task_with_deps(&loc, gtid, ptr, 2, sdep, 0, 0);316 // compiler codegen end317#pragma omp task depend(in : i3)318 { // task 8319 int lcheck, th;320#pragma omp atomic capture321 lcheck = ++checker; // 1322 th = omp_get_thread_num();323 printf("task 8_%d, th %d, checker %d\n", t, th, lcheck);324 if (lcheck != 1) {325 err++;326 printf("Error9, checker %d, != 1\n", lcheck);327 }328 mysleep(DELAY);329#pragma omp atomic read330 lcheck = checker;331 if (lcheck != 1) {332 err++;333 printf("Error10, checker %d, != 1\n", lcheck);334 }335#pragma omp atomic336 --checker;337 }338 } // single339 } // parallel340 if (err == 0 && checker == 0) {341 printf("passed\n");342 return 0;343 } else {344 printf("failed, err = %d, checker = %d\n", err, checker);345 return 1;346 }347}348