xref: /llvm-project/openmp/runtime/test/tasking/bug_nested_proxy_task.c (revision 110141b37813dc48af33de5e1407231e56acdfc5)
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 
9624e9e13SMartin Storsjö #include <stdint.h>
1069f8511fSJonas Hahnfeld #include <stdio.h>
1169f8511fSJonas Hahnfeld #include <omp.h>
12323b4309SMartin Storsjö #include "omp_testsuite.h"
1369f8511fSJonas Hahnfeld #include "omp_my_sleep.h"
1469f8511fSJonas Hahnfeld 
1569f8511fSJonas Hahnfeld /*
1669f8511fSJonas Hahnfeld  With task dependencies one can generate proxy tasks from an explicit task
1769f8511fSJonas Hahnfeld  being executed by a serial task team. The OpenMP runtime library didn't
1869f8511fSJonas Hahnfeld  expect that and tries to free the explicit task that is the parent of the
1969f8511fSJonas Hahnfeld  proxy task still working in background. It therefore has incomplete children
2069f8511fSJonas Hahnfeld  which triggers a debugging assertion.
2169f8511fSJonas Hahnfeld */
2269f8511fSJonas Hahnfeld 
2369f8511fSJonas Hahnfeld // Compiler-generated code (emulation)
24624e9e13SMartin Storsjö typedef intptr_t kmp_intptr_t;
25624e9e13SMartin Storsjö typedef int32_t kmp_int32;
26624e9e13SMartin Storsjö typedef uint8_t kmp_uint8;
2769f8511fSJonas Hahnfeld 
2869f8511fSJonas Hahnfeld typedef char bool;
2969f8511fSJonas Hahnfeld 
304ed8fcc5SMartin Storsjö // These structs need to match the implementation within libomp, in kmp.h.
314ed8fcc5SMartin Storsjö 
3269f8511fSJonas Hahnfeld typedef struct ident {
3369f8511fSJonas Hahnfeld     kmp_int32 reserved_1;   /**<  might be used in Fortran; see above  */
3469f8511fSJonas Hahnfeld     kmp_int32 flags;        /**<  also f.flags; KMP_IDENT_xxx flags; KMP_IDENT_KMPC identifies this union member  */
3569f8511fSJonas Hahnfeld     kmp_int32 reserved_2;   /**<  not really used in Fortran any more; see above */
3669f8511fSJonas Hahnfeld #if USE_ITT_BUILD
3769f8511fSJonas Hahnfeld                             /*  but currently used for storing region-specific ITT */
3869f8511fSJonas Hahnfeld                             /*  contextual information. */
3969f8511fSJonas Hahnfeld #endif /* USE_ITT_BUILD */
4069f8511fSJonas Hahnfeld     kmp_int32 reserved_3;   /**< source[4] in Fortran, do not use for C++  */
4169f8511fSJonas Hahnfeld     char const *psource;    /**< String describing the source location.
4269f8511fSJonas Hahnfeld                             The string is composed of semi-colon separated fields which describe the source file,
4369f8511fSJonas Hahnfeld                             the function and a pair of line numbers that delimit the construct.
4469f8511fSJonas Hahnfeld                              */
4569f8511fSJonas Hahnfeld } ident_t;
4669f8511fSJonas Hahnfeld 
4769f8511fSJonas Hahnfeld typedef struct kmp_depend_info {
4869f8511fSJonas Hahnfeld      kmp_intptr_t               base_addr;
4969f8511fSJonas Hahnfeld      size_t                     len;
504ed8fcc5SMartin Storsjö      union {
514ed8fcc5SMartin Storsjö         kmp_uint8 flag; // flag as an unsigned char
524ed8fcc5SMartin Storsjö         struct { // flag as a set of 8 bits
53*110141b3SVadim Paretsky #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
547a9b0e4aSXing Xue           unsigned all : 1;
557a9b0e4aSXing Xue           unsigned unused : 3;
567a9b0e4aSXing Xue           unsigned set : 1;
577a9b0e4aSXing Xue           unsigned mtx : 1;
587a9b0e4aSXing Xue           unsigned out : 1;
597a9b0e4aSXing Xue           unsigned in : 1;
607a9b0e4aSXing Xue #else
614ed8fcc5SMartin Storsjö           unsigned in : 1;
624ed8fcc5SMartin Storsjö           unsigned out : 1;
634ed8fcc5SMartin Storsjö           unsigned mtx : 1;
644ed8fcc5SMartin Storsjö           unsigned set : 1;
654ed8fcc5SMartin Storsjö           unsigned unused : 3;
664ed8fcc5SMartin Storsjö           unsigned all : 1;
677a9b0e4aSXing Xue #endif
689ce2e5e7SAndreyChurbanov         } flags;
694ed8fcc5SMartin Storsjö      };
7069f8511fSJonas Hahnfeld } kmp_depend_info_t;
7169f8511fSJonas Hahnfeld 
7269f8511fSJonas Hahnfeld struct kmp_task;
7369f8511fSJonas Hahnfeld typedef kmp_int32 (* kmp_routine_entry_t)( kmp_int32, struct kmp_task * );
7469f8511fSJonas Hahnfeld 
7569f8511fSJonas Hahnfeld typedef struct kmp_task {                   /* GEH: Shouldn't this be aligned somehow? */
7669f8511fSJonas Hahnfeld     void *              shareds;            /**< pointer to block of pointers to shared vars   */
7769f8511fSJonas Hahnfeld     kmp_routine_entry_t routine;            /**< pointer to routine to call for executing task */
7869f8511fSJonas Hahnfeld     kmp_int32           part_id;            /**< part id for the task                          */
7969f8511fSJonas Hahnfeld } kmp_task_t;
8069f8511fSJonas Hahnfeld 
8169f8511fSJonas Hahnfeld #ifdef __cplusplus
8269f8511fSJonas Hahnfeld extern "C" {
8369f8511fSJonas Hahnfeld #endif
8469f8511fSJonas Hahnfeld kmp_int32  __kmpc_global_thread_num  ( ident_t * );
8569f8511fSJonas Hahnfeld kmp_task_t*
8669f8511fSJonas Hahnfeld __kmpc_omp_task_alloc( ident_t *loc_ref, kmp_int32 gtid, kmp_int32 flags,
8769f8511fSJonas Hahnfeld                        size_t sizeof_kmp_task_t, size_t sizeof_shareds,
8869f8511fSJonas Hahnfeld                        kmp_routine_entry_t task_entry );
8969f8511fSJonas Hahnfeld void __kmpc_proxy_task_completed_ooo ( kmp_task_t *ptask );
9069f8511fSJonas Hahnfeld kmp_int32 __kmpc_omp_task_with_deps ( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t * new_task,
9169f8511fSJonas Hahnfeld                                       kmp_int32 ndeps, kmp_depend_info_t *dep_list,
9269f8511fSJonas Hahnfeld                                       kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list );
9369f8511fSJonas Hahnfeld kmp_int32
9469f8511fSJonas Hahnfeld __kmpc_omp_task( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t * new_task );
9569f8511fSJonas Hahnfeld #ifdef __cplusplus
9669f8511fSJonas Hahnfeld }
9769f8511fSJonas Hahnfeld #endif
9869f8511fSJonas Hahnfeld 
target(void * task)9969f8511fSJonas Hahnfeld void *target(void *task)
10069f8511fSJonas Hahnfeld {
10169f8511fSJonas Hahnfeld     my_sleep( 0.1 );
10269f8511fSJonas Hahnfeld     __kmpc_proxy_task_completed_ooo((kmp_task_t*) task);
10369f8511fSJonas Hahnfeld     return NULL;
10469f8511fSJonas Hahnfeld }
10569f8511fSJonas Hahnfeld 
10669f8511fSJonas Hahnfeld pthread_t target_thread;
10769f8511fSJonas Hahnfeld 
10869f8511fSJonas Hahnfeld // User's code
task_entry(kmp_int32 gtid,kmp_task_t * task)10969f8511fSJonas Hahnfeld int task_entry(kmp_int32 gtid, kmp_task_t *task)
11069f8511fSJonas Hahnfeld {
11169f8511fSJonas Hahnfeld     pthread_create(&target_thread, NULL, &target, task);
11269f8511fSJonas Hahnfeld     return 0;
11369f8511fSJonas Hahnfeld }
11469f8511fSJonas Hahnfeld 
main()11569f8511fSJonas Hahnfeld int main()
11669f8511fSJonas Hahnfeld {
11769f8511fSJonas Hahnfeld     int dep;
11869f8511fSJonas Hahnfeld 
11969f8511fSJonas Hahnfeld #pragma omp taskgroup
12069f8511fSJonas Hahnfeld {
12169f8511fSJonas Hahnfeld /*
12269f8511fSJonas Hahnfeld  *  Corresponds to:
12369f8511fSJonas Hahnfeld     #pragma omp target nowait depend(out: dep)
12469f8511fSJonas Hahnfeld     {
12569f8511fSJonas Hahnfeld         my_sleep( 0.1 );
12669f8511fSJonas Hahnfeld     }
12769f8511fSJonas Hahnfeld */
1284ed8fcc5SMartin Storsjö     kmp_depend_info_t dep_info = { 0 };
1294ed8fcc5SMartin Storsjö     dep_info.base_addr = (kmp_intptr_t) &dep;
13069f8511fSJonas Hahnfeld     dep_info.len = sizeof(int);
13169f8511fSJonas Hahnfeld     // out = inout per spec and runtime expects this
1329ce2e5e7SAndreyChurbanov     dep_info.flags.in = 1;
1339ce2e5e7SAndreyChurbanov     dep_info.flags.out = 1;
13469f8511fSJonas Hahnfeld 
13569f8511fSJonas Hahnfeld     kmp_int32 gtid = __kmpc_global_thread_num(NULL);
13669f8511fSJonas Hahnfeld     kmp_task_t *proxy_task = __kmpc_omp_task_alloc(NULL,gtid,17,sizeof(kmp_task_t),0,&task_entry);
13769f8511fSJonas Hahnfeld     __kmpc_omp_task_with_deps(NULL,gtid,proxy_task,1,&dep_info,0,NULL);
13869f8511fSJonas Hahnfeld 
13969f8511fSJonas Hahnfeld     #pragma omp task depend(in: dep)
14069f8511fSJonas Hahnfeld     {
14169f8511fSJonas Hahnfeld /*
14269f8511fSJonas Hahnfeld  *      Corresponds to:
143479088eeSJonas Hahnfeld         #pragma omp target nowait
14469f8511fSJonas Hahnfeld         {
14569f8511fSJonas Hahnfeld             my_sleep( 0.1 );
14669f8511fSJonas Hahnfeld         }
14769f8511fSJonas Hahnfeld */
14869f8511fSJonas Hahnfeld         kmp_task_t *nested_proxy_task = __kmpc_omp_task_alloc(NULL,gtid,17,sizeof(kmp_task_t),0,&task_entry);
14969f8511fSJonas Hahnfeld         __kmpc_omp_task(NULL,gtid,nested_proxy_task);
15069f8511fSJonas Hahnfeld     }
15169f8511fSJonas Hahnfeld }
15269f8511fSJonas Hahnfeld 
15369f8511fSJonas Hahnfeld     // only check that it didn't crash
15469f8511fSJonas Hahnfeld     return 0;
15569f8511fSJonas Hahnfeld }
156