1 // RUN: %libomp-compile-and-run 2 // The runtime currently does not get dependency information from GCC. 3 // UNSUPPORTED: gcc 4 5 // Very flaky on openmp-clang-x86_64-linux-debian. 6 // https://bugs.llvm.org/show_bug.cgi?id=45397 7 // UNSUPPORTED: linux 8 9 #include <stdio.h> 10 #include <omp.h> 11 #include <pthread.h> 12 #include "omp_my_sleep.h" 13 14 /* 15 An explicit task can have a dependency on a target task. If it is not 16 directly satisfied, the runtime should not wait but resume execution. 17 */ 18 19 // Compiler-generated code (emulation) 20 typedef long kmp_intptr_t; 21 typedef int kmp_int32; 22 23 typedef char bool; 24 25 typedef struct ident { 26 kmp_int32 reserved_1; /**< might be used in Fortran; see above */ 27 kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; KMP_IDENT_KMPC identifies this union member */ 28 kmp_int32 reserved_2; /**< not really used in Fortran any more; see above */ 29 #if USE_ITT_BUILD 30 /* but currently used for storing region-specific ITT */ 31 /* contextual information. */ 32 #endif /* USE_ITT_BUILD */ 33 kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for C++ */ 34 char const *psource; /**< String describing the source location. 35 The string is composed of semi-colon separated fields which describe the source file, 36 the function and a pair of line numbers that delimit the construct. 37 */ 38 } ident_t; 39 40 typedef struct kmp_depend_info { 41 kmp_intptr_t base_addr; 42 size_t len; 43 struct { 44 bool in:1; 45 bool out:1; 46 } flags; 47 } kmp_depend_info_t; 48 49 struct kmp_task; 50 typedef kmp_int32 (* kmp_routine_entry_t)( kmp_int32, struct kmp_task * ); 51 52 typedef struct kmp_task { /* GEH: Shouldn't this be aligned somehow? */ 53 void * shareds; /**< pointer to block of pointers to shared vars */ 54 kmp_routine_entry_t routine; /**< pointer to routine to call for executing task */ 55 kmp_int32 part_id; /**< part id for the task */ 56 } kmp_task_t; 57 58 #ifdef __cplusplus 59 extern "C" { 60 #endif 61 kmp_int32 __kmpc_global_thread_num ( ident_t * ); 62 kmp_task_t* 63 __kmpc_omp_task_alloc( ident_t *loc_ref, kmp_int32 gtid, kmp_int32 flags, 64 size_t sizeof_kmp_task_t, size_t sizeof_shareds, 65 kmp_routine_entry_t task_entry ); 66 void __kmpc_proxy_task_completed_ooo ( kmp_task_t *ptask ); 67 kmp_int32 __kmpc_omp_task_with_deps ( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t * new_task, 68 kmp_int32 ndeps, kmp_depend_info_t *dep_list, 69 kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list ); 70 kmp_int32 71 __kmpc_omp_task( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t * new_task ); 72 #ifdef __cplusplus 73 } 74 #endif 75 76 void *target(void *task) 77 { 78 my_sleep( 0.1 ); 79 __kmpc_proxy_task_completed_ooo((kmp_task_t*) task); 80 return NULL; 81 } 82 83 pthread_t target_thread; 84 85 // User's code 86 int task_entry(kmp_int32 gtid, kmp_task_t *task) 87 { 88 pthread_create(&target_thread, NULL, &target, task); 89 return 0; 90 } 91 92 int main() 93 { 94 int dep; 95 96 /* 97 * Corresponds to: 98 #pragma omp target nowait depend(out: dep) 99 { 100 my_sleep( 0.1 ); 101 } 102 */ 103 kmp_depend_info_t dep_info; 104 dep_info.base_addr = (long) &dep; 105 dep_info.len = sizeof(int); 106 // out = inout per spec and runtime expects this 107 dep_info.flags.in = 1; 108 dep_info.flags.out = 1; 109 110 kmp_int32 gtid = __kmpc_global_thread_num(NULL); 111 kmp_task_t *proxy_task = __kmpc_omp_task_alloc(NULL,gtid,17,sizeof(kmp_task_t),0,&task_entry); 112 __kmpc_omp_task_with_deps(NULL,gtid,proxy_task,1,&dep_info,0,NULL); 113 114 int first_task_finished = 0; 115 #pragma omp task shared(first_task_finished) depend(inout: dep) 116 { 117 first_task_finished = 1; 118 } 119 120 int second_task_finished = 0; 121 #pragma omp task shared(second_task_finished) depend(in: dep) 122 { 123 second_task_finished = 1; 124 } 125 126 // check that execution has been resumed and the runtime has not waited 127 // for the dependencies to be satisfied. 128 int error = (first_task_finished == 1); 129 error += (second_task_finished == 1); 130 131 #pragma omp taskwait 132 133 // by now all tasks should have finished 134 error += (first_task_finished != 1); 135 error += (second_task_finished != 1); 136 137 return error; 138 } 139