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