/home/runner/work/HiCR/HiCR/include/hicr/backends/nosv/executionState.hpp Source File

HiCR: /home/runner/work/HiCR/HiCR/include/hicr/backends/nosv/executionState.hpp Source File
HiCR
executionState.hpp
Go to the documentation of this file.
1/*
2 * Copyright 2025 Huawei Technologies Co., Ltd.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
23#pragma once
24
25#include <memory>
26#include <nosv.h>
27#include <nosv/affinity.h>
28#include <hicr/core/definitions.hpp>
31
34
35#ifdef ENABLE_INSTRUMENTATION
36 #include <tracr.hpp>
37#endif
38
39namespace HiCR::backend::nosv
40{
41
47{
48 public:
49
54 {
58 volatile bool mainLoop = false;
59
64 nosv_barrier_t mainLoop_barrier;
65
69 std::function<void(void *)> fc = nullptr;
70
74 void *arg = nullptr;
75
79 nosv_task_t parent_task = NULL;
80
85 };
86
91
98 __INLINE__ ExecutionState(const std::shared_ptr<HiCR::ExecutionUnit> &executionUnit, void *const argument = nullptr)
99 : HiCR::ExecutionState(executionUnit)
100 {
101 // Getting up-casted pointer of the execution unit
102 auto c = static_pointer_cast<HiCR::backend::nosv::ExecutionUnit>(executionUnit);
103
104 // Checking whether the execution unit passed is compatible with this backend
105 if (c == nullptr) HICR_THROW_LOGIC("The passed execution unit is not supported by this execution state type\n");
106
107 // Initialize the nosv type with the new defined task type and its metadata
108 check(nosv_type_init(&_executionStateTaskType, run_callback, NULL, completed_callback, "executionUnitTaskType", NULL, NULL, NOSV_TYPE_INIT_NONE));
109
110 // nosv create the execution task
111 check(nosv_create(&_executionStateTask, _executionStateTaskType, sizeof(taskMetadata_t), NOSV_CREATE_NONE));
112
113 // Access the execution state task metadata
115
116 // Store the function and function argument in the metadata
117 metadata->executionState = this;
118 metadata->fc = c->getFunction();
119 metadata->arg = argument;
120 }
121
122 protected:
123
127 __INLINE__ void resumeImpl() override
128 {
129 // Get current self task
130 nosv_task_t current_task = nosv_self();
131
132 // Access this execution state task metadata
134
135 // Store the parent task in this task
136 metadata->parent_task = current_task;
137
138 // Set the affinity of this task to be the same as the current task.
139 nosv_affinity_t self_affinity = nosv_get_task_affinity(current_task);
140 nosv_set_task_affinity(_executionStateTask, &self_affinity);
141
142 // submit (i.e. execute) the execution state task
143 check(nosv_submit(_executionStateTask, NOSV_SUBMIT_NONE));
144
145 // Pause this current task until either _executionStateTask suspends or finalized
146 check(nosv_pause(NOSV_PAUSE_NONE));
147 }
148
152 void suspendImpl() override
153 {
154 // Get current self task
155 nosv_task_t self_task = nosv_self();
156
157 // Check if the self task is actually this execution state task (otherwise is illegal as only the self task is to suspend itself)
158 if (self_task != _executionStateTask) HICR_THROW_RUNTIME("Those should be the same task. nosv_self(): %p, _executionStateTask: %p", &self_task, &_executionStateTask);
159
160 auto metadata = (taskMetadata_t *)getTaskMetadata(self_task);
161
162// TraCR set trace of thread polling again (as it suspended his task)
163#ifdef ENABLE_INSTRUMENTATION
164 INSTRUMENTATION_THREAD_MARK_SET((long)2);
165#endif
166
167 // Resume the parent task to continue running other tasks.
168 check(nosv_submit(metadata->parent_task, NOSV_SUBMIT_NONE));
169
170 // Now suspending this execution state.
171 check(nosv_pause(NOSV_PAUSE_NONE));
172 }
173
179 bool checkFinalizationImpl() override { return _completed; }
180
181 private:
182
186 static __INLINE__ void run_callback(nosv_task_t task)
187 {
188// TraCR set trace of thread executing a task
189#ifdef ENABLE_INSTRUMENTATION
190 INSTRUMENTATION_THREAD_MARK_SET((long)0);
191#endif
192
193 // Accessing metadata from the task
194 auto metadata = (taskMetadata_t *)getTaskMetadata(task);
195
196 // Unblocking the worker mainLoop as the run_callback successfully has been called from here
197 if (metadata->mainLoop) check(nosv_barrier_wait(metadata->mainLoop_barrier));
198
199 // Get the fc
200 auto fc = metadata->fc;
201
202 // Get the argument pointer to pass over the function
203 auto arg = metadata->arg;
204
205 // Executing the function (Else we throw at runtime)
206 if (fc) { fc(arg); }
207 else { HICR_THROW_RUNTIME("Error: No valid callback function.\n"); }
208
209// TraCR reset marker to nothing as otherwise nOS-V continues displaying them.
210#ifdef ENABLE_INSTRUMENTATION
211 INSTRUMENTATION_VMARKER_RESET();
212#endif
213 }
214
219 static __INLINE__ void completed_callback(nosv_task_t task)
220 {
221 auto metadata = (taskMetadata_t *)getTaskMetadata(task);
222
223 // mark task as completed
224 metadata->executionState->_completed = true;
225
226 // Resume the parent task as its child task has just finished
227 if (!(metadata->mainLoop))
228 {
229 if (!(metadata->parent_task)) HICR_THROW_RUNTIME("The parent task is not existing (i.e. NULL).");
230
231 // sleeping somehow helps the problem of this rare bug not occuring:
232 // [HiCR] Runtime Exception: Task has to be either in suspended or in finished state but I got State: 2. IsFinished: 0
233 // sleep(0.01);
234 check(nosv_submit(metadata->parent_task, NOSV_SUBMIT_UNLOCKED));
235 }
236
237 // Destroying this task
238 // TODO: Destroy a nOS-V task when no longer needed. Destroying the nOS-V task here does not work for all the TaskR examples (e.g. abcTasks and Jacobi3D).
239 // check(nosv_destroy(task, NOSV_DESTROY_NONE));
240 }
241
245 nosv_task_type_t _executionStateTaskType;
246
250 volatile bool _completed = false;
251};
252
253} // namespace HiCR::backend::nosv
This file consists of the common nOS-V function used for all the backend implementations.
void check(int error)
Definition common.hpp:41
void * getTaskMetadata(nosv_task_t task)
Definition common.hpp:56
nOS-V execution unit class. Main job is to store the function call
Definition executionState.hpp:38
Definition executionState.hpp:47
void suspendImpl() override
Definition executionState.hpp:152
nosv_task_t _executionStateTask
Definition executionState.hpp:90
__INLINE__ ExecutionState(const std::shared_ptr< HiCR::ExecutionUnit > &executionUnit, void *const argument=nullptr)
Definition executionState.hpp:98
bool checkFinalizationImpl() override
Definition executionState.hpp:179
__INLINE__ void resumeImpl() override
Definition executionState.hpp:127
Provides a base definition for a HiCR Execution State class.
Provides a failure model and corresponding exception classes.
#define HICR_THROW_RUNTIME(...)
Definition exceptions.hpp:74
#define HICR_THROW_LOGIC(...)
Definition exceptions.hpp:67
nosv_task_t parent_task
Definition executionState.hpp:79
void * arg
Definition executionState.hpp:74
nosv_barrier_t mainLoop_barrier
Definition executionState.hpp:64
ExecutionState * executionState
Definition executionState.hpp:84
volatile bool mainLoop
Definition executionState.hpp:58
std::function< void(void *)> fc
Definition executionState.hpp:69