172 lines
4.8 KiB
C++
172 lines
4.8 KiB
C++
// Copyright (C) 2018-2022 Intel Corporation
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
#include "utils.h"
|
|
|
|
#include <string>
|
|
#include <string.h>
|
|
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#include <psapi.h>
|
|
#include <tlhelp32.h>
|
|
#else
|
|
#include <sys/unistd.h>
|
|
#include <sys/wait.h>
|
|
#endif
|
|
|
|
|
|
std::string OS_PATH_JOIN(std::initializer_list<std::string> list) {
|
|
if (!list.size())
|
|
return "";
|
|
std::string res = *list.begin();
|
|
for (auto it = list.begin() + 1; it != list.end(); it++) {
|
|
res += OS_SEP + *it;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
std::string fileNameNoExt(const std::string &filepath) {
|
|
auto pos = filepath.rfind('.');
|
|
if (pos == std::string::npos) return filepath;
|
|
return filepath.substr(0, pos);
|
|
}
|
|
|
|
|
|
/// Parses number from provided string
|
|
static int parseLine(std::string line) {
|
|
std::string res = "";
|
|
for (auto c: line)
|
|
if (isdigit(c))
|
|
res += c;
|
|
if (res.empty())
|
|
// If number wasn't found return -1
|
|
return -1;
|
|
return std::stoi(res);
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
static PROCESS_MEMORY_COUNTERS getMemoryInfo() {
|
|
static PROCESS_MEMORY_COUNTERS pmc;
|
|
pmc.cb = sizeof(PROCESS_MEMORY_COUNTERS);
|
|
GetProcessMemoryInfo(GetCurrentProcess(),&pmc, pmc.cb);
|
|
return pmc;
|
|
}
|
|
|
|
size_t getVmSizeInKB() {
|
|
return getMemoryInfo().PagefileUsage / 1024;
|
|
}
|
|
|
|
size_t getVmPeakInKB() {
|
|
return getMemoryInfo().PeakPagefileUsage / 1024;
|
|
}
|
|
|
|
size_t getVmRSSInKB() {
|
|
return getMemoryInfo().WorkingSetSize / 1024;
|
|
}
|
|
|
|
size_t getVmHWMInKB() {
|
|
return getMemoryInfo().PeakWorkingSetSize / 1024;
|
|
}
|
|
|
|
size_t getThreadsNum() {
|
|
// first determine the id of the current process
|
|
DWORD const id = GetCurrentProcessId();
|
|
|
|
// then get a process list snapshot.
|
|
HANDLE const snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPALL, 0 );
|
|
|
|
// initialize the process entry structure.
|
|
PROCESSENTRY32 entry = { 0 };
|
|
entry.dwSize = sizeof( entry );
|
|
|
|
// get the first process info.
|
|
BOOL ret = true;
|
|
ret = Process32First( snapshot, &entry );
|
|
while( ret && entry.th32ProcessID != id ) {
|
|
ret = Process32Next( snapshot, &entry );
|
|
}
|
|
CloseHandle( snapshot );
|
|
return ret
|
|
? entry.cntThreads
|
|
: -1;
|
|
}
|
|
|
|
#else
|
|
size_t getSystemDataByName(char *name){
|
|
FILE* file = fopen("/proc/self/status", "r");
|
|
size_t result = 0;
|
|
if (file != nullptr) {
|
|
char line[128];
|
|
|
|
while (fgets(line, 128, file) != NULL) {
|
|
if (strncmp(line, name, strlen(name)) == 0) {
|
|
result = parseLine(line);
|
|
break;
|
|
}
|
|
}
|
|
fclose(file);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
size_t getVmSizeInKB() {return getSystemDataByName((char*) "VmSize:");}
|
|
size_t getVmPeakInKB() {return getSystemDataByName((char*) "VmPeak:");}
|
|
size_t getVmRSSInKB() {return getSystemDataByName((char*) "VmRSS:");}
|
|
size_t getVmHWMInKB() {return getSystemDataByName((char*) "VmHWM:");}
|
|
size_t getThreadsNum() {return getSystemDataByName((char*) "Threads:");}
|
|
|
|
#endif
|
|
|
|
int run_in_processes(const int &numprocesses, const std::function<void()> &function) {
|
|
#ifdef _WIN32
|
|
// TODO: implement run in separate process by using WinAPI
|
|
function();
|
|
return 0;
|
|
#else
|
|
std::vector<pid_t> child_pids(numprocesses);
|
|
|
|
for (int i = 0; i < numprocesses; i++) {
|
|
child_pids[i] = fork();
|
|
if (child_pids[i] == 0) {
|
|
function();
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
}
|
|
|
|
int status = 0;
|
|
for (int i = 0; i < numprocesses; i++) {
|
|
int _status = 0;
|
|
waitpid(child_pids[i], &_status, WSTOPPED);
|
|
if (_status) {
|
|
log_err("Process run # " << i << " failed with exitcode " << _status);
|
|
status = _status;
|
|
}
|
|
}
|
|
return status;
|
|
#endif
|
|
}
|
|
|
|
void auto_expand_env_vars(std::string &input) {
|
|
const static std::string pattern1 = "${", pattern2 = "}";
|
|
size_t pattern1_pos, pattern2_pos, envvar_start_pos, envvar_finish_pos;
|
|
while ((pattern1_pos = input.find(pattern1)) != std::string::npos) {
|
|
envvar_start_pos = pattern1_pos + pattern1.length();
|
|
if ((pattern2_pos = input.find(pattern2)) != std::string::npos) {
|
|
envvar_finish_pos = pattern2_pos - pattern2.length();
|
|
const std::string envvar_name = input.substr(envvar_start_pos, envvar_finish_pos - envvar_start_pos + 1);
|
|
const char *envvar_val = getenv(envvar_name.c_str());
|
|
if (envvar_val == NULL)
|
|
throw std::logic_error("Expected environment variable " + envvar_name + " is not set.");
|
|
const std::string envvar_val_s(envvar_val);
|
|
input.replace(pattern1_pos, pattern2_pos - pattern1_pos + 1, envvar_val_s);
|
|
}
|
|
}
|
|
}
|
|
std::string expand_env_vars(const std::string &input) {
|
|
std::string _input = input;
|
|
auto_expand_env_vars(_input);
|
|
return _input;
|
|
}
|