Add event notification API

Change-Id: Ib6e8efbe6cdefaa7de1f74bd26993e9b4b011649
This commit is contained in:
Chris Freehill
2020-04-30 17:07:39 -05:00
parent 806f665a85
commit 2235ede34c
13 changed files with 1190 additions and 22 deletions
+225 -16
View File
@@ -47,6 +47,9 @@
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sstream>
#include <algorithm>
@@ -72,6 +75,23 @@
static const uint32_t kMaxOverdriveLevel = 20;
static rsmi_status_t errno_to_rsmi_status(uint32_t err) {
switch (err) {
case 0: return RSMI_STATUS_SUCCESS;
case ESRCH: return RSMI_STATUS_NOT_FOUND;
case EACCES: return RSMI_STATUS_PERMISSION;
case EPERM:
case ENOENT: return RSMI_STATUS_NOT_SUPPORTED;
case EBADF:
case EISDIR: return RSMI_STATUS_FILE_ERROR;
case EINTR: return RSMI_STATUS_INTERRUPT;
case EIO: return RSMI_STATUS_UNEXPECTED_SIZE;
case ENXIO: return RSMI_STATUS_UNEXPECTED_DATA;
case EBUSY: return RSMI_STATUS_BUSY;
default: return RSMI_STATUS_UNKNOWN_ERROR;
}
}
static rsmi_status_t handleException() {
try {
throw;
@@ -86,6 +106,8 @@ static rsmi_status_t handleException() {
} catch (const std::nested_exception& e) {
debug_print("Callback threw.\n");
return RSMI_STATUS_INTERNAL_EXCEPTION;
} catch (int erno) {
return errno_to_rsmi_status(erno);
} catch (...) {
debug_print("Unknown exception caught.\n");
return RSMI_STATUS_INTERNAL_EXCEPTION;
@@ -170,22 +192,6 @@ static pthread_mutex_t *get_mutex(uint32_t dv_ind) {
return dev->mutex();
}
static rsmi_status_t errno_to_rsmi_status(uint32_t err) {
switch (err) {
case 0: return RSMI_STATUS_SUCCESS;
case ESRCH: return RSMI_STATUS_NOT_FOUND;
case EACCES: return RSMI_STATUS_PERMISSION;
case EPERM:
case ENOENT: return RSMI_STATUS_NOT_SUPPORTED;
case EBADF:
case EISDIR: return RSMI_STATUS_FILE_ERROR;
case EINTR: return RSMI_STATUS_INTERRUPT;
case EIO: return RSMI_STATUS_UNEXPECTED_SIZE;
case ENXIO: return RSMI_STATUS_UNEXPECTED_DATA;
default: return RSMI_STATUS_UNKNOWN_ERROR;
}
}
static uint64_t get_multiplier_from_str(char units_char) {
uint32_t multiplier = 0;
@@ -3157,6 +3163,209 @@ rsmi_func_iter_next(rsmi_func_id_iter_handle_t handle) {
CATCH
}
static bool check_evt_notif_support(int kfd_fd) {
struct kfd_ioctl_get_version_args args = {0, 0};
if (ioctl(kfd_fd, AMDKFD_IOC_GET_VERSION, &args) == -1) {
return RSMI_STATUS_INIT_ERROR;
}
if (args.major_version < 2 && args.minor_version < 3) {
return false;
}
return true;
}
static const char *kPathKFDIoctl = "/dev/kfd";
rsmi_status_t
rsmi_event_notification_init(uint32_t dv_ind) {
TRY
GET_DEV_FROM_INDX
std::lock_guard<std::mutex> guard(*smi.kfd_notif_evt_fh_mutex());
if (smi.kfd_notif_evt_fh() == -1) {
int kfd_fd = open(kPathKFDIoctl, O_RDWR | O_CLOEXEC);
if (kfd_fd <= 0) {
return RSMI_STATUS_FILE_ERROR;
}
if (!check_evt_notif_support(kfd_fd)) {
close(kfd_fd);
return RSMI_STATUS_NOT_SUPPORTED;
}
smi.set_kfd_notif_evt_fh(kfd_fd);
}
smi.kfd_notif_evt_fh_refcnt_inc();
struct kfd_ioctl_smi_events_args args;
assert(dev->kfd_gpu_id() <= UINT32_MAX);
args.gpuid = static_cast<uint32_t>(dev->kfd_gpu_id());
int ret = ioctl(smi.kfd_notif_evt_fh(), AMDKFD_IOC_SMI_EVENTS, &args);
if (ret < 0) {
return errno_to_rsmi_status(errno);
}
if (args.anon_fd < 1) {
return RSMI_STATUS_NO_DATA;
}
dev->set_evt_notif_anon_fd(args.anon_fd);
FILE *anon_file_ptr = fdopen(args.anon_fd, "r");
if (anon_file_ptr == nullptr) {
close(dev->evt_notif_anon_fd());
return errno_to_rsmi_status(errno);
}
dev->set_evt_notif_anon_file_ptr(anon_file_ptr);
return RSMI_STATUS_SUCCESS;
CATCH
}
rsmi_status_t
rsmi_event_notification_mask_set(uint32_t dv_ind, uint64_t mask) {
TRY
GET_DEV_FROM_INDX
if (dev->evt_notif_anon_fd() == -1) {
return RSMI_INITIALIZATION_ERROR;
}
ssize_t ret = write(dev->evt_notif_anon_fd(), &mask, sizeof(uint64_t));
if (ret == -1) {
return errno_to_rsmi_status(errno);
}
return RSMI_STATUS_SUCCESS;
CATCH
}
rsmi_status_t
rsmi_event_notification_get(int timeout_ms,
uint32_t *num_elem, rsmi_evt_notification_data_t *data) {
TRY
if (num_elem == nullptr || data == nullptr || *num_elem == 0) {
return RSMI_STATUS_INVALID_ARGS;
}
uint32_t buffer_size = *num_elem;
*num_elem = 0;
rsmi_evt_notification_data_t *data_item;
// struct pollfd {
// int fd; /* file descriptor */
// short events; /* requested events */
// short revents; /* returned events */
// };
std::vector<struct pollfd> fds;
amd::smi::RocmSMI& smi = amd::smi::RocmSMI::getInstance();
std::vector<uint32_t> fd_indx_to_dev_id;
for (uint32_t i = 0; i < smi.monitor_devices().size(); ++i) {
if (smi.monitor_devices()[i]->evt_notif_anon_fd() == -1) {
continue;
}
fds.push_back({smi.monitor_devices()[i]->evt_notif_anon_fd(),
POLLIN | POLLRDNORM, 0});
fd_indx_to_dev_id.push_back(i);
}
auto fill_data_buffer = [&](bool did_poll) {
for (uint32_t i = 0; i < fds.size(); ++i) {
if (did_poll) {
if (!(fds[i].revents & (POLLIN | POLLRDNORM))) {
continue;
}
}
if (*num_elem >= buffer_size) {
return;
}
FILE *anon_fp =
smi.monitor_devices()[fd_indx_to_dev_id[i]]->evt_notif_anon_file_ptr();
data_item =
reinterpret_cast<rsmi_evt_notification_data_t *>(&data[*num_elem]);
uint64_t event;
while (fscanf(anon_fp, "%lx %63s\n", &event,
reinterpret_cast<char *>(&data_item->message)) == 2) {
/* Output is in format as "event information\n"
* Both event are expressed in hex.
* information is a string
*/
data_item->event = (rsmi_evt_notification_type_t)event;
data_item->dv_ind = fd_indx_to_dev_id[i];
++(*num_elem);
if (*num_elem >= buffer_size) {
break;
}
data_item =
reinterpret_cast<rsmi_evt_notification_data_t *>(&data[*num_elem]);
}
}
};
// Collect any left-over events from a poll in a previous call to
// rsmi_event_notification_get()
fill_data_buffer(false);
if (*num_elem < buffer_size && errno != EAGAIN) {
return errno_to_rsmi_status(errno);
} else if (*num_elem >= buffer_size) {
return RSMI_STATUS_SUCCESS;
}
// We still have buffer left, see if there are any new events
int p_ret = poll(fds.data(), fds.size(), timeout_ms);
if (p_ret > 0) {
fill_data_buffer(true);
} else if (p_ret < 0) {
return errno_to_rsmi_status(errno);
}
if (*num_elem == 0) {
return RSMI_STATUS_NO_DATA;
}
return RSMI_STATUS_SUCCESS;
CATCH
}
rsmi_status_t rsmi_event_notification_stop(uint32_t dv_ind) {
TRY
GET_DEV_FROM_INDX
std::lock_guard<std::mutex> guard(*smi.kfd_notif_evt_fh_mutex());
if (dev->evt_notif_anon_fd() == -1) {
return RSMI_STATUS_INVALID_ARGS;
}
// close(dev->evt_notif_anon_fd());
FILE *anon_fp = smi.monitor_devices()[dv_ind]->evt_notif_anon_file_ptr();
fclose(anon_fp);
assert(errno == 0 || errno == EAGAIN);
dev->set_evt_notif_anon_file_ptr(nullptr);
dev->set_evt_notif_anon_fd(-1);
if (!smi.kfd_notif_evt_fh_refcnt_dec()) {
int ret = close(smi.kfd_notif_evt_fh());
smi.set_kfd_notif_evt_fh(-1);
if (ret < 0) {
return errno_to_rsmi_status(errno);
}
}
return RSMI_STATUS_SUCCESS;
CATCH
}
// UNDOCUMENTED FUNCTIONS
// This functions are not declared in rocm_smi.h. They are either not fully
// supported, or to be used for test purposes.
+2 -3
View File
@@ -458,9 +458,8 @@ static const std::map<const char *, dev_depends_t> kDevFuncDependsMap = {
if (X) return X; \
}
Device::Device(std::string p, RocmSMI_env_vars const *e) : path_(p), env_(e) {
monitor_ = nullptr;
Device::Device(std::string p, RocmSMI_env_vars const *e) : monitor_(nullptr),
path_(p), env_(e), evt_notif_anon_fd_(-1) {
#ifdef NDEBUG
env_ = nullptr;
#endif
+10 -2
View File
@@ -266,7 +266,7 @@ RocmSMI::Initialize(uint64_t flags) {
if (ret != 0) {
throw amd::smi::rsmi_exception(RSMI_INITIALIZATION_ERROR,
"Failed to initialize rocm_smi library (amdgpu node discovery.");
"Failed to initialize rocm_smi library (amdgpu node discovery).");
}
std::map<uint64_t, std::shared_ptr<KFDNode>> tmp_map;
@@ -299,12 +299,20 @@ RocmSMI::Initialize(uint64_t flags) {
void
RocmSMI::Cleanup() {
if (kfd_notif_evt_fh() >= 0) {
int ret = close(kfd_notif_evt_fh());
if (ret < 0) {
throw amd::smi::rsmi_exception(RSMI_STATUS_FILE_ERROR,
"Failed to close kfd file handle on shutdown.");
}
}
s_monitor_devices.clear();
devices_.clear();
monitors_.clear();
}
RocmSMI::RocmSMI(uint64_t flags) : init_options_(flags) {
RocmSMI::RocmSMI(uint64_t flags) : init_options_(flags),
kfd_notif_evt_fh_(-1), kfd_notif_evt_fh_refcnt_(0) {
}
RocmSMI::~RocmSMI() {