1 //===--- Kernel.cpp - OpenMP device kernel interface -------------- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains the kernel entry points for the device. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "Debug.h" 14 #include "Interface.h" 15 #include "Mapping.h" 16 #include "State.h" 17 #include "Synchronization.h" 18 #include "Types.h" 19 20 using namespace _OMP; 21 22 #pragma omp declare target 23 24 static void inititializeRuntime(bool IsSPMD) { 25 // Order is important here. 26 synchronize::init(IsSPMD); 27 mapping::init(IsSPMD); 28 state::init(IsSPMD); 29 } 30 31 /// Simple generic state machine for worker threads. 32 static void genericStateMachine(IdentTy *Ident) { 33 FunctionTracingRAII(); 34 35 uint32_t TId = mapping::getThreadIdInBlock(); 36 37 do { 38 ParallelRegionFnTy WorkFn = 0; 39 40 // Wait for the signal that we have a new work function. 41 synchronize::threads(); 42 43 // Retrieve the work function from the runtime. 44 bool IsActive = __kmpc_kernel_parallel(&WorkFn); 45 46 // If there is nothing more to do, break out of the state machine by 47 // returning to the caller. 48 if (!WorkFn) 49 return; 50 51 if (IsActive) { 52 ASSERT(!mapping::isSPMDMode()); 53 ((void (*)(uint32_t, uint32_t))WorkFn)(0, TId); 54 __kmpc_kernel_end_parallel(); 55 } 56 57 synchronize::threads(); 58 59 } while (true); 60 } 61 62 extern "C" { 63 64 /// Initialization 65 /// 66 /// \param Ident Source location identification, can be NULL. 67 /// 68 int32_t __kmpc_target_init(IdentTy *Ident, int8_t Mode, 69 bool UseGenericStateMachine, bool) { 70 FunctionTracingRAII(); 71 const bool IsSPMD = Mode & OMP_TGT_EXEC_MODE_SPMD; 72 if (IsSPMD) { 73 inititializeRuntime(/* IsSPMD */ true); 74 synchronize::threadsAligned(); 75 } else { 76 inititializeRuntime(/* IsSPMD */ false); 77 // No need to wait since only the main threads will execute user 78 // code and workers will run into a barrier right away. 79 } 80 81 if (IsSPMD) { 82 state::assumeInitialState(IsSPMD); 83 return -1; 84 } 85 86 if (mapping::isInitialThreadInLevel0(IsSPMD)) 87 return -1; 88 89 if (UseGenericStateMachine) 90 genericStateMachine(Ident); 91 92 return mapping::getThreadIdInBlock(); 93 } 94 95 /// De-Initialization 96 /// 97 /// In non-SPMD, this function releases the workers trapped in a state machine 98 /// and also any memory dynamically allocated by the runtime. 99 /// 100 /// \param Ident Source location identification, can be NULL. 101 /// 102 void __kmpc_target_deinit(IdentTy *Ident, int8_t Mode, bool) { 103 FunctionTracingRAII(); 104 const bool IsSPMD = Mode & OMP_TGT_EXEC_MODE_SPMD; 105 state::assumeInitialState(IsSPMD); 106 if (IsSPMD) 107 return; 108 109 // Signal the workers to exit the state machine and exit the kernel. 110 state::ParallelRegionFn = nullptr; 111 } 112 113 int8_t __kmpc_is_spmd_exec_mode() { 114 FunctionTracingRAII(); 115 return mapping::isSPMDMode(); 116 } 117 } 118 119 #pragma omp end declare target 120