You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

166 lines
3.7KB

  1. #include "system.hpp"
  2. #include "string.hpp"
  3. #include <thread>
  4. #include <dirent.h>
  5. #include <sys/stat.h>
  6. #if defined ARCH_LIN || defined ARCH_MAC
  7. #include <pthread.h>
  8. #include <sched.h>
  9. #include <execinfo.h> // for backtrace and backtrace_symbols
  10. #endif
  11. #if defined ARCH_WIN
  12. #include <windows.h>
  13. #include <shellapi.h>
  14. #include <processthreadsapi.h>
  15. #include <dbghelp.h>
  16. #endif
  17. namespace rack {
  18. namespace system {
  19. std::list<std::string> listEntries(const std::string &path) {
  20. std::list<std::string> filenames;
  21. DIR *dir = opendir(path.c_str());
  22. if (dir) {
  23. struct dirent *d;
  24. while ((d = readdir(dir))) {
  25. std::string filename = d->d_name;
  26. if (filename == "." || filename == "..")
  27. continue;
  28. filenames.push_back(path + "/" + filename);
  29. }
  30. closedir(dir);
  31. }
  32. return filenames;
  33. }
  34. bool isFile(const std::string &path) {
  35. struct stat statbuf;
  36. if (stat(path.c_str(), &statbuf))
  37. return false;
  38. return S_ISREG(statbuf.st_mode);
  39. }
  40. bool isDirectory(const std::string &path) {
  41. struct stat statbuf;
  42. if (stat(path.c_str(), &statbuf))
  43. return false;
  44. return S_ISDIR(statbuf.st_mode);
  45. }
  46. void copyFile(const std::string &srcPath, const std::string &destPath) {
  47. // Open files
  48. FILE *source = fopen(srcPath.c_str(), "rb");
  49. if (!source)
  50. return;
  51. DEFER({
  52. fclose(source);
  53. });
  54. FILE *dest = fopen(destPath.c_str(), "wb");
  55. if (!dest)
  56. return;
  57. DEFER({
  58. fclose(dest);
  59. });
  60. // Copy buffer
  61. const int bufferSize = (1<<15);
  62. char buffer[bufferSize];
  63. while (1) {
  64. size_t size = fread(buffer, 1, bufferSize, source);
  65. if (size == 0)
  66. break;
  67. size = fwrite(buffer, 1, size, dest);
  68. if (size == 0)
  69. break;
  70. }
  71. }
  72. void createDirectory(const std::string &path) {
  73. #if defined ARCH_WIN
  74. CreateDirectory(path.c_str(), NULL);
  75. #else
  76. mkdir(path.c_str(), 0755);
  77. #endif
  78. }
  79. int getPhysicalCoreCount() {
  80. // TODO Return the physical cores, not logical cores.
  81. return std::thread::hardware_concurrency();
  82. }
  83. void setThreadName(const std::string &name) {
  84. #if defined ARCH_LIN
  85. pthread_setname_np(pthread_self(), name.c_str());
  86. #elif defined ARCH_WIN
  87. // Unsupported on Windows
  88. #endif
  89. }
  90. void setThreadRealTime() {
  91. #if defined ARCH_LIN || defined ARCH_MAC
  92. // Round-robin scheduler policy
  93. int policy = SCHED_RR;
  94. struct sched_param param;
  95. param.sched_priority = sched_get_priority_max(policy);
  96. pthread_setschedparam(pthread_self(), policy, &param);
  97. #elif defined ARCH_WIN
  98. // Set process class first
  99. SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
  100. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
  101. #endif
  102. }
  103. std::string getStackTrace() {
  104. int stackLen = 128;
  105. void *stack[stackLen];
  106. std::string s;
  107. #if defined ARCH_LIN || defined ARCH_MAC
  108. stackLen = backtrace(stack, stackLen);
  109. char **strings = backtrace_symbols(stack, stackLen);
  110. for (int i = 1; i < stackLen; i++) {
  111. s += string::f("%d: %s\n", stackLen - i - 1, strings[i]);
  112. }
  113. free(strings);
  114. #elif defined ARCH_WIN
  115. HANDLE process = GetCurrentProcess();
  116. SymInitialize(process, NULL, true);
  117. stackLen = CaptureStackBackTrace(0, stackLen, stack, NULL);
  118. SYMBOL_INFO *symbol = (SYMBOL_INFO*) calloc(sizeof(SYMBOL_INFO) + 256, 1);
  119. symbol->MaxNameLen = 255;
  120. symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
  121. for (int i = 1; i < stackLen; i++) {
  122. SymFromAddr(process, (DWORD64) stack[i], 0, symbol);
  123. s += string::f("%d: %s 0x%0x\n", stackLen - i - 1, symbol->Name, symbol->Address);
  124. }
  125. free(symbol);
  126. #endif
  127. return s;
  128. }
  129. void openBrowser(const std::string &url) {
  130. #if defined ARCH_LIN
  131. std::string command = "xdg-open " + url;
  132. (void) std::system(command.c_str());
  133. #endif
  134. #if defined ARCH_MAC
  135. std::string command = "open " + url;
  136. std::system(command.c_str());
  137. #endif
  138. #if defined ARCH_WIN
  139. ShellExecute(NULL, "open", url.c_str(), NULL, NULL, SW_SHOWNORMAL);
  140. #endif
  141. }
  142. } // namespace system
  143. } // namespace rack