1 //===-------- interface.cpp - Target independent OpenMP target RTL --------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.txt for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Implementation of the interface to be used by Clang during the codegen of a 11 // target region. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include <omptarget.h> 16 17 #include "device.h" 18 #include "private.h" 19 #include "rtl.h" 20 21 #include <cassert> 22 #include <cstdlib> 23 #include <stdarg.h> 24 #include <mutex> 25 26 // Store target policy (disabled, mandatory, default) 27 kmp_target_offload_kind_t TargetOffloadPolicy = tgt_default; 28 std::mutex TargetOffloadMtx; 29 30 //////////////////////////////////////////////////////////////////////////////// 31 /// manage the success or failure of a target constuct 32 33 static void HandleDefaultTargetOffload() { 34 TargetOffloadMtx.lock(); 35 if (TargetOffloadPolicy == tgt_default) { 36 if (omp_get_num_devices() > 0) { 37 DP("Default TARGET OFFLOAD policy is now mandatory " 38 "(devicew were found)\n"); 39 TargetOffloadPolicy = tgt_mandatory; 40 } else { 41 DP("Default TARGET OFFLOAD policy is now disabled " 42 "(devices were not found)\n"); 43 TargetOffloadPolicy = tgt_disabled; 44 } 45 } 46 TargetOffloadMtx.unlock(); 47 } 48 49 static int IsOffloadDisabled() { 50 if (TargetOffloadPolicy == tgt_default) HandleDefaultTargetOffload(); 51 return TargetOffloadPolicy == tgt_disabled; 52 } 53 54 static void HandleTargetOutcome(bool success) { 55 switch (TargetOffloadPolicy) { 56 case tgt_disabled: 57 if (success) { 58 FATAL_MESSAGE0(1, "expected no offloading while offloading is disabled"); 59 } 60 break; 61 case tgt_default: 62 FATAL_MESSAGE0(1, "default offloading policy must switched to " 63 "mandatory or disabled"); 64 break; 65 case tgt_mandatory: 66 if (!success) { 67 FATAL_MESSAGE0(1, "failure of target construct while offloading is mandatory"); 68 } 69 break; 70 } 71 } 72 73 //////////////////////////////////////////////////////////////////////////////// 74 /// adds a target shared library to the target execution image 75 EXTERN void __tgt_register_lib(__tgt_bin_desc *desc) { 76 RTLs.RegisterLib(desc); 77 } 78 79 //////////////////////////////////////////////////////////////////////////////// 80 /// unloads a target shared library 81 EXTERN void __tgt_unregister_lib(__tgt_bin_desc *desc) { 82 RTLs.UnregisterLib(desc); 83 } 84 85 /// creates host-to-target data mapping, stores it in the 86 /// libomptarget.so internal structure (an entry in a stack of data maps) 87 /// and passes the data to the device. 88 EXTERN void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 89 void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types) { 90 if (IsOffloadDisabled()) return; 91 92 DP("Entering data begin region for device %" PRId64 " with %d mappings\n", 93 device_id, arg_num); 94 95 // No devices available? 96 if (device_id == OFFLOAD_DEVICE_DEFAULT) { 97 device_id = omp_get_default_device(); 98 DP("Use default device id %" PRId64 "\n", device_id); 99 } 100 101 if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) { 102 DP("Failed to get device %" PRId64 " ready\n", device_id); 103 HandleTargetOutcome(false); 104 return; 105 } 106 107 DeviceTy& Device = Devices[device_id]; 108 109 #ifdef OMPTARGET_DEBUG 110 for (int i=0; i<arg_num; ++i) { 111 DP("Entry %2d: Base=" DPxMOD ", Begin=" DPxMOD ", Size=%" PRId64 112 ", Type=0x%" PRIx64 "\n", i, DPxPTR(args_base[i]), DPxPTR(args[i]), 113 arg_sizes[i], arg_types[i]); 114 } 115 #endif 116 117 int rc = target_data_begin(Device, arg_num, args_base, 118 args, arg_sizes, arg_types); 119 HandleTargetOutcome(rc == OFFLOAD_SUCCESS); 120 } 121 122 EXTERN void __tgt_target_data_begin_nowait(int64_t device_id, int32_t arg_num, 123 void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types, 124 int32_t depNum, void *depList, int32_t noAliasDepNum, 125 void *noAliasDepList) { 126 if (depNum + noAliasDepNum > 0) 127 __kmpc_omp_taskwait(NULL, 0); 128 129 __tgt_target_data_begin(device_id, arg_num, args_base, args, arg_sizes, 130 arg_types); 131 } 132 133 /// passes data from the target, releases target memory and destroys 134 /// the host-target mapping (top entry from the stack of data maps) 135 /// created by the last __tgt_target_data_begin. 136 EXTERN void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 137 void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types) { 138 if (IsOffloadDisabled()) return; 139 DP("Entering data end region with %d mappings\n", arg_num); 140 141 // No devices available? 142 if (device_id == OFFLOAD_DEVICE_DEFAULT) { 143 device_id = omp_get_default_device(); 144 } 145 146 RTLsMtx.lock(); 147 size_t Devices_size = Devices.size(); 148 RTLsMtx.unlock(); 149 if (Devices_size <= (size_t)device_id) { 150 DP("Device ID %" PRId64 " does not have a matching RTL.\n", device_id); 151 HandleTargetOutcome(false); 152 return; 153 } 154 155 DeviceTy &Device = Devices[device_id]; 156 if (!Device.IsInit) { 157 DP("Uninit device: ignore"); 158 HandleTargetOutcome(false); 159 return; 160 } 161 162 #ifdef OMPTARGET_DEBUG 163 for (int i=0; i<arg_num; ++i) { 164 DP("Entry %2d: Base=" DPxMOD ", Begin=" DPxMOD ", Size=%" PRId64 165 ", Type=0x%" PRIx64 "\n", i, DPxPTR(args_base[i]), DPxPTR(args[i]), 166 arg_sizes[i], arg_types[i]); 167 } 168 #endif 169 170 int rc = target_data_end(Device, arg_num, args_base, 171 args, arg_sizes, arg_types); 172 HandleTargetOutcome(rc == OFFLOAD_SUCCESS); 173 } 174 175 EXTERN void __tgt_target_data_end_nowait(int64_t device_id, int32_t arg_num, 176 void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types, 177 int32_t depNum, void *depList, int32_t noAliasDepNum, 178 void *noAliasDepList) { 179 if (depNum + noAliasDepNum > 0) 180 __kmpc_omp_taskwait(NULL, 0); 181 182 __tgt_target_data_end(device_id, arg_num, args_base, args, arg_sizes, 183 arg_types); 184 } 185 186 EXTERN void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 187 void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types) { 188 if (IsOffloadDisabled()) return; 189 DP("Entering data update with %d mappings\n", arg_num); 190 191 // No devices available? 192 if (device_id == OFFLOAD_DEVICE_DEFAULT) { 193 device_id = omp_get_default_device(); 194 } 195 196 if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) { 197 DP("Failed to get device %" PRId64 " ready\n", device_id); 198 HandleTargetOutcome(false); 199 return; 200 } 201 202 DeviceTy& Device = Devices[device_id]; 203 int rc = target_data_update(Device, arg_num, args_base, 204 args, arg_sizes, arg_types); 205 HandleTargetOutcome(rc == OFFLOAD_SUCCESS); 206 } 207 208 EXTERN void __tgt_target_data_update_nowait( 209 int64_t device_id, int32_t arg_num, void **args_base, void **args, 210 int64_t *arg_sizes, int64_t *arg_types, int32_t depNum, void *depList, 211 int32_t noAliasDepNum, void *noAliasDepList) { 212 if (depNum + noAliasDepNum > 0) 213 __kmpc_omp_taskwait(NULL, 0); 214 215 __tgt_target_data_update(device_id, arg_num, args_base, args, arg_sizes, 216 arg_types); 217 } 218 219 EXTERN int __tgt_target(int64_t device_id, void *host_ptr, int32_t arg_num, 220 void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types) { 221 if (IsOffloadDisabled()) return OFFLOAD_FAIL; 222 DP("Entering target region with entry point " DPxMOD " and device Id %" 223 PRId64 "\n", DPxPTR(host_ptr), device_id); 224 225 if (device_id == OFFLOAD_DEVICE_DEFAULT) { 226 device_id = omp_get_default_device(); 227 } 228 229 if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) { 230 DP("Failed to get device %" PRId64 " ready\n", device_id); 231 HandleTargetOutcome(false); 232 return OFFLOAD_FAIL; 233 } 234 235 #ifdef OMPTARGET_DEBUG 236 for (int i=0; i<arg_num; ++i) { 237 DP("Entry %2d: Base=" DPxMOD ", Begin=" DPxMOD ", Size=%" PRId64 238 ", Type=0x%" PRIx64 "\n", i, DPxPTR(args_base[i]), DPxPTR(args[i]), 239 arg_sizes[i], arg_types[i]); 240 } 241 #endif 242 243 int rc = target(device_id, host_ptr, arg_num, args_base, args, arg_sizes, 244 arg_types, 0, 0, false /*team*/); 245 HandleTargetOutcome(rc == OFFLOAD_SUCCESS); 246 return rc; 247 } 248 249 EXTERN int __tgt_target_nowait(int64_t device_id, void *host_ptr, 250 int32_t arg_num, void **args_base, void **args, int64_t *arg_sizes, 251 int64_t *arg_types, int32_t depNum, void *depList, int32_t noAliasDepNum, 252 void *noAliasDepList) { 253 if (depNum + noAliasDepNum > 0) 254 __kmpc_omp_taskwait(NULL, 0); 255 256 return __tgt_target(device_id, host_ptr, arg_num, args_base, args, arg_sizes, 257 arg_types); 258 } 259 260 EXTERN int __tgt_target_teams(int64_t device_id, void *host_ptr, 261 int32_t arg_num, void **args_base, void **args, int64_t *arg_sizes, 262 int64_t *arg_types, int32_t team_num, int32_t thread_limit) { 263 if (IsOffloadDisabled()) return OFFLOAD_FAIL; 264 DP("Entering target region with entry point " DPxMOD " and device Id %" 265 PRId64 "\n", DPxPTR(host_ptr), device_id); 266 267 if (device_id == OFFLOAD_DEVICE_DEFAULT) { 268 device_id = omp_get_default_device(); 269 } 270 271 if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) { 272 DP("Failed to get device %" PRId64 " ready\n", device_id); 273 HandleTargetOutcome(false); 274 return OFFLOAD_FAIL; 275 } 276 277 #ifdef OMPTARGET_DEBUG 278 for (int i=0; i<arg_num; ++i) { 279 DP("Entry %2d: Base=" DPxMOD ", Begin=" DPxMOD ", Size=%" PRId64 280 ", Type=0x%" PRIx64 "\n", i, DPxPTR(args_base[i]), DPxPTR(args[i]), 281 arg_sizes[i], arg_types[i]); 282 } 283 #endif 284 285 int rc = target(device_id, host_ptr, arg_num, args_base, args, arg_sizes, 286 arg_types, team_num, thread_limit, true /*team*/); 287 HandleTargetOutcome(rc == OFFLOAD_SUCCESS); 288 289 return rc; 290 } 291 292 EXTERN int __tgt_target_teams_nowait(int64_t device_id, void *host_ptr, 293 int32_t arg_num, void **args_base, void **args, int64_t *arg_sizes, 294 int64_t *arg_types, int32_t team_num, int32_t thread_limit, int32_t depNum, 295 void *depList, int32_t noAliasDepNum, void *noAliasDepList) { 296 if (depNum + noAliasDepNum > 0) 297 __kmpc_omp_taskwait(NULL, 0); 298 299 return __tgt_target_teams(device_id, host_ptr, arg_num, args_base, args, 300 arg_sizes, arg_types, team_num, thread_limit); 301 } 302 303 304 // The trip count mechanism will be revised - this scheme is not thread-safe. 305 EXTERN void __kmpc_push_target_tripcount(int64_t device_id, 306 uint64_t loop_tripcount) { 307 if (device_id == OFFLOAD_DEVICE_DEFAULT) { 308 device_id = omp_get_default_device(); 309 } 310 311 if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) { 312 DP("Failed to get device %" PRId64 " ready\n", device_id); 313 HandleTargetOutcome(false); 314 return; 315 } 316 317 DP("__kmpc_push_target_tripcount(%" PRId64 ", %" PRIu64 ")\n", device_id, 318 loop_tripcount); 319 Devices[device_id].loopTripCnt = loop_tripcount; 320 } 321