| 67 | }; |
| 68 | |
| 69 | ThreadController::ThreadController() { |
| 70 | std::vector<std::string> get_names = { |
| 71 | "MKL_Get_Max_Threads", |
| 72 | "openblas_get_num_threads", |
| 73 | "openblas_get_num_threads64_", |
| 74 | "omp_get_num_threads"}; |
| 75 | std::vector<std::string> set_names = { |
| 76 | "MKL_Set_Num_Threads", |
| 77 | "openblas_set_num_threads", |
| 78 | "openblas_set_num_threads64_", |
| 79 | "omp_set_num_threads"}; |
| 80 | |
| 81 | #ifdef MLX_HAS_DLOPEN_NOLOAD |
| 82 | auto lib_names = find_loaded_lib_names(); |
| 83 | for (auto i = 0; i < get_names.size(); i++) { |
| 84 | auto get_name = get_names[i]; |
| 85 | auto set_name = set_names[i]; |
| 86 | for (auto l = 0; l <= lib_names.size(); l++) { |
| 87 | // at the last resort, we test main executable |
| 88 | const char* lib_name = |
| 89 | (l < lib_names.size() ? lib_names[l].c_str() : nullptr); |
| 90 | auto lib = dlopen(lib_name, RTLD_NOW | RTLD_NOLOAD); |
| 91 | if (lib) { |
| 92 | auto get_sym = dlsym(lib, get_name.c_str()); |
| 93 | auto set_sym = dlsym(lib, set_name.c_str()); |
| 94 | if (get_sym && set_sym) { |
| 95 | symbols_.push_back( |
| 96 | std::make_shared<ThreadControllerSym>(lib, get_sym, set_sym)); |
| 97 | break; |
| 98 | } |
| 99 | } else { |
| 100 | dlclose(lib); |
| 101 | } |
| 102 | } |
| 103 | } |
| 104 | #endif |
| 105 | } |
| 106 | |
| 107 | ThreadControllerState ThreadController::limit() { |
| 108 | ThreadControllerState state(symbols_.size()); |
nothing calls this directly
no test coverage detected