mirror of
https://github.com/intel/compute-runtime.git
synced 2026-01-05 09:09:04 +08:00
refactor: Move Sysman APIs to level_zero/sysman/source/api
Signed-off-by: Jitendra Sharma <jitendra.sharma@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
55585b1fd8
commit
541e4e57f6
17
level_zero/sysman/source/api/events/CMakeLists.txt
Normal file
17
level_zero/sysman/source/api/events/CMakeLists.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
#
|
||||
# Copyright (C) 2023 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
target_sources(${L0_STATIC_LIB_NAME}
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sysman_events.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sysman_events_imp.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sysman_events_imp.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sysman_os_events.h
|
||||
)
|
||||
|
||||
add_subdirectories()
|
||||
|
||||
14
level_zero/sysman/source/api/events/linux/CMakeLists.txt
Normal file
14
level_zero/sysman/source/api/events/linux/CMakeLists.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# Copyright (C) 2023 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
if(UNIX)
|
||||
target_sources(${L0_STATIC_LIB_NAME}
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sysman_os_events_imp.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sysman_os_events_imp.h
|
||||
)
|
||||
endif()
|
||||
@@ -0,0 +1,438 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "level_zero/sysman/source/api/events/linux/sysman_os_events_imp.h"
|
||||
|
||||
#include "shared/source/debug_settings/debug_settings_manager.h"
|
||||
#include "shared/source/utilities/directory.h"
|
||||
|
||||
#include "level_zero/sysman/source/api/events/sysman_events_imp.h"
|
||||
#include "level_zero/sysman/source/api/memory/linux/sysman_os_memory_imp_prelim.h"
|
||||
#include "level_zero/sysman/source/linux/zes_os_sysman_driver_imp.h"
|
||||
#include "level_zero/sysman/source/linux/zes_os_sysman_imp.h"
|
||||
#include "level_zero/sysman/source/sysman_driver_handle_imp.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace L0 {
|
||||
namespace Sysman {
|
||||
|
||||
const std::string LinuxEventsUtil::add("add");
|
||||
const std::string LinuxEventsUtil::remove("remove");
|
||||
const std::string LinuxEventsUtil::change("change");
|
||||
const std::string LinuxEventsUtil::unbind("unbind");
|
||||
const std::string LinuxEventsUtil::bind("bind");
|
||||
|
||||
bool LinuxEventsImp::eventListen(zes_event_type_flags_t &pEvent, uint64_t timeout) {
|
||||
// This is dummy implementation, Actual implementation is handled at driver level
|
||||
// for all devices.
|
||||
return false;
|
||||
}
|
||||
|
||||
ze_result_t LinuxEventsImp::eventRegister(zes_event_type_flags_t events) {
|
||||
if (0x7fff < events) {
|
||||
return ZE_RESULT_ERROR_INVALID_ENUMERATION;
|
||||
}
|
||||
|
||||
auto pLinuxSysmanDriverImp = static_cast<LinuxSysmanDriverImp *>(GlobalSysmanDriver->pOsSysmanDriver);
|
||||
if (pLinuxSysmanDriverImp == nullptr) {
|
||||
NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr,
|
||||
"%s", "Os Sysman driver not initialized\n");
|
||||
return ZE_RESULT_ERROR_UNINITIALIZED;
|
||||
}
|
||||
pLinuxSysmanDriverImp->eventRegister(events, pLinuxSysmanImp->getSysmanDeviceImp());
|
||||
return ZE_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
LinuxEventsImp::LinuxEventsImp(OsSysman *pOsSysman) {
|
||||
pLinuxSysmanImp = static_cast<LinuxSysmanImp *>(pOsSysman);
|
||||
}
|
||||
|
||||
OsEvents *OsEvents::create(OsSysman *pOsSysman) {
|
||||
LinuxEventsImp *pLinuxEventsImp = new LinuxEventsImp(pOsSysman);
|
||||
return static_cast<OsEvents *>(pLinuxEventsImp);
|
||||
}
|
||||
|
||||
LinuxEventsUtil::LinuxEventsUtil(LinuxSysmanDriverImp *pOsSysmanDriverImp) : pLinuxSysmanDriverImp(pOsSysmanDriverImp) {
|
||||
}
|
||||
|
||||
bool LinuxEventsUtil::checkRasEvent(zes_event_type_flags_t &pEvent, SysmanDeviceImp *pSysmanDeviceImp, zes_event_type_flags_t registeredEvents) {
|
||||
for (auto rasHandle : pSysmanDeviceImp->pRasHandleContext->handleList) {
|
||||
zes_ras_properties_t properties = {};
|
||||
rasHandle->rasGetProperties(&properties);
|
||||
if ((registeredEvents & ZES_EVENT_TYPE_FLAG_RAS_CORRECTABLE_ERRORS) && (properties.type == ZES_RAS_ERROR_TYPE_CORRECTABLE)) {
|
||||
if (LinuxEventsUtil::checkRasEventOccured(rasHandle) == true) {
|
||||
pEvent |= ZES_EVENT_TYPE_FLAG_RAS_CORRECTABLE_ERRORS;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ((registeredEvents & ZES_EVENT_TYPE_FLAG_RAS_UNCORRECTABLE_ERRORS) && (properties.type == ZES_RAS_ERROR_TYPE_UNCORRECTABLE)) {
|
||||
if (LinuxEventsUtil::checkRasEventOccured(rasHandle) == true) {
|
||||
pEvent |= ZES_EVENT_TYPE_FLAG_RAS_UNCORRECTABLE_ERRORS;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LinuxEventsUtil::checkRasEventOccured(Ras *rasHandle) {
|
||||
zes_ras_config_t config = {};
|
||||
zes_ras_state_t state = {};
|
||||
rasHandle->rasGetConfig(&config);
|
||||
if (ZE_RESULT_SUCCESS == rasHandle->rasGetState(&state, 0)) {
|
||||
uint64_t totalCategoryThreshold = 0;
|
||||
for (int i = 0; i < ZES_MAX_RAS_ERROR_CATEGORY_COUNT; i++) {
|
||||
totalCategoryThreshold += state.category[i];
|
||||
if ((config.detailedThresholds.category[i] > 0) && (state.category[i] > config.detailedThresholds.category[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ((config.totalThreshold > 0) && (totalCategoryThreshold > config.totalThreshold)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LinuxEventsUtil::eventRegister(zes_event_type_flags_t events, SysmanDeviceImp *pSysmanDevice) {
|
||||
std::call_once(initEventsOnce, [this]() {
|
||||
this->init();
|
||||
});
|
||||
|
||||
zes_event_type_flags_t prevRegisteredEvents = 0;
|
||||
if (deviceEventsMap.find(pSysmanDevice) != deviceEventsMap.end()) {
|
||||
prevRegisteredEvents = deviceEventsMap[pSysmanDevice];
|
||||
}
|
||||
|
||||
eventsMutex.lock();
|
||||
if (!events) {
|
||||
// If user is trying to register events with empty events argument, then clear all the registered events
|
||||
if (deviceEventsMap.find(pSysmanDevice) != deviceEventsMap.end()) {
|
||||
deviceEventsMap[pSysmanDevice] = events;
|
||||
} else {
|
||||
deviceEventsMap.emplace(pSysmanDevice, events);
|
||||
}
|
||||
} else {
|
||||
zes_event_type_flags_t registeredEvents = 0;
|
||||
// supportedEventMask --> this mask checks for events that supported currently
|
||||
zes_event_type_flags_t supportedEventMask = ZES_EVENT_TYPE_FLAG_FABRIC_PORT_HEALTH | ZES_EVENT_TYPE_FLAG_DEVICE_DETACH |
|
||||
ZES_EVENT_TYPE_FLAG_DEVICE_ATTACH | ZES_EVENT_TYPE_FLAG_DEVICE_RESET_REQUIRED |
|
||||
ZES_EVENT_TYPE_FLAG_MEM_HEALTH | ZES_EVENT_TYPE_FLAG_RAS_CORRECTABLE_ERRORS |
|
||||
ZES_EVENT_TYPE_FLAG_RAS_UNCORRECTABLE_ERRORS;
|
||||
if (deviceEventsMap.find(pSysmanDevice) != deviceEventsMap.end()) {
|
||||
registeredEvents = deviceEventsMap[pSysmanDevice];
|
||||
}
|
||||
registeredEvents |= (events & supportedEventMask);
|
||||
deviceEventsMap[pSysmanDevice] = registeredEvents;
|
||||
}
|
||||
|
||||
// Write to Pipe only if eventregister() is called during listen and previously registered events are modified.
|
||||
if ((pipeFd[1] != -1) && (prevRegisteredEvents != deviceEventsMap[pSysmanDevice])) {
|
||||
uint8_t value = 0x00;
|
||||
if (NEO::SysCalls::write(pipeFd[1], &value, 1) < 0) {
|
||||
NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr,
|
||||
"%s", "Write to Pipe failed\n");
|
||||
}
|
||||
}
|
||||
eventsMutex.unlock();
|
||||
}
|
||||
|
||||
void LinuxEventsUtil::init() {
|
||||
pUdevLib = pLinuxSysmanDriverImp->getUdevLibHandle();
|
||||
}
|
||||
|
||||
ze_result_t LinuxEventsUtil::eventsListen(uint64_t timeout, uint32_t count, zes_device_handle_t *phDevices, uint32_t *pNumDeviceEvents, zes_event_type_flags_t *pEvents) {
|
||||
memset(pEvents, 0, count * sizeof(zes_event_type_flags_t));
|
||||
*pNumDeviceEvents = 0;
|
||||
std::vector<zes_event_type_flags_t> registeredEvents(count);
|
||||
for (uint32_t devIndex = 0; devIndex < count; devIndex++) {
|
||||
auto device = static_cast<SysmanDeviceImp *>(L0::Sysman::SysmanDevice::fromHandle(phDevices[devIndex]));
|
||||
eventsMutex.lock();
|
||||
if (deviceEventsMap.find(device) != deviceEventsMap.end()) {
|
||||
registeredEvents[devIndex] = deviceEventsMap[device];
|
||||
}
|
||||
eventsMutex.unlock();
|
||||
if (registeredEvents[devIndex]) {
|
||||
if ((registeredEvents[devIndex] & ZES_EVENT_TYPE_FLAG_RAS_CORRECTABLE_ERRORS) || (registeredEvents[devIndex] & ZES_EVENT_TYPE_FLAG_RAS_UNCORRECTABLE_ERRORS)) {
|
||||
if (checkRasEvent(pEvents[devIndex], device, registeredEvents[devIndex])) {
|
||||
*pNumDeviceEvents = 1;
|
||||
return ZE_RESULT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (registeredEvents[devIndex] & ZES_EVENT_TYPE_FLAG_DEVICE_RESET_REQUIRED) {
|
||||
zes_device_state_t deviceState = {};
|
||||
device->pGlobalOperations->deviceGetState(&deviceState);
|
||||
if (deviceState.reset & ZES_RESET_REASON_FLAG_REPAIR) {
|
||||
pEvents[devIndex] |= ZES_EVENT_TYPE_FLAG_DEVICE_RESET_REQUIRED;
|
||||
*pNumDeviceEvents = 1;
|
||||
return ZE_RESULT_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (listenSystemEvents(pEvents, count, registeredEvents, phDevices, timeout)) {
|
||||
*pNumDeviceEvents = 1;
|
||||
}
|
||||
|
||||
return ZE_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
bool LinuxEventsUtil::isResetRequired(void *dev, zes_event_type_flags_t &pEvent) {
|
||||
if (action.compare(change) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> properties{"RESET_FAILED", "RESET_REQUIRED"};
|
||||
for (auto &property : properties) {
|
||||
const char *propVal = nullptr;
|
||||
propVal = pUdevLib->getEventPropertyValue(dev, property.c_str());
|
||||
if (propVal && atoi(propVal) == 1) {
|
||||
pEvent |= ZES_EVENT_TYPE_FLAG_DEVICE_RESET_REQUIRED;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LinuxEventsUtil::checkDeviceDetachEvent(zes_event_type_flags_t &pEvent) {
|
||||
if (action.compare(remove) == 0) {
|
||||
pEvent |= ZES_EVENT_TYPE_FLAG_DEVICE_DETACH;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LinuxEventsUtil::checkDeviceAttachEvent(zes_event_type_flags_t &pEvent) {
|
||||
if (action.compare(add) == 0) {
|
||||
pEvent |= ZES_EVENT_TYPE_FLAG_DEVICE_ATTACH;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LinuxEventsUtil::checkIfMemHealthChanged(void *dev, zes_event_type_flags_t &pEvent) {
|
||||
if (action.compare(change) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> properties{"MEM_HEALTH_ALARM", "RESET_REQUIRED", "EC_PENDING", "DEGRADED", "EC_FAILED", "SPARING_STATUS_UNKNOWN"};
|
||||
for (auto &property : properties) {
|
||||
const char *propVal = nullptr;
|
||||
propVal = pUdevLib->getEventPropertyValue(dev, property.c_str());
|
||||
if (propVal && atoi(propVal) == 1) {
|
||||
pEvent |= ZES_EVENT_TYPE_FLAG_MEM_HEALTH;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LinuxEventsUtil::checkIfFabricPortStatusChanged(void *dev, zes_event_type_flags_t &pEvent) {
|
||||
if (action.compare(change) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *str = pUdevLib->getEventPropertyValue(dev, "TYPE");
|
||||
if (str == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string expectedStr = "PORT_CHANGE";
|
||||
if (expectedStr == str) {
|
||||
pEvent |= ZES_EVENT_TYPE_FLAG_FABRIC_PORT_HEALTH;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LinuxEventsUtil::getDevIndexToDevPathMap(std::vector<zes_event_type_flags_t> ®isteredEvents, uint32_t count, zes_device_handle_t *phDevices, std::map<uint32_t, std::string> &mapOfDevIndexToDevPath) {
|
||||
for (uint32_t devIndex = 0; devIndex < count; devIndex++) {
|
||||
auto device = static_cast<SysmanDeviceImp *>(L0::Sysman::SysmanDevice::fromHandle(phDevices[devIndex]));
|
||||
registeredEvents[devIndex] = deviceEventsMap[device];
|
||||
if (!registeredEvents[devIndex]) {
|
||||
continue;
|
||||
} else {
|
||||
std::string bdf;
|
||||
auto pSysfsAccess = &static_cast<L0::Sysman::LinuxSysmanImp *>(device->deviceGetOsInterface())->getSysfsAccess();
|
||||
if (pSysfsAccess->getRealPath("device", bdf) == ZE_RESULT_SUCCESS) {
|
||||
// /sys needs to be removed from real path inorder to equate with
|
||||
// DEVPATH property of uevent.
|
||||
// Example of real path: /sys/devices/pci0000:97/0000:97:02.0/0000:98:00.0/0000:99:01.0/0000:9a:00.0
|
||||
// Example of DEVPATH: /devices/pci0000:97/0000:97:02.0/0000:98:00.0/0000:99:01.0/0000:9a:00.0/i915.iaf.0
|
||||
const auto loc = bdf.find("/devices");
|
||||
if (loc == std::string::npos) {
|
||||
NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr,
|
||||
"%s", "Invalid device path\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
bdf = bdf.substr(loc);
|
||||
mapOfDevIndexToDevPath.insert({devIndex, bdf});
|
||||
} else {
|
||||
NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr,
|
||||
"%s", "Failed to get real path of device\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LinuxEventsUtil::checkDeviceEvents(std::vector<zes_event_type_flags_t> ®isteredEvents, std::map<uint32_t, std::string> mapOfDevIndexToDevPath, zes_event_type_flags_t *pEvents, void *dev) {
|
||||
const char *devicePath = pUdevLib->getEventPropertyValue(dev, "DEVPATH");
|
||||
bool retVal = false;
|
||||
if (devicePath != nullptr) {
|
||||
std::string devPath(devicePath);
|
||||
for (auto it = mapOfDevIndexToDevPath.begin(); it != mapOfDevIndexToDevPath.end(); it++) {
|
||||
if (devPath.find(it->second.c_str()) != std::string::npos) {
|
||||
if (registeredEvents[it->first] & ZES_EVENT_TYPE_FLAG_DEVICE_DETACH) {
|
||||
if (checkDeviceDetachEvent(pEvents[it->first])) {
|
||||
retVal = true;
|
||||
}
|
||||
}
|
||||
if (registeredEvents[it->first] & ZES_EVENT_TYPE_FLAG_DEVICE_ATTACH) {
|
||||
if (checkDeviceAttachEvent(pEvents[it->first])) {
|
||||
retVal = true;
|
||||
}
|
||||
}
|
||||
if (registeredEvents[it->first] & ZES_EVENT_TYPE_FLAG_DEVICE_RESET_REQUIRED) {
|
||||
if (isResetRequired(dev, pEvents[it->first])) {
|
||||
retVal = true;
|
||||
}
|
||||
}
|
||||
if (registeredEvents[it->first] & ZES_EVENT_TYPE_FLAG_MEM_HEALTH) {
|
||||
if (checkIfMemHealthChanged(dev, pEvents[it->first])) {
|
||||
retVal = true;
|
||||
}
|
||||
}
|
||||
if (registeredEvents[it->first] & ZES_EVENT_TYPE_FLAG_FABRIC_PORT_HEALTH) {
|
||||
if (checkIfFabricPortStatusChanged(dev, pEvents[it->first])) {
|
||||
retVal = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool LinuxEventsUtil::listenSystemEvents(zes_event_type_flags_t *pEvents, uint32_t count, std::vector<zes_event_type_flags_t> ®isteredEvents, zes_device_handle_t *phDevices, uint64_t timeout) {
|
||||
std::call_once(initEventsOnce, [this]() {
|
||||
this->init();
|
||||
});
|
||||
|
||||
bool retval = false;
|
||||
struct pollfd pfd[2];
|
||||
std::vector<std::string> subsystemList;
|
||||
std::map<uint32_t, std::string> mapOfDevIndexToDevPath = {};
|
||||
|
||||
if (pUdevLib == nullptr) {
|
||||
NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr,
|
||||
"%s", "libudev library instantiation failed\n");
|
||||
return retval;
|
||||
}
|
||||
|
||||
subsystemList.push_back("drm");
|
||||
subsystemList.push_back("auxiliary");
|
||||
pfd[0].fd = pUdevLib->registerEventsFromSubsystemAndGetFd(subsystemList);
|
||||
pfd[0].events = POLLIN;
|
||||
pfd[0].revents = 0;
|
||||
|
||||
eventsMutex.lock();
|
||||
if (NEO::SysCalls::pipe(pipeFd) < 0) {
|
||||
NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr,
|
||||
"%s", "Creation of pipe failed\n");
|
||||
}
|
||||
|
||||
pfd[1].fd = pipeFd[0];
|
||||
pfd[1].events = POLLIN;
|
||||
pfd[1].revents = 0;
|
||||
|
||||
auto start = L0::Sysman::SteadyClock::now();
|
||||
std::chrono::duration<double, std::milli> timeElapsed;
|
||||
getDevIndexToDevPathMap(registeredEvents, count, phDevices, mapOfDevIndexToDevPath);
|
||||
eventsMutex.unlock();
|
||||
while (NEO::SysCalls::poll(pfd, 2, static_cast<int>(timeout)) > 0) {
|
||||
bool eventReceived = false;
|
||||
for (auto i = 0; i < 2; i++) {
|
||||
if (pfd[i].revents != 0) {
|
||||
if (pfd[i].fd == pipeFd[0]) {
|
||||
eventsMutex.lock();
|
||||
uint8_t dummy;
|
||||
NEO::SysCalls::read(pipeFd[0], &dummy, 1);
|
||||
mapOfDevIndexToDevPath.clear();
|
||||
getDevIndexToDevPathMap(registeredEvents, count, phDevices, mapOfDevIndexToDevPath);
|
||||
eventsMutex.unlock();
|
||||
} else {
|
||||
eventReceived = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mapOfDevIndexToDevPath.empty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!eventReceived) {
|
||||
timeElapsed = L0::Sysman::SteadyClock::now() - start;
|
||||
if (timeout > timeElapsed.count()) {
|
||||
timeout = timeout - timeElapsed.count();
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void *dev = nullptr;
|
||||
dev = pUdevLib->allocateDeviceToReceiveData();
|
||||
if (dev == nullptr) {
|
||||
timeElapsed = L0::Sysman::SteadyClock::now() - start;
|
||||
if (timeout > timeElapsed.count()) {
|
||||
timeout = timeout - timeElapsed.count();
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto eventTypePtr = pUdevLib->getEventType(dev);
|
||||
if (eventTypePtr != nullptr) {
|
||||
action = std::string(eventTypePtr);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
retval = checkDeviceEvents(registeredEvents, mapOfDevIndexToDevPath, pEvents, dev);
|
||||
pUdevLib->dropDeviceReference(dev);
|
||||
if (retval) {
|
||||
break;
|
||||
}
|
||||
timeElapsed = L0::Sysman::SteadyClock::now() - start;
|
||||
if (timeout > timeElapsed.count()) {
|
||||
timeout = timeout - timeElapsed.count();
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
eventsMutex.lock();
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
if (pipeFd[i] != -1) {
|
||||
NEO::SysCalls::close(pipeFd[i]);
|
||||
pipeFd[i] = -1;
|
||||
}
|
||||
}
|
||||
eventsMutex.unlock();
|
||||
return retval;
|
||||
}
|
||||
|
||||
} // namespace Sysman
|
||||
} // namespace L0
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "level_zero/sysman/source/api/events/sysman_os_events.h"
|
||||
#include "level_zero/sysman/source/linux/udev/udev_lib.h"
|
||||
#include "level_zero/sysman/source/linux/zes_os_sysman_imp.h"
|
||||
|
||||
namespace L0 {
|
||||
namespace Sysman {
|
||||
|
||||
class LinuxSysmanDriverImp;
|
||||
|
||||
class LinuxEventsImp : public OsEvents, NEO::NonCopyableOrMovableClass {
|
||||
public:
|
||||
bool eventListen(zes_event_type_flags_t &pEvent, uint64_t timeout) override;
|
||||
ze_result_t eventRegister(zes_event_type_flags_t events) override;
|
||||
LinuxEventsImp() = delete;
|
||||
LinuxEventsImp(OsSysman *pOsSysman);
|
||||
~LinuxEventsImp() override = default;
|
||||
|
||||
protected:
|
||||
LinuxSysmanImp *pLinuxSysmanImp = nullptr;
|
||||
};
|
||||
|
||||
class LinuxEventsUtil {
|
||||
|
||||
public:
|
||||
LinuxEventsUtil() = delete;
|
||||
LinuxEventsUtil(LinuxSysmanDriverImp *pOsSysmanDriverImp);
|
||||
~LinuxEventsUtil() = default;
|
||||
|
||||
ze_result_t eventsListen(uint64_t timeout, uint32_t count, zes_device_handle_t *phDevices, uint32_t *pNumDeviceEvents, zes_event_type_flags_t *pEvents);
|
||||
void eventRegister(zes_event_type_flags_t events, SysmanDeviceImp *pSysmanDevice);
|
||||
|
||||
protected:
|
||||
UdevLib *pUdevLib = nullptr;
|
||||
LinuxSysmanDriverImp *pLinuxSysmanDriverImp = nullptr;
|
||||
int pipeFd[2] = {-1, -1};
|
||||
std::map<SysmanDeviceImp *, zes_event_type_flags_t> deviceEventsMap;
|
||||
bool checkRasEvent(zes_event_type_flags_t &pEvent, SysmanDeviceImp *pSysmanDeviceImp, zes_event_type_flags_t registeredEvents);
|
||||
bool isResetRequired(void *dev, zes_event_type_flags_t &pEvent);
|
||||
bool checkDeviceDetachEvent(zes_event_type_flags_t &pEvent);
|
||||
bool checkDeviceAttachEvent(zes_event_type_flags_t &pEvent);
|
||||
bool checkIfMemHealthChanged(void *dev, zes_event_type_flags_t &pEvent);
|
||||
bool checkIfFabricPortStatusChanged(void *dev, zes_event_type_flags_t &pEvent);
|
||||
bool listenSystemEvents(zes_event_type_flags_t *pEvents, uint32_t count, std::vector<zes_event_type_flags_t> ®isteredEvents, zes_device_handle_t *phDevices, uint64_t timeout);
|
||||
|
||||
private:
|
||||
std::string action;
|
||||
static const std::string add;
|
||||
static const std::string remove;
|
||||
static const std::string change;
|
||||
static const std::string unbind;
|
||||
static const std::string bind;
|
||||
static bool checkRasEventOccured(Ras *rasHandle);
|
||||
void getDevIndexToDevPathMap(std::vector<zes_event_type_flags_t> ®isteredEvents, uint32_t count, zes_device_handle_t *phDevices, std::map<uint32_t, std::string> &mapOfDevIndexToDevPath);
|
||||
bool checkDeviceEvents(std::vector<zes_event_type_flags_t> ®isteredEvents, std::map<uint32_t, std::string> mapOfDevIndexToDevPath, zes_event_type_flags_t *pEvents, void *dev);
|
||||
std::once_flag initEventsOnce;
|
||||
std::mutex eventsMutex;
|
||||
void init();
|
||||
};
|
||||
|
||||
} // namespace Sysman
|
||||
} // namespace L0
|
||||
22
level_zero/sysman/source/api/events/sysman_events.h
Normal file
22
level_zero/sysman/source/api/events/sysman_events.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <level_zero/zes_api.h>
|
||||
namespace L0 {
|
||||
namespace Sysman {
|
||||
|
||||
class Events {
|
||||
public:
|
||||
virtual ~Events(){};
|
||||
virtual ze_result_t eventRegister(zes_event_type_flags_t events) = 0;
|
||||
virtual bool eventListen(zes_event_type_flags_t &pEvent, uint64_t timeout) = 0;
|
||||
virtual void init() = 0;
|
||||
};
|
||||
|
||||
} // namespace Sysman
|
||||
} // namespace L0
|
||||
43
level_zero/sysman/source/api/events/sysman_events_imp.cpp
Normal file
43
level_zero/sysman/source/api/events/sysman_events_imp.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "level_zero/sysman/source/api/events/sysman_events_imp.h"
|
||||
|
||||
#include "shared/source/helpers/debug_helpers.h"
|
||||
|
||||
namespace L0 {
|
||||
namespace Sysman {
|
||||
|
||||
ze_result_t EventsImp::eventRegister(zes_event_type_flags_t events) {
|
||||
initEvents();
|
||||
return pOsEvents->eventRegister(events);
|
||||
}
|
||||
|
||||
bool EventsImp::eventListen(zes_event_type_flags_t &pEvent, uint64_t timeout) {
|
||||
initEvents();
|
||||
return pOsEvents->eventListen(pEvent, timeout);
|
||||
}
|
||||
void EventsImp::initEvents() {
|
||||
std::call_once(initEventsOnce, [this]() {
|
||||
this->init();
|
||||
});
|
||||
}
|
||||
void EventsImp::init() {
|
||||
if (pOsEvents == nullptr) {
|
||||
pOsEvents = OsEvents::create(pOsSysman);
|
||||
}
|
||||
UNRECOVERABLE_IF(nullptr == pOsEvents);
|
||||
}
|
||||
|
||||
EventsImp::~EventsImp() {
|
||||
if (nullptr != pOsEvents) {
|
||||
delete pOsEvents;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Sysman
|
||||
} // namespace L0
|
||||
37
level_zero/sysman/source/api/events/sysman_events_imp.h
Normal file
37
level_zero/sysman/source/api/events/sysman_events_imp.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "shared/source/helpers/non_copyable_or_moveable.h"
|
||||
|
||||
#include "level_zero/sysman/source/api/events/sysman_events.h"
|
||||
#include "level_zero/sysman/source/api/events/sysman_os_events.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace L0 {
|
||||
namespace Sysman {
|
||||
|
||||
class EventsImp : public Events, NEO::NonCopyableOrMovableClass {
|
||||
public:
|
||||
void init() override;
|
||||
ze_result_t eventRegister(zes_event_type_flags_t events) override;
|
||||
bool eventListen(zes_event_type_flags_t &pEvent, uint64_t timeout) override;
|
||||
OsEvents *pOsEvents = nullptr;
|
||||
|
||||
EventsImp() = default;
|
||||
EventsImp(OsSysman *pOsSysman) : pOsSysman(pOsSysman){};
|
||||
~EventsImp() override;
|
||||
|
||||
private:
|
||||
OsSysman *pOsSysman = nullptr;
|
||||
std::once_flag initEventsOnce;
|
||||
void initEvents();
|
||||
};
|
||||
|
||||
} // namespace Sysman
|
||||
} // namespace L0
|
||||
25
level_zero/sysman/source/api/events/sysman_os_events.h
Normal file
25
level_zero/sysman/source/api/events/sysman_os_events.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "level_zero/sysman/source/os_sysman.h"
|
||||
#include <level_zero/zes_api.h>
|
||||
|
||||
namespace L0 {
|
||||
namespace Sysman {
|
||||
|
||||
class OsEvents {
|
||||
public:
|
||||
static OsEvents *create(OsSysman *pOsSysman);
|
||||
virtual bool eventListen(zes_event_type_flags_t &pEvent, uint64_t timeout) = 0;
|
||||
virtual ze_result_t eventRegister(zes_event_type_flags_t events) = 0;
|
||||
virtual ~OsEvents() {}
|
||||
};
|
||||
|
||||
} // namespace Sysman
|
||||
} // namespace L0
|
||||
14
level_zero/sysman/source/api/events/windows/CMakeLists.txt
Normal file
14
level_zero/sysman/source/api/events/windows/CMakeLists.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# Copyright (C) 2023 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
if(WIN32)
|
||||
target_sources(${L0_STATIC_LIB_NAME}
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sysman_os_events_imp.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sysman_os_events_imp.cpp
|
||||
)
|
||||
endif()
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "level_zero/sysman/source/api/events/windows/sysman_os_events_imp.h"
|
||||
|
||||
#include "level_zero/sysman/source/windows/sysman_kmd_sys_manager.h"
|
||||
#include "level_zero/sysman/source/windows/zes_os_sysman_imp.h"
|
||||
|
||||
namespace L0 {
|
||||
namespace Sysman {
|
||||
|
||||
void WddmEventsImp::registerEvents(zes_event_type_flags_t eventId, uint32_t requestId) {
|
||||
ze_result_t status = ZE_RESULT_SUCCESS;
|
||||
EventHandler event;
|
||||
KmdSysman::RequestProperty request;
|
||||
KmdSysman::ResponseProperty response;
|
||||
|
||||
request.requestId = requestId;
|
||||
request.commandId = KmdSysman::Command::RegisterEvent;
|
||||
request.componentId = KmdSysman::Component::InterfaceProperties;
|
||||
request.dataSize = sizeof(HANDLE);
|
||||
|
||||
event.requestId = requestId;
|
||||
event.id = eventId;
|
||||
|
||||
// create an event with a default security descriptor with no name
|
||||
bool manualResetObject = FALSE;
|
||||
bool isEventStateSignalled = FALSE;
|
||||
event.windowsHandle = createWddmEvent(NULL, manualResetObject, isEventStateSignalled, NULL);
|
||||
|
||||
memcpy_s(request.dataBuffer, sizeof(HANDLE), &event.windowsHandle, sizeof(HANDLE));
|
||||
|
||||
status = pKmdSysManager->requestSingle(request, response);
|
||||
|
||||
if (status != ZE_RESULT_SUCCESS) {
|
||||
closeWddmHandle(event.windowsHandle);
|
||||
return;
|
||||
}
|
||||
|
||||
eventList.push_back(event);
|
||||
}
|
||||
|
||||
void WddmEventsImp::unregisterEvents() {
|
||||
ze_result_t status = ZE_RESULT_SUCCESS;
|
||||
EventHandler event;
|
||||
KmdSysman::RequestProperty request;
|
||||
KmdSysman::ResponseProperty response;
|
||||
|
||||
setWddmEvent(exitHandle);
|
||||
|
||||
request.commandId = KmdSysman::Command::UnregisterEvent;
|
||||
request.componentId = KmdSysman::Component::InterfaceProperties;
|
||||
request.dataSize = sizeof(HANDLE);
|
||||
|
||||
for (uint32_t i = 0; i < eventList.size(); i++) {
|
||||
request.requestId = eventList[i].requestId;
|
||||
event.windowsHandle = eventList[i].windowsHandle;
|
||||
|
||||
memcpy_s(request.dataBuffer, sizeof(HANDLE), &event.windowsHandle, sizeof(HANDLE));
|
||||
|
||||
status = pKmdSysManager->requestSingle(request, response);
|
||||
|
||||
if (status == ZE_RESULT_SUCCESS) {
|
||||
closeWddmHandle(event.windowsHandle);
|
||||
}
|
||||
}
|
||||
|
||||
eventList.clear();
|
||||
}
|
||||
|
||||
ze_result_t WddmEventsImp::eventRegister(zes_event_type_flags_t events) {
|
||||
|
||||
unregisterEvents();
|
||||
|
||||
if (events & ZES_EVENT_TYPE_FLAG_ENERGY_THRESHOLD_CROSSED) {
|
||||
registerEvents(ZES_EVENT_TYPE_FLAG_ENERGY_THRESHOLD_CROSSED, KmdSysman::Events::EnergyThresholdCrossed);
|
||||
}
|
||||
|
||||
if (events & ZES_EVENT_TYPE_FLAG_DEVICE_SLEEP_STATE_ENTER) {
|
||||
registerEvents(ZES_EVENT_TYPE_FLAG_DEVICE_SLEEP_STATE_ENTER, KmdSysman::Events::EnterD3);
|
||||
}
|
||||
|
||||
if (events & ZES_EVENT_TYPE_FLAG_DEVICE_SLEEP_STATE_EXIT) {
|
||||
registerEvents(ZES_EVENT_TYPE_FLAG_DEVICE_SLEEP_STATE_EXIT, KmdSysman::Events::EnterD0);
|
||||
}
|
||||
|
||||
if (events & ZES_EVENT_TYPE_FLAG_DEVICE_DETACH) {
|
||||
registerEvents(ZES_EVENT_TYPE_FLAG_DEVICE_DETACH, KmdSysman::Events::EnterTDR);
|
||||
}
|
||||
|
||||
if (events & ZES_EVENT_TYPE_FLAG_DEVICE_ATTACH) {
|
||||
registerEvents(ZES_EVENT_TYPE_FLAG_DEVICE_ATTACH, KmdSysman::Events::ExitTDR);
|
||||
}
|
||||
|
||||
resetWddmEvent(exitHandle);
|
||||
|
||||
return (eventList.size() == 0) ? ZE_RESULT_ERROR_UNSUPPORTED_FEATURE : ZE_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
bool WddmEventsImp::eventListen(zes_event_type_flags_t &pEvent, uint64_t timeout) {
|
||||
HANDLE events[MAXIMUM_WAIT_OBJECTS];
|
||||
pEvent = 0;
|
||||
|
||||
// Note: whatever happens on this function, it should return true. If that's not the case, the upper loop in sysman.cpp will
|
||||
// cause an infinite loop for the case of "Infinite timeout". This may work on Linux since the implementation is poll based,
|
||||
// windows uses WaitForMultipleObjects, which is a blocking call.
|
||||
|
||||
// no events no listen. Less than MAXIMUM_WAIT_OBJECTS - 2 to left space for the exit handle.
|
||||
if (eventList.size() == 0 || (eventList.size() >= (MAXIMUM_WAIT_OBJECTS - 2))) {
|
||||
pEvent = ZES_EVENT_TYPE_FLAG_FORCE_UINT32;
|
||||
return true;
|
||||
}
|
||||
|
||||
// set every handle from pos 0 onwards...
|
||||
for (uint32_t i = 0; i < eventList.size(); i++) {
|
||||
events[i] = eventList[i].windowsHandle;
|
||||
}
|
||||
events[eventList.size()] = exitHandle;
|
||||
|
||||
// Setting the last handle for the exit handle, then the exit handle is signaled, it breaks from the wait.
|
||||
uint32_t signaledEvent = waitForMultipleWddmEvents(static_cast<uint32_t>(eventList.size() + 1), events, FALSE, static_cast<uint32_t>(timeout));
|
||||
|
||||
resetWddmEvent(exitHandle);
|
||||
// Was a timeout, exit event loop.
|
||||
if (signaledEvent == WAIT_TIMEOUT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Was the exit event and exit event loop.
|
||||
if (signaledEvent == eventList.size()) {
|
||||
pEvent = ZES_EVENT_TYPE_FLAG_FORCE_UINT32;
|
||||
} else {
|
||||
pEvent = eventList[signaledEvent].id;
|
||||
}
|
||||
|
||||
// Whatever reason exit the loop, WaitForMultipleObjects exited, exit from the loop must follow.
|
||||
return true;
|
||||
}
|
||||
|
||||
HANDLE WddmEventsImp::createWddmEvent(
|
||||
LPSECURITY_ATTRIBUTES lpEventAttributes,
|
||||
BOOL bManualReset,
|
||||
BOOL bInitialState,
|
||||
LPCWSTR lpName) {
|
||||
return CreateEvent(lpEventAttributes, bManualReset, bInitialState, lpName);
|
||||
}
|
||||
|
||||
void WddmEventsImp::closeWddmHandle(HANDLE exitHandle) {
|
||||
CloseHandle(exitHandle);
|
||||
}
|
||||
|
||||
void WddmEventsImp::resetWddmEvent(HANDLE resetHandle) {
|
||||
ResetEvent(resetHandle);
|
||||
}
|
||||
|
||||
void WddmEventsImp::setWddmEvent(HANDLE setHandle) {
|
||||
SetEvent(setHandle);
|
||||
}
|
||||
|
||||
uint32_t WddmEventsImp::waitForMultipleWddmEvents(_In_ DWORD nCount,
|
||||
_In_reads_(nCount) CONST HANDLE *lpHandles,
|
||||
_In_ BOOL bWaitAll,
|
||||
_In_ DWORD dwMilliseconds) {
|
||||
return WaitForMultipleObjects(nCount, lpHandles, bWaitAll, dwMilliseconds);
|
||||
}
|
||||
|
||||
WddmEventsImp::WddmEventsImp(OsSysman *pOsSysman) {
|
||||
WddmSysmanImp *pWddmSysmanImp = static_cast<WddmSysmanImp *>(pOsSysman);
|
||||
pKmdSysManager = &pWddmSysmanImp->getKmdSysManager();
|
||||
|
||||
// create an exit event with a default security decriptor with no name
|
||||
bool manualResetObject = FALSE;
|
||||
bool isEventStateSignalled = FALSE;
|
||||
exitHandle = createWddmEvent(NULL, manualResetObject, isEventStateSignalled, NULL);
|
||||
}
|
||||
|
||||
WddmEventsImp::~WddmEventsImp() {
|
||||
closeWddmHandle(exitHandle);
|
||||
}
|
||||
|
||||
OsEvents *OsEvents::create(OsSysman *pOsSysman) {
|
||||
WddmEventsImp *pWddmEventsImp = new WddmEventsImp(pOsSysman);
|
||||
return static_cast<OsEvents *>(pWddmEventsImp);
|
||||
}
|
||||
|
||||
} // namespace Sysman
|
||||
} // namespace L0
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shared/source/helpers/non_copyable_or_moveable.h"
|
||||
|
||||
#include "level_zero/sysman/source/api/events/sysman_os_events.h"
|
||||
#include "level_zero/sysman/source/windows/zes_os_sysman_imp.h"
|
||||
|
||||
namespace L0 {
|
||||
namespace Sysman {
|
||||
|
||||
class KmdSysManager;
|
||||
struct EventHandler {
|
||||
HANDLE windowsHandle;
|
||||
zes_event_type_flags_t id;
|
||||
uint32_t requestId;
|
||||
};
|
||||
|
||||
class WddmEventsImp : public OsEvents, NEO::NonCopyableOrMovableClass {
|
||||
public:
|
||||
bool eventListen(zes_event_type_flags_t &pEvent, uint64_t timeout) override;
|
||||
ze_result_t eventRegister(zes_event_type_flags_t events) override;
|
||||
WddmEventsImp(OsSysman *pOsSysman);
|
||||
~WddmEventsImp();
|
||||
|
||||
// Don't allow copies of the WddmEventsImp object
|
||||
WddmEventsImp(const WddmEventsImp &obj) = delete;
|
||||
WddmEventsImp &operator=(const WddmEventsImp &obj) = delete;
|
||||
|
||||
private:
|
||||
void registerEvents(zes_event_type_flags_t eventId, uint32_t requestId);
|
||||
void unregisterEvents();
|
||||
HANDLE exitHandle;
|
||||
|
||||
protected:
|
||||
MOCKABLE_VIRTUAL HANDLE createWddmEvent(
|
||||
LPSECURITY_ATTRIBUTES lpEventAttributes,
|
||||
BOOL bManualReset,
|
||||
BOOL bInitialState,
|
||||
LPCWSTR lpName);
|
||||
MOCKABLE_VIRTUAL void closeWddmHandle(HANDLE exitHandle);
|
||||
MOCKABLE_VIRTUAL void resetWddmEvent(HANDLE resetHandle);
|
||||
MOCKABLE_VIRTUAL void setWddmEvent(HANDLE setHandle);
|
||||
MOCKABLE_VIRTUAL uint32_t waitForMultipleWddmEvents(_In_ DWORD nCount,
|
||||
_In_reads_(nCount) CONST HANDLE *lpHandles,
|
||||
_In_ BOOL bWaitAll,
|
||||
_In_ DWORD dwMilliseconds);
|
||||
KmdSysManager *pKmdSysManager = nullptr;
|
||||
std::vector<EventHandler> eventList;
|
||||
};
|
||||
|
||||
} // namespace Sysman
|
||||
} // namespace L0
|
||||
Reference in New Issue
Block a user