diff --git a/projects/rocm-smi-lib/src/rocm_smi_device.cc b/projects/rocm-smi-lib/src/rocm_smi_device.cc index 0d602f4595..0eade39ce5 100755 --- a/projects/rocm-smi-lib/src/rocm_smi_device.cc +++ b/projects/rocm-smi-lib/src/rocm_smi_device.cc @@ -41,10 +41,10 @@ * */ + #include #include #include - #include #include #include diff --git a/projects/rocm-smi-lib/third_party/shared_mutex/shared_mutex.cc b/projects/rocm-smi-lib/third_party/shared_mutex/shared_mutex.cc index 55fac1f5b5..ae211a81c3 100755 --- a/projects/rocm-smi-lib/third_party/shared_mutex/shared_mutex.cc +++ b/projects/rocm-smi-lib/third_party/shared_mutex/shared_mutex.cc @@ -1,5 +1,5 @@ /* -Modifications Copyright © 2019 – 2020 Advanced Micro Devices, Inc. All Rights +Modifications Copyright 2019 - 2022 Advanced Micro Devices, Inc. All Rights Reserved. Copyright (c) 2018 Oleg Yamnikov @@ -34,8 +34,50 @@ THE SOFTWARE. #include // clock_gettime #include +#include +#include +#include +#include +#include + #include "rocm_smi/rocm_smi_exception.h" +// find which processes are using the file by searching /proc/*/fd +static std::vector lsof(const char* filename) { + struct dirent *entry = nullptr; + DIR *dp = nullptr; + std::vector process_id; + + dp = opendir("/proc"); + if (dp != nullptr) { + while ((entry = readdir(dp))) { + std::string id(entry->d_name); + // the process id should be a number + if (std::all_of(id.begin(), id.end(), ::isdigit)) { + process_id.push_back(entry->d_name); + } + } + closedir(dp); + } + + std::vector matched_process; + for (unsigned int i=0; i < process_id.size(); i++) { + std::string folder_name("/proc/"); + folder_name += process_id[i]+"/fd/"; + dp = opendir(folder_name.c_str()); + if (dp == nullptr) continue; + while ((entry = readdir(dp))) { + std::string p(folder_name+entry->d_name); + char buf[512]; + memset(buf, 0, 512); + if (readlink(p.c_str(), buf, sizeof(buf)-1) < 0) continue; + if (!strcmp(filename, buf)) matched_process.push_back(process_id[i]); + } + closedir(dp); + } + return matched_process; +} + shared_mutex_t shared_mutex_init(const char *name, mode_t mode) { shared_mutex_t mutex = {NULL, 0, NULL, 0}; errno = 0; @@ -81,6 +123,15 @@ shared_mutex_t shared_mutex_init(const char *name, mode_t mode) { pthread_mutex_t *mutex_ptr = reinterpret_cast(addr); + // When process crash before unlock the mutex, the mutex is in bad status. + // reset the mutex if no process is using it + std::vector ids = lsof(name); + if (ids.size() == 0) { // no process is using it + memset(mutex_ptr, 0, sizeof(pthread_mutex_t)); + // Set mutex.created == 1 so that it can be initialized latter. + mutex.created = 1; + } + // Make sure the mutex wasn't left in a locked state. If we can't // acquire it in 5 sec., re-do everything. struct timespec expireTime;