1 | //===-------- Tasking.cpp - NVPTX OpenMP tasks support ------------ 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 | // Task implementation support. |
10 | // |
11 | // TODO: We should not allocate and execute the task in two steps. A new API is |
12 | // needed for that though. |
13 | // |
14 | //===----------------------------------------------------------------------===// |
15 | |
16 | #include "DeviceTypes.h" |
17 | #include "DeviceUtils.h" |
18 | #include "Interface.h" |
19 | #include "State.h" |
20 | |
21 | using namespace ompx; |
22 | |
23 | extern "C" { |
24 | |
25 | TaskDescriptorTy *__kmpc_omp_task_alloc(IdentTy *, int32_t, int32_t, |
26 | size_t TaskSizeInclPrivateValues, |
27 | size_t SharedValuesSize, |
28 | TaskFnTy TaskFn) { |
29 | auto TaskSizeInclPrivateValuesPadded = |
30 | utils::roundUp(TaskSizeInclPrivateValues, sizeof(void *)); |
31 | auto TaskSizeTotal = TaskSizeInclPrivateValuesPadded + SharedValuesSize; |
32 | TaskDescriptorTy *TaskDescriptor = (TaskDescriptorTy *)memory::allocGlobal( |
33 | TaskSizeTotal, "explicit task descriptor" ); |
34 | TaskDescriptor->Payload = |
35 | utils::advancePtr(TaskDescriptor, TaskSizeInclPrivateValuesPadded); |
36 | TaskDescriptor->TaskFn = TaskFn; |
37 | |
38 | return TaskDescriptor; |
39 | } |
40 | |
41 | int32_t __kmpc_omp_task(IdentTy *Loc, uint32_t TId, |
42 | TaskDescriptorTy *TaskDescriptor) { |
43 | return __kmpc_omp_task_with_deps(Loc, TId, TaskDescriptor, 0, 0, 0, 0); |
44 | } |
45 | |
46 | int32_t __kmpc_omp_task_with_deps(IdentTy *Loc, uint32_t TId, |
47 | TaskDescriptorTy *TaskDescriptor, int32_t, |
48 | void *, int32_t, void *) { |
49 | state::DateEnvironmentRAII DERAII(Loc); |
50 | |
51 | TaskDescriptor->TaskFn(0, TaskDescriptor); |
52 | |
53 | memory::freeGlobal(TaskDescriptor, "explicit task descriptor" ); |
54 | return 0; |
55 | } |
56 | |
57 | void __kmpc_omp_task_begin_if0(IdentTy *Loc, uint32_t TId, |
58 | TaskDescriptorTy *TaskDescriptor) { |
59 | state::enterDataEnvironment(Loc); |
60 | } |
61 | |
62 | void __kmpc_omp_task_complete_if0(IdentTy *Loc, uint32_t TId, |
63 | TaskDescriptorTy *TaskDescriptor) { |
64 | state::exitDataEnvironment(); |
65 | |
66 | memory::freeGlobal(TaskDescriptor, "explicit task descriptor" ); |
67 | } |
68 | |
69 | void __kmpc_omp_wait_deps(IdentTy *Loc, uint32_t TId, int32_t, void *, int32_t, |
70 | void *) {} |
71 | |
72 | void __kmpc_taskgroup(IdentTy *Loc, uint32_t TId) {} |
73 | |
74 | void __kmpc_end_taskgroup(IdentTy *Loc, uint32_t TId) {} |
75 | |
76 | int32_t __kmpc_omp_taskyield(IdentTy *Loc, uint32_t TId, int) { return 0; } |
77 | |
78 | int32_t __kmpc_omp_taskwait(IdentTy *Loc, uint32_t TId) { return 0; } |
79 | |
80 | void __kmpc_taskloop(IdentTy *Loc, uint32_t TId, |
81 | TaskDescriptorTy *TaskDescriptor, int, |
82 | uint64_t *LowerBound, uint64_t *UpperBound, int64_t, int, |
83 | int32_t, uint64_t, void *) { |
84 | // Skip task entirely if empty iteration space. |
85 | if (*LowerBound > *UpperBound) |
86 | return; |
87 | |
88 | // The compiler has already stored lb and ub in the TaskDescriptorTy structure |
89 | // as we are using a single task to execute the entire loop, we can leave |
90 | // the initial task_t untouched |
91 | __kmpc_omp_task_with_deps(Loc, TId, TaskDescriptor, 0, 0, 0, 0); |
92 | } |
93 | |
94 | int omp_in_final(void) { |
95 | // treat all tasks as final... Specs may expect runtime to keep |
96 | // track more precisely if a task was actively set by users... This |
97 | // is not explicitly specified; will treat as if runtime can |
98 | // actively decide to put a non-final task into a final one. |
99 | return 1; |
100 | } |
101 | |
102 | int omp_get_max_task_priority(void) { return 0; } |
103 | } |
104 | |