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, bool IsSPMD,
68                            bool UseGenericStateMachine, bool) {
69   if (IsSPMD) {
70     inititializeRuntime(/* IsSPMD */ true);
71     synchronize::threads();
72   } else {
73     inititializeRuntime(/* IsSPMD */ false);
74     // No need to wait since only the main threads will execute user
75     // code and workers will run into a barrier right away.
76   }
77 
78   if (IsSPMD) {
79     state::assumeInitialState(IsSPMD);
80     return -1;
81   }
82 
83   if (mapping::isMainThreadInGenericMode())
84     return -1;
85 
86   if (UseGenericStateMachine)
87     genericStateMachine(Ident);
88 
89   return mapping::getThreadIdInBlock();
90 }
91 
92 /// De-Initialization
93 ///
94 /// In non-SPMD, this function releases the workers trapped in a state machine
95 /// and also any memory dynamically allocated by the runtime.
96 ///
97 /// \param Ident Source location identification, can be NULL.
98 ///
99 void __kmpc_target_deinit(IdentTy *Ident, bool IsSPMD, bool) {
100   state::assumeInitialState(IsSPMD);
101   if (IsSPMD)
102     return;
103 
104   // Signal the workers to exit the state machine and exit the kernel.
105   state::ParallelRegionFn = nullptr;
106 }
107 
108 int8_t __kmpc_is_spmd_exec_mode() { return mapping::isSPMDMode(); }
109 }
110 
111 #pragma omp end declare target
112