351 lines · c
1// RUN--: %libarcher-compile-and-run | FileCheck %s --check-prefix=NOENV2// RUN: %libarcher-compile && env ARCHER_OPTIONS="all_memory=1" \3// RUN: %libarcher-run | FileCheck %s --check-prefix=ENV4// REQUIRES: tsan5 6// 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#include <omp.h>29#include <stdio.h>30 31#ifdef _WIN3232#include <windows.h>33#define mysleep(n) Sleep(n)34#else35#include <unistd.h>36#define mysleep(n) usleep((n)*1000)37#endif38 39// to check the # of concurrent tasks (must be 1 for MTX, <3 for other kinds)40static int checker = 0;41static int err = 0;42#ifndef DELAY43#define DELAY 10044#endif45 46// ---------------------------------------------------------------------------47// internal data to emulate compiler codegen48typedef struct DEP {49 size_t addr;50 size_t len;51 unsigned char flags;52} dep;53#define DEP_ALL_MEM 0x8054typedef struct task {55 void **shareds;56 void *entry;57 int part_id;58 void *destr_thunk;59 int priority;60 long long device_id;61 int f_priv;62} task_t;63#define TIED 164typedef int (*entry_t)(int, task_t *);65typedef struct ID {66 int reserved_1;67 int flags;68 int reserved_2;69 int reserved_3;70 char *psource;71} id;72// thunk routine for tasks with ALL dependency73int thunk_m(int gtid, task_t *ptask) {74 int lcheck, th;75#pragma omp atomic capture76 lcheck = ++checker;77 th = omp_get_thread_num();78 printf("task m_%d, th %d, checker %d\n", ptask->f_priv, th, lcheck);79 if (lcheck != 1) { // no more than 1 task at a time80 err++;81 printf("Error m1, checker %d != 1\n", lcheck);82 }83 mysleep(DELAY);84#pragma omp atomic read85 lcheck = checker; // must still be equal to 186 if (lcheck != 1) {87 err++;88 printf("Error m2, checker %d != 1\n", lcheck);89 }90#pragma omp atomic91 --checker;92 return 0;93}94// thunk routine for tasks with inoutset dependency95int thunk_s(int gtid, task_t *ptask) {96 int lcheck, th;97#pragma omp atomic capture98 lcheck = ++checker; // 199 th = omp_get_thread_num();100 printf("task 2_%d, th %d, checker %d\n", ptask->f_priv, th, lcheck);101 if (lcheck != 1) { // no more than 1 task at a time102 err++;103 printf("Error s1, checker %d != 1\n", lcheck);104 }105 mysleep(DELAY);106#pragma omp atomic read107 lcheck = checker; // must still be equal to 1108 if (lcheck != 1) {109 err++;110 printf("Error s2, checker %d != 1\n", lcheck);111 }112#pragma omp atomic113 --checker;114 return 0;115}116 117#ifdef __cplusplus118extern "C" {119#endif120int __kmpc_global_thread_num(id *);121task_t *__kmpc_omp_task_alloc(id *loc, int gtid, int flags, size_t sz,122 size_t shar, entry_t rtn);123int __kmpc_omp_task_with_deps(id *loc, int gtid, task_t *task, int ndeps,124 dep *dep_lst, int nd_noalias, dep *noalias_lst);125static id loc = {0, 2, 0, 0, ";file;func;0;0;;"};126#ifdef __cplusplus127} // extern "C"128#endif129// End of internal data130// ---------------------------------------------------------------------------131 132int main() {133 char *ompx_all_memory = (void *)0xffffffffffffffff;134 int i1, i2, i3;135 omp_set_num_threads(8);136 omp_set_dynamic(0);137#pragma omp parallel138 {139#pragma omp single nowait140 {141 dep sdep[2];142 task_t *ptr;143 int gtid = __kmpc_global_thread_num(&loc);144 int t = omp_get_thread_num();145#pragma omp task depend(in : i1, i2)146 { // task 0147 int lcheck, th;148#pragma omp atomic capture149 lcheck = ++checker; // 1 or 2150 th = omp_get_thread_num();151 printf("task 0_%d, th %d, checker %d\n", t, th, lcheck);152 if (lcheck > 2 || lcheck < 1) {153 err++; // no more than 2 tasks concurrently154 printf("Error1, checker %d, not 1 or 2\n", lcheck);155 }156 mysleep(DELAY);157#pragma omp atomic read158 lcheck = checker; // 1 or 2159 if (lcheck > 2 || lcheck < 1) {160#pragma omp atomic161 err++;162 printf("Error2, checker %d, not 1 or 2\n", lcheck);163 }164#pragma omp atomic165 --checker;166 }167#pragma omp task depend(in : i1, i2)168 { // task 1169 int lcheck, th;170#pragma omp atomic capture171 lcheck = ++checker; // 1 or 2172 th = omp_get_thread_num();173 printf("task 1_%d, th %d, checker %d\n", t, th, lcheck);174 if (lcheck > 2 || lcheck < 1) {175 err++; // no more than 2 tasks concurrently176 printf("Error3, 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 err++;183 printf("Error4, checker %d, not 1 or 2\n", lcheck);184 }185#pragma omp atomic186 --checker;187 }188 // compiler codegen start189 // task2190 ptr = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(task_t), 0, thunk_s);191 sdep[0].addr = (size_t)&i1;192 sdep[0].len = 0; // not used193 sdep[0].flags = 1; // IN194 sdep[1].addr = (size_t)&i2;195 sdep[1].len = 0; // not used196 sdep[1].flags = 8; // INOUTSET197 ptr->f_priv = t + 10; // init single first-private variable198 __kmpc_omp_task_with_deps(&loc, gtid, ptr, 2, sdep, 0, 0);199 200// task3201#pragma omp task depend(in : i1) depend(inout : ompx_all_memory[0])202 {203 int lcheck, th;204#pragma omp atomic capture205 lcheck = ++checker;206 th = omp_get_thread_num();207 printf("task 3_%d, th %d, checker %d\n", t, th, lcheck);208 if (lcheck != 1) { // no more than 1 task at a time209 err++;210 printf("Error m1, checker %d != 1\n", lcheck);211 }212 mysleep(DELAY);213#pragma omp atomic read214 lcheck = checker; // must still be equal to 1215 if (lcheck != 1) {216 err++;217 printf("Error m2, checker %d != 1\n", lcheck);218 }219#pragma omp atomic220 --checker;221 }222 // compiler codegen end223#pragma omp task depend(in : i1, i2)224 { // task 4225 int lcheck, th;226#pragma omp atomic capture227 lcheck = ++checker; // 1 or 2228 th = omp_get_thread_num();229 printf("task 4_%d, th %d, checker %d\n", t, th, lcheck);230 if (lcheck > 2 || lcheck < 1) {231 err++; // no more than 2 tasks concurrently232 printf("Error5, checker %d, not 1 or 2\n", lcheck);233 }234 mysleep(DELAY);235#pragma omp atomic read236 lcheck = checker; // 1 or 2237 if (lcheck > 2 || lcheck < 1) {238 err++;239 printf("Error6, checker %d, not 1 or 2\n", lcheck);240 }241#pragma omp atomic242 --checker;243 }244#pragma omp task depend(in : i1, i2)245 { // task 5246 int lcheck, th;247#pragma omp atomic capture248 lcheck = ++checker; // 1 or 2249 th = omp_get_thread_num();250 printf("task 5_%d, th %d, checker %d\n", t, th, lcheck);251 if (lcheck > 2 || lcheck < 1) {252 err++; // no more than 2 tasks concurrently253 printf("Error7, checker %d, not 1 or 2\n", lcheck);254 }255 mysleep(DELAY);256#pragma omp atomic read257 lcheck = checker; // 1 or 2258 if (lcheck > 2 || lcheck < 1) {259 err++;260 printf("Error8, checker %d, not 1 or 2\n", lcheck);261 }262#pragma omp atomic263 --checker;264 }265// task6266#pragma omp task depend(inout : ompx_all_memory[0])267 {268 int lcheck, th;269#pragma omp atomic capture270 lcheck = ++checker;271 th = omp_get_thread_num();272 printf("task 6_%d, th %d, checker %d\n", t, th, lcheck);273 if (lcheck != 1) { // no more than 1 task at a time274 err++;275 printf("Error m1, checker %d != 1\n", lcheck);276 }277 mysleep(DELAY);278#pragma omp atomic read279 lcheck = checker; // must still be equal to 1280 if (lcheck != 1) {281 err++;282 printf("Error m2, checker %d != 1\n", lcheck);283 }284#pragma omp atomic285 --checker;286 }287// task7288#pragma omp task depend(inout : ompx_all_memory[0]) depend(mutexinoutset : i3)289 {290 int lcheck, th;291#pragma omp atomic capture292 lcheck = ++checker;293 th = omp_get_thread_num();294 printf("task 7_%d, th %d, checker %d\n", t, th, lcheck);295 if (lcheck != 1) { // no more than 1 task at a time296 err++;297 printf("Error m1, checker %d != 1\n", lcheck);298 }299 mysleep(DELAY);300#pragma omp atomic read301 lcheck = checker; // must still be equal to 1302 if (lcheck != 1) {303 err++;304 printf("Error m2, checker %d != 1\n", lcheck);305 }306#pragma omp atomic307 --checker;308 }309#pragma omp task depend(in : i3)310 { // task 8311 int lcheck, th;312#pragma omp atomic capture313 lcheck = ++checker; // 1314 th = omp_get_thread_num();315 printf("task 8_%d, th %d, checker %d\n", t, th, lcheck);316 if (lcheck != 1) {317 err++;318 printf("Error9, checker %d, != 1\n", lcheck);319 }320 mysleep(DELAY);321#pragma omp atomic read322 lcheck = checker;323 if (lcheck != 1) {324 err++;325 printf("Error10, checker %d, != 1\n", lcheck);326 }327#pragma omp atomic328 --checker;329 }330 } // single331 } // parallel332 if (err == 0 && checker == 0) {333 printf("passed\n");334 return 0;335 } else {336 printf("failed, err = %d, checker = %d\n", err, checker);337 return 1;338 }339}340 341// NOENV-NOT: ThreadSanitizer: data race342// NOENV-NOT: ThreadSanitizer: reported343// NOENV: omp_all_memory344// NOENV-NOT: ThreadSanitizer: data race345// NOENV-NOT: ThreadSanitizer: reported346// NOENV: passed347 348// ENV-NOT: ThreadSanitizer: data race349// ENV-NOT: ThreadSanitizer: reported350// ENV: passed351