1956168c8SDimitry Andric // RUN: %libomp-compile-and-run
2ca32babfSJonas Hahnfeld // The runtime currently does not get dependency information from GCC.
3ca32babfSJonas Hahnfeld // UNSUPPORTED: gcc
4ca32babfSJonas Hahnfeld
5c9ae3c5eSVitaly Buka // Very flaky on openmp-clang-x86_64-linux-debian.
6c9ae3c5eSVitaly Buka // https://bugs.llvm.org/show_bug.cgi?id=45397
7c9ae3c5eSVitaly Buka // UNSUPPORTED: linux
8c9ae3c5eSVitaly Buka
969f8511fSJonas Hahnfeld #include <stdio.h>
1069f8511fSJonas Hahnfeld #include <omp.h>
1169f8511fSJonas Hahnfeld #include <pthread.h>
1269f8511fSJonas Hahnfeld #include "omp_my_sleep.h"
1369f8511fSJonas Hahnfeld
1469f8511fSJonas Hahnfeld /*
1569f8511fSJonas Hahnfeld With task dependencies one can generate proxy tasks from an explicit task
1669f8511fSJonas Hahnfeld being executed by a serial task team. The OpenMP runtime library didn't
1769f8511fSJonas Hahnfeld expect that and tries to free the explicit task that is the parent of the
1869f8511fSJonas Hahnfeld proxy task still working in background. It therefore has incomplete children
1969f8511fSJonas Hahnfeld which triggers a debugging assertion.
2069f8511fSJonas Hahnfeld */
2169f8511fSJonas Hahnfeld
2269f8511fSJonas Hahnfeld // Compiler-generated code (emulation)
2369f8511fSJonas Hahnfeld typedef long kmp_intptr_t;
2469f8511fSJonas Hahnfeld typedef int kmp_int32;
2569f8511fSJonas Hahnfeld
2669f8511fSJonas Hahnfeld typedef char bool;
2769f8511fSJonas Hahnfeld
2869f8511fSJonas Hahnfeld typedef struct ident {
2969f8511fSJonas Hahnfeld kmp_int32 reserved_1; /**< might be used in Fortran; see above */
3069f8511fSJonas Hahnfeld kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; KMP_IDENT_KMPC identifies this union member */
3169f8511fSJonas Hahnfeld kmp_int32 reserved_2; /**< not really used in Fortran any more; see above */
3269f8511fSJonas Hahnfeld #if USE_ITT_BUILD
3369f8511fSJonas Hahnfeld /* but currently used for storing region-specific ITT */
3469f8511fSJonas Hahnfeld /* contextual information. */
3569f8511fSJonas Hahnfeld #endif /* USE_ITT_BUILD */
3669f8511fSJonas Hahnfeld kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for C++ */
3769f8511fSJonas Hahnfeld char const *psource; /**< String describing the source location.
3869f8511fSJonas Hahnfeld The string is composed of semi-colon separated fields which describe the source file,
3969f8511fSJonas Hahnfeld the function and a pair of line numbers that delimit the construct.
4069f8511fSJonas Hahnfeld */
4169f8511fSJonas Hahnfeld } ident_t;
4269f8511fSJonas Hahnfeld
4369f8511fSJonas Hahnfeld typedef struct kmp_depend_info {
4469f8511fSJonas Hahnfeld kmp_intptr_t base_addr;
4569f8511fSJonas Hahnfeld size_t len;
46*9ce2e5e7SAndreyChurbanov struct {
47*9ce2e5e7SAndreyChurbanov bool in:1;
48*9ce2e5e7SAndreyChurbanov bool out:1;
49*9ce2e5e7SAndreyChurbanov } flags;
5069f8511fSJonas Hahnfeld } kmp_depend_info_t;
5169f8511fSJonas Hahnfeld
5269f8511fSJonas Hahnfeld struct kmp_task;
5369f8511fSJonas Hahnfeld typedef kmp_int32 (* kmp_routine_entry_t)( kmp_int32, struct kmp_task * );
5469f8511fSJonas Hahnfeld
5569f8511fSJonas Hahnfeld typedef struct kmp_task { /* GEH: Shouldn't this be aligned somehow? */
5669f8511fSJonas Hahnfeld void * shareds; /**< pointer to block of pointers to shared vars */
5769f8511fSJonas Hahnfeld kmp_routine_entry_t routine; /**< pointer to routine to call for executing task */
5869f8511fSJonas Hahnfeld kmp_int32 part_id; /**< part id for the task */
5969f8511fSJonas Hahnfeld } kmp_task_t;
6069f8511fSJonas Hahnfeld
6169f8511fSJonas Hahnfeld #ifdef __cplusplus
6269f8511fSJonas Hahnfeld extern "C" {
6369f8511fSJonas Hahnfeld #endif
6469f8511fSJonas Hahnfeld kmp_int32 __kmpc_global_thread_num ( ident_t * );
6569f8511fSJonas Hahnfeld kmp_task_t*
6669f8511fSJonas Hahnfeld __kmpc_omp_task_alloc( ident_t *loc_ref, kmp_int32 gtid, kmp_int32 flags,
6769f8511fSJonas Hahnfeld size_t sizeof_kmp_task_t, size_t sizeof_shareds,
6869f8511fSJonas Hahnfeld kmp_routine_entry_t task_entry );
6969f8511fSJonas Hahnfeld void __kmpc_proxy_task_completed_ooo ( kmp_task_t *ptask );
7069f8511fSJonas Hahnfeld kmp_int32 __kmpc_omp_task_with_deps ( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t * new_task,
7169f8511fSJonas Hahnfeld kmp_int32 ndeps, kmp_depend_info_t *dep_list,
7269f8511fSJonas Hahnfeld kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list );
7369f8511fSJonas Hahnfeld kmp_int32
7469f8511fSJonas Hahnfeld __kmpc_omp_task( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t * new_task );
7569f8511fSJonas Hahnfeld #ifdef __cplusplus
7669f8511fSJonas Hahnfeld }
7769f8511fSJonas Hahnfeld #endif
7869f8511fSJonas Hahnfeld
target(void * task)7969f8511fSJonas Hahnfeld void *target(void *task)
8069f8511fSJonas Hahnfeld {
8169f8511fSJonas Hahnfeld my_sleep( 0.1 );
8269f8511fSJonas Hahnfeld __kmpc_proxy_task_completed_ooo((kmp_task_t*) task);
8369f8511fSJonas Hahnfeld return NULL;
8469f8511fSJonas Hahnfeld }
8569f8511fSJonas Hahnfeld
8669f8511fSJonas Hahnfeld pthread_t target_thread;
8769f8511fSJonas Hahnfeld
8869f8511fSJonas Hahnfeld // User's code
task_entry(kmp_int32 gtid,kmp_task_t * task)8969f8511fSJonas Hahnfeld int task_entry(kmp_int32 gtid, kmp_task_t *task)
9069f8511fSJonas Hahnfeld {
9169f8511fSJonas Hahnfeld pthread_create(&target_thread, NULL, &target, task);
9269f8511fSJonas Hahnfeld return 0;
9369f8511fSJonas Hahnfeld }
9469f8511fSJonas Hahnfeld
main()9569f8511fSJonas Hahnfeld int main()
9669f8511fSJonas Hahnfeld {
9769f8511fSJonas Hahnfeld int dep;
9869f8511fSJonas Hahnfeld
9969f8511fSJonas Hahnfeld #pragma omp taskgroup
10069f8511fSJonas Hahnfeld {
10169f8511fSJonas Hahnfeld /*
10269f8511fSJonas Hahnfeld * Corresponds to:
10369f8511fSJonas Hahnfeld #pragma omp target nowait depend(out: dep)
10469f8511fSJonas Hahnfeld {
10569f8511fSJonas Hahnfeld my_sleep( 0.1 );
10669f8511fSJonas Hahnfeld }
10769f8511fSJonas Hahnfeld */
10869f8511fSJonas Hahnfeld kmp_depend_info_t dep_info;
10969f8511fSJonas Hahnfeld dep_info.base_addr = (long) &dep;
11069f8511fSJonas Hahnfeld dep_info.len = sizeof(int);
11169f8511fSJonas Hahnfeld // out = inout per spec and runtime expects this
112*9ce2e5e7SAndreyChurbanov dep_info.flags.in = 1;
113*9ce2e5e7SAndreyChurbanov dep_info.flags.out = 1;
11469f8511fSJonas Hahnfeld
11569f8511fSJonas Hahnfeld kmp_int32 gtid = __kmpc_global_thread_num(NULL);
11669f8511fSJonas Hahnfeld kmp_task_t *proxy_task = __kmpc_omp_task_alloc(NULL,gtid,17,sizeof(kmp_task_t),0,&task_entry);
11769f8511fSJonas Hahnfeld __kmpc_omp_task_with_deps(NULL,gtid,proxy_task,1,&dep_info,0,NULL);
11869f8511fSJonas Hahnfeld
11969f8511fSJonas Hahnfeld #pragma omp task depend(in: dep)
12069f8511fSJonas Hahnfeld {
12169f8511fSJonas Hahnfeld /*
12269f8511fSJonas Hahnfeld * Corresponds to:
123479088eeSJonas Hahnfeld #pragma omp target nowait
12469f8511fSJonas Hahnfeld {
12569f8511fSJonas Hahnfeld my_sleep( 0.1 );
12669f8511fSJonas Hahnfeld }
12769f8511fSJonas Hahnfeld */
12869f8511fSJonas Hahnfeld kmp_task_t *nested_proxy_task = __kmpc_omp_task_alloc(NULL,gtid,17,sizeof(kmp_task_t),0,&task_entry);
12969f8511fSJonas Hahnfeld __kmpc_omp_task(NULL,gtid,nested_proxy_task);
13069f8511fSJonas Hahnfeld }
13169f8511fSJonas Hahnfeld }
13269f8511fSJonas Hahnfeld
13369f8511fSJonas Hahnfeld // only check that it didn't crash
13469f8511fSJonas Hahnfeld return 0;
13569f8511fSJonas Hahnfeld }
136