Index: libomptarget/src/device.h =================================================================== --- libomptarget/src/device.h +++ libomptarget/src/device.h @@ -29,6 +29,16 @@ #define INF_REF_CNT (LONG_MAX>>1) // leave room for additions/subtractions #define CONSIDERED_INF(x) (x > (INF_REF_CNT>>1)) +enum TargetOffloadPolicyEnum { + // forces all target computation on device if presemt, on the host if not present + OMP_TARGET_OFFLOAD_DEFAULT = 0, + // forces all target computations on the host + OMP_TARGET_OFFLOAD_DISABLED = 1, + // forces all target computations on the devices, abort if failed to execute on device + OMP_TARGET_OFFLOAD_MANDATORY = 2 +}; + + /// Map between host data and target data. struct HostDataToTargetTy { uintptr_t HstPtrBase; // host info. @@ -161,7 +171,8 @@ /// Map between Device ID (i.e. openmp device id) and its DeviceTy. typedef std::vector DevicesTy; extern DevicesTy Devices; - +extern TargetOffloadPolicyEnum TargetOffloadPolicy; extern bool device_is_ready(int device_num); +extern void handle_target_outcome(bool success); #endif Index: libomptarget/src/device.cpp =================================================================== --- libomptarget/src/device.cpp +++ libomptarget/src/device.cpp @@ -21,6 +21,8 @@ /// Map between Device ID (i.e. openmp device id) and its DeviceTy. DevicesTy Devices; +// Store target policy (disabled, mandatory, default) +TargetOffloadPolicyEnum TargetOffloadPolicy; int DeviceTy::associatePtr(void *HstPtrBegin, void *TgtPtrBegin, int64_t Size) { DataMapMtx.lock(); @@ -363,3 +365,34 @@ return true; } + +// manage the success or failure of a target constuct +void handle_target_outcome(bool success) +{ + switch (TargetOffloadPolicy) { + case OMP_TARGET_OFFLOAD_DEFAULT: + // if we have a success, now all computations must go to device + if (success) { + DP("Default TARGET OFFLOAD policy is now mandatory " + "(due to successful handling of a target construct)"); + TargetOffloadPolicy = OMP_TARGET_OFFLOAD_MANDATORY; + } else { + DP("Default TARGET OFFLOAD policy is now disabled " + "(due to unsuccessful handling of a target construct)"); + TargetOffloadPolicy = OMP_TARGET_OFFLOAD_DISABLED; + } + break; + case OMP_TARGET_OFFLOAD_MANDATORY: + if (! success) { + DP("failure of target construct when expecting to successfully offload"); + assert(success); + } + break; + case OMP_TARGET_OFFLOAD_DISABLED: + if (success) { + DP("failure of target construct when expecting to fail offloading"); + assert(! success); + } + break; + } +} Index: libomptarget/src/interface.cpp =================================================================== --- libomptarget/src/interface.cpp +++ libomptarget/src/interface.cpp @@ -49,6 +49,7 @@ if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) { DP("Failed to get device %" PRId64 " ready\n", device_id); + handle_target_outcome(false); return; } @@ -62,7 +63,9 @@ } #endif - target_data_begin(Device, arg_num, args_base, args, arg_sizes, arg_types); + int rc = target_data_begin(Device, arg_num, args_base, + args, arg_sizes, arg_types); + handle_target_outcome(rc == OFFLOAD_SUCCESS); } EXTERN void __tgt_target_data_begin_nowait(int64_t device_id, int32_t arg_num, @@ -93,12 +96,14 @@ RTLsMtx.unlock(); if (Devices_size <= (size_t)device_id) { DP("Device ID %" PRId64 " does not have a matching RTL.\n", device_id); + handle_target_outcome(false); return; } DeviceTy &Device = Devices[device_id]; if (!Device.IsInit) { DP("Uninit device: ignore"); + handle_target_outcome(false); return; } @@ -110,7 +115,9 @@ } #endif - target_data_end(Device, arg_num, args_base, args, arg_sizes, arg_types); + int rc = target_data_end(Device, arg_num, args_base, + args, arg_sizes, arg_types); + handle_target_outcome(rc == OFFLOAD_SUCCESS); } EXTERN void __tgt_target_data_end_nowait(int64_t device_id, int32_t arg_num, @@ -135,11 +142,14 @@ if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) { DP("Failed to get device %" PRId64 " ready\n", device_id); + handle_target_outcome(false); return; } DeviceTy& Device = Devices[device_id]; - target_data_update(Device, arg_num, args_base, args, arg_sizes, arg_types); + int rc = target_data_update(Device, arg_num, args_base, + args, arg_sizes, arg_types); + handle_target_outcome(rc == OFFLOAD_SUCCESS); } EXTERN void __tgt_target_data_update_nowait( @@ -164,6 +174,7 @@ if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) { DP("Failed to get device %" PRId64 " ready\n", device_id); + handle_target_outcome(false); return OFFLOAD_FAIL; } @@ -177,7 +188,7 @@ int rc = target(device_id, host_ptr, arg_num, args_base, args, arg_sizes, arg_types, 0, 0, false /*team*/); - + handle_target_outcome(rc == OFFLOAD_SUCCESS); return rc; } @@ -204,6 +215,7 @@ if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) { DP("Failed to get device %" PRId64 " ready\n", device_id); + handle_target_outcome(false); return OFFLOAD_FAIL; } @@ -217,6 +229,7 @@ int rc = target(device_id, host_ptr, arg_num, args_base, args, arg_sizes, arg_types, team_num, thread_limit, true /*team*/); + handle_target_outcome(rc == OFFLOAD_SUCCESS); return rc; } @@ -242,6 +255,7 @@ if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) { DP("Failed to get device %" PRId64 " ready\n", device_id); + handle_target_outcome(false); return; } Index: libomptarget/src/omptarget.cpp =================================================================== --- libomptarget/src/omptarget.cpp +++ libomptarget/src/omptarget.cpp @@ -457,7 +457,7 @@ } /// Internal function to pass data to/from the target. -void target_data_update(DeviceTy &Device, int32_t arg_num, +int target_data_update(DeviceTy &Device, int32_t arg_num, void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types) { // process each input. for (int32_t i = 0; i < arg_num; ++i) { @@ -474,7 +474,11 @@ if (arg_types[i] & OMP_TGT_MAPTYPE_FROM) { DP("Moving %" PRId64 " bytes (tgt:" DPxMOD ") -> (hst:" DPxMOD ")\n", arg_sizes[i], DPxPTR(TgtPtrBegin), DPxPTR(HstPtrBegin)); - Device.data_retrieve(HstPtrBegin, TgtPtrBegin, MapSize); + int rt = Device.data_retrieve(HstPtrBegin, TgtPtrBegin, MapSize); + if (rt != OFFLOAD_SUCCESS) { + DP("Copying data from device failed.\n"); + return OFFLOAD_FAIL; + } uintptr_t lb = (uintptr_t) HstPtrBegin; uintptr_t ub = (uintptr_t) HstPtrBegin + MapSize; @@ -497,8 +501,11 @@ if (arg_types[i] & OMP_TGT_MAPTYPE_TO) { DP("Moving %" PRId64 " bytes (hst:" DPxMOD ") -> (tgt:" DPxMOD ")\n", arg_sizes[i], DPxPTR(HstPtrBegin), DPxPTR(TgtPtrBegin)); - Device.data_submit(TgtPtrBegin, HstPtrBegin, MapSize); - + int rt = Device.data_submit(TgtPtrBegin, HstPtrBegin, MapSize); + if (rt != OFFLOAD_SUCCESS) { + DP("Copying data to device failed.\n"); + return OFFLOAD_FAIL; + } uintptr_t lb = (uintptr_t) HstPtrBegin; uintptr_t ub = (uintptr_t) HstPtrBegin + MapSize; Device.ShadowMtx.lock(); @@ -512,12 +519,17 @@ DP("Restoring original target pointer value " DPxMOD " for target " "pointer " DPxMOD "\n", DPxPTR(it->second.TgtPtrVal), DPxPTR(it->second.TgtPtrAddr)); - Device.data_submit(it->second.TgtPtrAddr, + rt = Device.data_submit(it->second.TgtPtrAddr, &it->second.TgtPtrVal, sizeof(void *)); + if (rt != OFFLOAD_SUCCESS) { + DP("Copying data to device failed.\n"); + return OFFLOAD_FAIL; + } } Device.ShadowMtx.unlock(); } } + return OFFLOAD_SUCCESS; } /// performs the same actions as data_begin in case arg_num is Index: libomptarget/src/private.h =================================================================== --- libomptarget/src/private.h +++ libomptarget/src/private.h @@ -24,7 +24,7 @@ extern int target_data_end(DeviceTy &Device, int32_t arg_num, void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); -extern void target_data_update(DeviceTy &Device, int32_t arg_num, +extern int target_data_update(DeviceTy &Device, int32_t arg_num, void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); extern int target(int64_t device_id, void *host_ptr, int32_t arg_num, @@ -42,7 +42,6 @@ #ifdef __cplusplus } #endif - #ifdef OMPTARGET_DEBUG extern int DebugLevel; Index: libomptarget/src/rtl.cpp =================================================================== --- libomptarget/src/rtl.cpp +++ libomptarget/src/rtl.cpp @@ -46,10 +46,21 @@ #endif // OMPTARGET_DEBUG // Parse environment variable OMP_TARGET_OFFLOAD (if set) + TargetOffloadPolicy = OMP_TARGET_OFFLOAD_DEFAULT; char *envStr = getenv("OMP_TARGET_OFFLOAD"); - if (envStr && !strcmp(envStr, "DISABLED")) { - DP("Target offloading disabled by environment\n"); - return; + if (envStr) { + if (!strcmp(envStr, "DISABLED")) { + DP("Target offloading disabled by environment\n"); + TargetOffloadPolicy = OMP_TARGET_OFFLOAD_DISABLED; + return; + } else if (!strcmp(envStr, "MANDATORY")) { + DP("Target offloading forced to be mandatory by environment\n"); + TargetOffloadPolicy = OMP_TARGET_OFFLOAD_MANDATORY; + } else if (!strcmp(envStr, "DEFAULT")) { + DP("Target offloading forced to default policy by environment\n"); + } else { + DP("Target offloading with unknown value\n"); + } } DP("Loading RTLs...\n");