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 34 uint32_t TId = mapping::getThreadIdInBlock(); 35 36 do { 37 ParallelRegionFnTy WorkFn = 0; 38 39 // Wait for the signal that we have a new work function. 40 synchronize::threads(); 41 42 // Retrieve the work function from the runtime. 43 bool IsActive = __kmpc_kernel_parallel(&WorkFn); 44 45 // If there is nothing more to do, break out of the state machine by 46 // returning to the caller. 47 if (!WorkFn) 48 return; 49 50 if (IsActive) { 51 ASSERT(!mapping::isSPMDMode()); 52 ((void (*)(uint32_t, uint32_t))WorkFn)(0, TId); 53 __kmpc_kernel_end_parallel(); 54 } 55 56 synchronize::threads(); 57 58 } while (true); 59 } 60 61 extern "C" { 62 63 /// Initialization 64 /// 65 /// \param Ident Source location identification, can be NULL. 66 /// 67 int32_t __kmpc_target_init(IdentTy *Ident, int8_t Mode, 68 bool UseGenericStateMachine, bool) { 69 const bool IsSPMD = Mode & OMP_TGT_EXEC_MODE_SPMD; 70 if (IsSPMD) { 71 inititializeRuntime(/* IsSPMD */ true); 72 synchronize::threads(); 73 } else { 74 inititializeRuntime(/* IsSPMD */ false); 75 // No need to wait since only the main threads will execute user 76 // code and workers will run into a barrier right away. 77 } 78 79 if (IsSPMD) { 80 state::assumeInitialState(IsSPMD); 81 return -1; 82 } 83 84 if (mapping::isMainThreadInGenericMode(IsSPMD)) 85 return -1; 86 87 if (UseGenericStateMachine) 88 genericStateMachine(Ident); 89 90 return mapping::getThreadIdInBlock(); 91 } 92 93 /// De-Initialization 94 /// 95 /// In non-SPMD, this function releases the workers trapped in a state machine 96 /// and also any memory dynamically allocated by the runtime. 97 /// 98 /// \param Ident Source location identification, can be NULL. 99 /// 100 void __kmpc_target_deinit(IdentTy *Ident, int8_t Mode, bool) { 101 const bool IsSPMD = Mode & OMP_TGT_EXEC_MODE_SPMD; 102 state::assumeInitialState(IsSPMD); 103 if (IsSPMD) 104 return; 105 106 // Signal the workers to exit the state machine and exit the kernel. 107 state::ParallelRegionFn = nullptr; 108 } 109 110 int8_t __kmpc_is_spmd_exec_mode() { return mapping::isSPMDMode(); } 111 } 112 113 #pragma omp end declare target 114