diff --git a/openmp/libomptarget/src/interface.cpp b/openmp/libomptarget/src/interface.cpp --- a/openmp/libomptarget/src/interface.cpp +++ b/openmp/libomptarget/src/interface.cpp @@ -21,69 +21,6 @@ #include #include -//////////////////////////////////////////////////////////////////////////////// -/// manage the success or failure of a target construct -static void HandleDefaultTargetOffload() { - PM->TargetOffloadMtx.lock(); - if (PM->TargetOffloadPolicy == tgt_default) { - if (omp_get_num_devices() > 0) { - DP("Default TARGET OFFLOAD policy is now mandatory " - "(devices were found)\n"); - PM->TargetOffloadPolicy = tgt_mandatory; - } else { - DP("Default TARGET OFFLOAD policy is now disabled " - "(no devices were found)\n"); - PM->TargetOffloadPolicy = tgt_disabled; - } - } - PM->TargetOffloadMtx.unlock(); -} - -static int IsOffloadDisabled() { - if (PM->TargetOffloadPolicy == tgt_default) - HandleDefaultTargetOffload(); - return PM->TargetOffloadPolicy == tgt_disabled; -} - -static void HandleTargetOutcome(bool success, ident_t *loc = nullptr) { - switch (PM->TargetOffloadPolicy) { - case tgt_disabled: - if (success) { - FATAL_MESSAGE0(1, "expected no offloading while offloading is disabled"); - } - break; - case tgt_default: - FATAL_MESSAGE0(1, "default offloading policy must be switched to " - "mandatory or disabled"); - break; - case tgt_mandatory: - if (!success) { - if (getInfoLevel() & OMP_INFOTYPE_DUMP_TABLE) - for (auto &Device : PM->Devices) - dumpTargetPointerMappings(loc, Device); - else - FAILURE_MESSAGE("Run with LIBOMPTARGET_DEBUG=%d to dump host-target " - "pointer mappings.\n", - OMP_INFOTYPE_DUMP_TABLE); - - SourceInfo info(loc); - if (info.isAvailible()) - fprintf(stderr, "%s:%d:%d: ", info.getFilename(), info.getLine(), - info.getColumn()); - else - FAILURE_MESSAGE("Source location information not present. Compile with " - "-g or -gline-tables-only.\n"); - FATAL_MESSAGE0( - 1, "failure of target construct while offloading is mandatory"); - } else { - if (getInfoLevel() & OMP_INFOTYPE_DUMP_TABLE) - for (auto &Device : PM->Devices) - dumpTargetPointerMappings(loc, Device); - } - break; - } -} - //////////////////////////////////////////////////////////////////////////////// /// adds requires flags EXTERN void __tgt_register_requires(int64_t flags) { @@ -152,34 +89,10 @@ map_var_info_t *arg_names, void **arg_mappers) { TIMESCOPE_WITH_IDENT(loc); - if (IsOffloadDisabled()) - return; - DP("Entering data begin region for device %" PRId64 " with %d mappings\n", device_id, arg_num); - - // No devices available? - if (device_id == OFFLOAD_DEVICE_DEFAULT) { - device_id = omp_get_default_device(); - DP("Use default device id %" PRId64 "\n", device_id); - } - - // Proposed behavior for OpenMP 5.2 in OpenMP spec github issue 2669. - if (omp_get_num_devices() == 0) { - DP("omp_get_num_devices() == 0 but offload is manadatory\n"); - HandleTargetOutcome(false, loc); - return; - } - - if (device_id == omp_get_initial_device()) { - DP("Device is host (%" PRId64 "), returning as if offload is disabled\n", - device_id); - return; - } - - if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) { - DP("Failed to get device %" PRId64 " ready\n", device_id); - HandleTargetOutcome(false, loc); + if (checkDeviceAndCtors(device_id, loc) != OFFLOAD_SUCCESS) { + DP("Not offloading to device %" PRId64 "\n", device_id); return; } @@ -202,7 +115,7 @@ arg_types, arg_names, arg_mappers, AsyncInfo); if (rc == OFFLOAD_SUCCESS) rc = AsyncInfo.synchronize(); - HandleTargetOutcome(rc == OFFLOAD_SUCCESS, loc); + handleTargetOutcome(rc == OFFLOAD_SUCCESS, loc); } EXTERN void __tgt_target_data_begin_nowait_mapper( @@ -250,31 +163,9 @@ map_var_info_t *arg_names, void **arg_mappers) { TIMESCOPE_WITH_IDENT(loc); - if (IsOffloadDisabled()) - return; DP("Entering data end region with %d mappings\n", arg_num); - - // No devices available? - if (device_id == OFFLOAD_DEVICE_DEFAULT) { - device_id = omp_get_default_device(); - } - - // Proposed behavior for OpenMP 5.2 in OpenMP spec github issue 2669. - if (omp_get_num_devices() == 0) { - DP("omp_get_num_devices() == 0 but offload is manadatory\n"); - HandleTargetOutcome(false, loc); - return; - } - - if (device_id == omp_get_initial_device()) { - DP("Device is host (%" PRId64 "), returning as if offload is disabled\n", - device_id); - return; - } - - if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) { - DP("Failed to get device %" PRId64 " ready\n", device_id); - HandleTargetOutcome(false, loc); + if (checkDeviceAndCtors(device_id, loc) != OFFLOAD_SUCCESS) { + DP("Not offloading to device %" PRId64 "\n", device_id); return; } @@ -297,7 +188,7 @@ arg_types, arg_names, arg_mappers, AsyncInfo); if (rc == OFFLOAD_SUCCESS) rc = AsyncInfo.synchronize(); - HandleTargetOutcome(rc == OFFLOAD_SUCCESS, loc); + handleTargetOutcome(rc == OFFLOAD_SUCCESS, loc); } EXTERN void __tgt_target_data_end_nowait_mapper( @@ -340,31 +231,9 @@ map_var_info_t *arg_names, void **arg_mappers) { TIMESCOPE_WITH_IDENT(loc); - if (IsOffloadDisabled()) - return; DP("Entering data update with %d mappings\n", arg_num); - - // No devices available? - if (device_id == OFFLOAD_DEVICE_DEFAULT) { - device_id = omp_get_default_device(); - } - - // Proposed behavior for OpenMP 5.2 in OpenMP spec github issue 2669. - if (omp_get_num_devices() == 0) { - DP("omp_get_num_devices() == 0 but offload is manadatory\n"); - HandleTargetOutcome(false, loc); - return; - } - - if (device_id == omp_get_initial_device()) { - DP("Device is host (%" PRId64 "), returning as if offload is disabled\n", - device_id); - return; - } - - if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) { - DP("Failed to get device %" PRId64 " ready\n", device_id); - HandleTargetOutcome(false, loc); + if (checkDeviceAndCtors(device_id, loc) != OFFLOAD_SUCCESS) { + DP("Not offloading to device %" PRId64 "\n", device_id); return; } @@ -378,7 +247,7 @@ arg_types, arg_names, arg_mappers, AsyncInfo); if (rc == OFFLOAD_SUCCESS) rc = AsyncInfo.synchronize(); - HandleTargetOutcome(rc == OFFLOAD_SUCCESS, loc); + handleTargetOutcome(rc == OFFLOAD_SUCCESS, loc); } EXTERN void __tgt_target_data_update_nowait_mapper( @@ -420,33 +289,11 @@ int64_t *arg_sizes, int64_t *arg_types, map_var_info_t *arg_names, void **arg_mappers) { TIMESCOPE_WITH_IDENT(loc); - if (IsOffloadDisabled()) - return OFFLOAD_FAIL; DP("Entering target region with entry point " DPxMOD " and device Id %" PRId64 "\n", DPxPTR(host_ptr), device_id); - - if (device_id == OFFLOAD_DEVICE_DEFAULT) { - device_id = omp_get_default_device(); - } - - // Proposed behavior for OpenMP 5.2 in OpenMP spec github issue 2669. - if (omp_get_num_devices() == 0) { - DP("omp_get_num_devices() == 0 but offload is manadatory\n"); - HandleTargetOutcome(false, loc); - return OFFLOAD_FAIL; - } - - if (device_id == omp_get_initial_device()) { - DP("Device is host (%" PRId64 "), returning OFFLOAD_FAIL as if offload is " - "disabled\n", - device_id); - return OFFLOAD_FAIL; - } - - if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) { - REPORT("Failed to get device %" PRId64 " ready\n", device_id); - HandleTargetOutcome(false, loc); + if (checkDeviceAndCtors(device_id, loc) != OFFLOAD_SUCCESS) { + DP("Not offloading to device %" PRId64 "\n", device_id); return OFFLOAD_FAIL; } @@ -469,7 +316,7 @@ AsyncInfo); if (rc == OFFLOAD_SUCCESS) rc = AsyncInfo.synchronize(); - HandleTargetOutcome(rc == OFFLOAD_SUCCESS, loc); + handleTargetOutcome(rc == OFFLOAD_SUCCESS, loc); return rc; } @@ -519,33 +366,11 @@ map_var_info_t *arg_names, void **arg_mappers, int32_t team_num, int32_t thread_limit) { - if (IsOffloadDisabled()) - return OFFLOAD_FAIL; DP("Entering target region with entry point " DPxMOD " and device Id %" PRId64 "\n", DPxPTR(host_ptr), device_id); - - if (device_id == OFFLOAD_DEVICE_DEFAULT) { - device_id = omp_get_default_device(); - } - - // Proposed behavior for OpenMP 5.2 in OpenMP spec github issue 2669. - if (omp_get_num_devices() == 0) { - DP("omp_get_num_devices() == 0 but offload is manadatory\n"); - HandleTargetOutcome(false, loc); - return OFFLOAD_FAIL; - } - - if (device_id == omp_get_initial_device()) { - DP("Device is host (%" PRId64 "), returning OFFLOAD_FAIL as if offload is " - "disabled\n", - device_id); - return OFFLOAD_FAIL; - } - - if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) { - REPORT("Failed to get device %" PRId64 " ready\n", device_id); - HandleTargetOutcome(false, loc); + if (checkDeviceAndCtors(device_id, loc) != OFFLOAD_SUCCESS) { + DP("Not offloading to device %" PRId64 "\n", device_id); return OFFLOAD_FAIL; } @@ -568,7 +393,7 @@ true /*team*/, AsyncInfo); if (rc == OFFLOAD_SUCCESS) rc = AsyncInfo.synchronize(); - HandleTargetOutcome(rc == OFFLOAD_SUCCESS, loc); + handleTargetOutcome(rc == OFFLOAD_SUCCESS, loc); return rc; } @@ -615,29 +440,8 @@ EXTERN void __kmpc_push_target_tripcount(ident_t *loc, int64_t device_id, uint64_t loop_tripcount) { TIMESCOPE_WITH_IDENT(loc); - if (IsOffloadDisabled()) - return; - - if (device_id == OFFLOAD_DEVICE_DEFAULT) { - device_id = omp_get_default_device(); - } - - // Proposed behavior for OpenMP 5.2 in OpenMP spec github issue 2669. - if (omp_get_num_devices() == 0) { - DP("omp_get_num_devices() == 0 but offload is manadatory\n"); - HandleTargetOutcome(false, loc); - return; - } - - if (device_id == omp_get_initial_device()) { - DP("Device is host (%" PRId64 "), returning as if offload is disabled\n", - device_id); - return; - } - - if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) { - DP("Failed to get device %" PRId64 " ready\n", device_id); - HandleTargetOutcome(false, loc); + if (checkDeviceAndCtors(device_id, loc) != OFFLOAD_SUCCESS) { + DP("Not offloading to device %" PRId64 "\n", device_id); return; } diff --git a/openmp/libomptarget/src/omptarget.cpp b/openmp/libomptarget/src/omptarget.cpp --- a/openmp/libomptarget/src/omptarget.cpp +++ b/openmp/libomptarget/src/omptarget.cpp @@ -205,24 +205,119 @@ return OFFLOAD_SUCCESS; } -// Check whether a device has been initialized, global ctors have been -// executed and global data has been mapped; do so if not already done. -int CheckDeviceAndCtors(int64_t device_id) { +void handleTargetOutcome(bool Success, ident_t *Loc) { + switch (PM->TargetOffloadPolicy) { + case tgt_disabled: + if (Success) { + FATAL_MESSAGE0(1, "expected no offloading while offloading is disabled"); + } + break; + case tgt_default: + FATAL_MESSAGE0(1, "default offloading policy must be switched to " + "mandatory or disabled"); + break; + case tgt_mandatory: + if (!Success) { + if (getInfoLevel() & OMP_INFOTYPE_DUMP_TABLE) + for (auto &Device : PM->Devices) + dumpTargetPointerMappings(Loc, Device); + else + FAILURE_MESSAGE("Run with LIBOMPTARGET_DEBUG=%d to dump host-target " + "pointer mappings.\n", + OMP_INFOTYPE_DUMP_TABLE); + + SourceInfo info(Loc); + if (info.isAvailible()) + fprintf(stderr, "%s:%d:%d: ", info.getFilename(), info.getLine(), + info.getColumn()); + else + FAILURE_MESSAGE("Source location information not present. Compile with " + "-g or -gline-tables-only.\n"); + FATAL_MESSAGE0( + 1, "failure of target construct while offloading is mandatory"); + } else { + if (getInfoLevel() & OMP_INFOTYPE_DUMP_TABLE) + for (auto &Device : PM->Devices) + dumpTargetPointerMappings(Loc, Device); + } + break; + } +} + +static void handleDefaultTargetOffload() { + PM->TargetOffloadMtx.lock(); + if (PM->TargetOffloadPolicy == tgt_default) { + if (omp_get_num_devices() > 0) { + DP("Default TARGET OFFLOAD policy is now mandatory " + "(devices were found)\n"); + PM->TargetOffloadPolicy = tgt_mandatory; + } else { + DP("Default TARGET OFFLOAD policy is now disabled " + "(no devices were found)\n"); + PM->TargetOffloadPolicy = tgt_disabled; + } + } + PM->TargetOffloadMtx.unlock(); +} + +static bool isOffloadDisabled() { + if (PM->TargetOffloadPolicy == tgt_default) + handleDefaultTargetOffload(); + return PM->TargetOffloadPolicy == tgt_disabled; +} + +// If offload is enabled, ensure that device DeviceID has been initialized, +// global ctors have been executed, and global data has been mapped. +// +// There are three possible results: +// - Return OFFLOAD_SUCCESS if the device is ready for offload. +// - Return OFFLOAD_FAIL without reporting a runtime error if offload is +// disabled, perhaps because the initial device was specified. +// - Report a runtime error and return OFFLOAD_FAIL. +// +// If DeviceID == OFFLOAD_DEVICE_DEFAULT, set DeviceID to the default device. +// This step might be skipped if offload is disabled. +int checkDeviceAndCtors(int64_t &DeviceID, ident_t *Loc) { + if (isOffloadDisabled()) { + DP("Offload is disabled\n"); + return OFFLOAD_FAIL; + } + + if (DeviceID == OFFLOAD_DEVICE_DEFAULT) { + DeviceID = omp_get_default_device(); + DP("Use default device id %" PRId64 "\n", DeviceID); + } + + // Proposed behavior for OpenMP 5.2 in OpenMP spec github issue 2669. + if (omp_get_num_devices() == 0) { + DP("omp_get_num_devices() == 0 but offload is manadatory\n"); + handleTargetOutcome(false, Loc); + return OFFLOAD_FAIL; + } + + if (DeviceID == omp_get_initial_device()) { + DP("Device is host (%" PRId64 "), returning as if offload is disabled\n", + DeviceID); + return OFFLOAD_FAIL; + } + // Is device ready? - if (!device_is_ready(device_id)) { - REPORT("Device %" PRId64 " is not ready.\n", device_id); + if (!device_is_ready(DeviceID)) { + REPORT("Device %" PRId64 " is not ready.\n", DeviceID); + handleTargetOutcome(false, Loc); return OFFLOAD_FAIL; } // Get device info. - DeviceTy &Device = PM->Devices[device_id]; + DeviceTy &Device = PM->Devices[DeviceID]; // Check whether global data has been mapped for this device Device.PendingGlobalsMtx.lock(); bool hasPendingGlobals = Device.HasPendingGlobals; Device.PendingGlobalsMtx.unlock(); if (hasPendingGlobals && InitLibrary(Device) != OFFLOAD_SUCCESS) { - REPORT("Failed to init globals on device %" PRId64 "\n", device_id); + REPORT("Failed to init globals on device %" PRId64 "\n", DeviceID); + handleTargetOutcome(false, Loc); return OFFLOAD_FAIL; } diff --git a/openmp/libomptarget/src/private.h b/openmp/libomptarget/src/private.h --- a/openmp/libomptarget/src/private.h +++ b/openmp/libomptarget/src/private.h @@ -44,7 +44,8 @@ void **ArgMappers, int32_t TeamNum, int32_t ThreadLimit, int IsTeamConstruct, AsyncInfoTy &AsyncInfo); -extern int CheckDeviceAndCtors(int64_t device_id); +extern void handleTargetOutcome(bool Success, ident_t *Loc); +extern int checkDeviceAndCtors(int64_t &DeviceID, ident_t *Loc); // This structure stores information of a mapped memory region. struct MapComponentInfoTy {