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
target(void * task)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
task_entry(kmp_int32 gtid,kmp_task_t * task)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
main()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