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