1*405037c4SAndrey Churbanov // RUN: %libomp-compile && env OMP_NUM_THREADS='3' %libomp-run
2*405037c4SAndrey Churbanov // RUN: %libomp-compile && env OMP_NUM_THREADS='1' %libomp-run
3*405037c4SAndrey Churbanov
4*405037c4SAndrey Churbanov #include <stdio.h>
5*405037c4SAndrey Churbanov #include <omp.h>
6*405037c4SAndrey Churbanov #include "omp_my_sleep.h"
7*405037c4SAndrey Churbanov
8*405037c4SAndrey Churbanov // detached tied
9*405037c4SAndrey Churbanov #define PTASK_FLAG_DETACHABLE 0x41
10*405037c4SAndrey Churbanov
11*405037c4SAndrey Churbanov // OpenMP RTL interfaces
12*405037c4SAndrey Churbanov typedef unsigned long long kmp_uint64;
13*405037c4SAndrey Churbanov typedef long long kmp_int64;
14*405037c4SAndrey Churbanov
15*405037c4SAndrey Churbanov typedef struct ID {
16*405037c4SAndrey Churbanov int reserved_1;
17*405037c4SAndrey Churbanov int flags;
18*405037c4SAndrey Churbanov int reserved_2;
19*405037c4SAndrey Churbanov int reserved_3;
20*405037c4SAndrey Churbanov char *psource;
21*405037c4SAndrey Churbanov } id;
22*405037c4SAndrey Churbanov
23*405037c4SAndrey Churbanov // Compiler-generated code (emulation)
24*405037c4SAndrey Churbanov typedef struct ident {
25*405037c4SAndrey Churbanov void* dummy; // not used in the library
26*405037c4SAndrey Churbanov } ident_t;
27*405037c4SAndrey Churbanov
28*405037c4SAndrey Churbanov typedef enum kmp_event_type_t {
29*405037c4SAndrey Churbanov KMP_EVENT_UNINITIALIZED = 0,
30*405037c4SAndrey Churbanov KMP_EVENT_ALLOW_COMPLETION = 1
31*405037c4SAndrey Churbanov } kmp_event_type_t;
32*405037c4SAndrey Churbanov
33*405037c4SAndrey Churbanov typedef struct {
34*405037c4SAndrey Churbanov kmp_event_type_t type;
35*405037c4SAndrey Churbanov union {
36*405037c4SAndrey Churbanov void *task;
37*405037c4SAndrey Churbanov } ed;
38*405037c4SAndrey Churbanov } kmp_event_t;
39*405037c4SAndrey Churbanov
40*405037c4SAndrey Churbanov typedef struct shar { // shareds used in the task
41*405037c4SAndrey Churbanov } *pshareds;
42*405037c4SAndrey Churbanov
43*405037c4SAndrey Churbanov typedef struct task {
44*405037c4SAndrey Churbanov pshareds shareds;
45*405037c4SAndrey Churbanov int(*routine)(int,struct task*);
46*405037c4SAndrey Churbanov int part_id;
47*405037c4SAndrey Churbanov // void *destructor_thunk; // optional, needs flag setting if provided
48*405037c4SAndrey Churbanov // int priority; // optional, needs flag setting if provided
49*405037c4SAndrey Churbanov // ------------------------------
50*405037c4SAndrey Churbanov // privates used in the task:
51*405037c4SAndrey Churbanov omp_event_handle_t evt;
52*405037c4SAndrey Churbanov } *ptask, kmp_task_t;
53*405037c4SAndrey Churbanov
54*405037c4SAndrey Churbanov typedef int(* task_entry_t)( int, ptask );
55*405037c4SAndrey Churbanov
56*405037c4SAndrey Churbanov #ifdef __cplusplus
57*405037c4SAndrey Churbanov extern "C" {
58*405037c4SAndrey Churbanov #endif
59*405037c4SAndrey Churbanov extern int __kmpc_global_thread_num(void *id_ref);
60*405037c4SAndrey Churbanov extern int** __kmpc_omp_task_alloc(id *loc, int gtid, int flags,
61*405037c4SAndrey Churbanov size_t sz, size_t shar, task_entry_t rtn);
62*405037c4SAndrey Churbanov extern int __kmpc_omp_task(id *loc, int gtid, kmp_task_t *task);
63*405037c4SAndrey Churbanov extern omp_event_handle_t __kmpc_task_allow_completion_event(
64*405037c4SAndrey Churbanov ident_t *loc_ref, int gtid, kmp_task_t *task);
65*405037c4SAndrey Churbanov #ifdef __cplusplus
66*405037c4SAndrey Churbanov }
67*405037c4SAndrey Churbanov #endif
68*405037c4SAndrey Churbanov
69*405037c4SAndrey Churbanov int volatile checker;
70*405037c4SAndrey Churbanov
71*405037c4SAndrey Churbanov // User's code, outlined into task entry
task_entry(int gtid,ptask task)72*405037c4SAndrey Churbanov int task_entry(int gtid, ptask task) {
73*405037c4SAndrey Churbanov my_sleep(2.0);
74*405037c4SAndrey Churbanov checker = 1;
75*405037c4SAndrey Churbanov return 0;
76*405037c4SAndrey Churbanov }
77*405037c4SAndrey Churbanov
main()78*405037c4SAndrey Churbanov int main() {
79*405037c4SAndrey Churbanov int i, j, gtid = __kmpc_global_thread_num(NULL);
80*405037c4SAndrey Churbanov int nt = omp_get_max_threads();
81*405037c4SAndrey Churbanov ptask task;
82*405037c4SAndrey Churbanov pshareds psh;
83*405037c4SAndrey Churbanov checker = 0;
84*405037c4SAndrey Churbanov omp_set_dynamic(0);
85*405037c4SAndrey Churbanov #pragma omp parallel //num_threads(N)
86*405037c4SAndrey Churbanov {
87*405037c4SAndrey Churbanov #pragma omp master
88*405037c4SAndrey Churbanov {
89*405037c4SAndrey Churbanov int gtid = __kmpc_global_thread_num(NULL);
90*405037c4SAndrey Churbanov omp_event_handle_t evt;
91*405037c4SAndrey Churbanov /*
92*405037c4SAndrey Churbanov #pragma omp task detach(evt)
93*405037c4SAndrey Churbanov {}
94*405037c4SAndrey Churbanov */
95*405037c4SAndrey Churbanov task = (ptask)__kmpc_omp_task_alloc(NULL,gtid,PTASK_FLAG_DETACHABLE,
96*405037c4SAndrey Churbanov sizeof(struct task),sizeof(struct shar),&task_entry);
97*405037c4SAndrey Churbanov psh = task->shareds;
98*405037c4SAndrey Churbanov evt = (omp_event_handle_t)__kmpc_task_allow_completion_event(NULL,gtid,task);
99*405037c4SAndrey Churbanov task->evt = evt;
100*405037c4SAndrey Churbanov __kmpc_omp_task(NULL, gtid, task);
101*405037c4SAndrey Churbanov omp_fulfill_event(evt);
102*405037c4SAndrey Churbanov #pragma omp taskwait
103*405037c4SAndrey Churbanov ;
104*405037c4SAndrey Churbanov // printf("after tw %d\n", omp_get_thread_num());
105*405037c4SAndrey Churbanov } // end master
106*405037c4SAndrey Churbanov } // end parallel
107*405037c4SAndrey Churbanov
108*405037c4SAndrey Churbanov // check results
109*405037c4SAndrey Churbanov if (checker == 1) {
110*405037c4SAndrey Churbanov printf("passed\n");
111*405037c4SAndrey Churbanov return 0;
112*405037c4SAndrey Churbanov } else {
113*405037c4SAndrey Churbanov printf("failed\n");
114*405037c4SAndrey Churbanov return 1;
115*405037c4SAndrey Churbanov }
116*405037c4SAndrey Churbanov }
117