System.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. // Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Util/System.h>
  6. #include <AnKi/Util/Logger.h>
  7. #include <AnKi/Util/StringList.h>
  8. #include <AnKi/Util/Thread.h>
  9. #include <cstdio>
  10. #if ANKI_POSIX
  11. # include <unistd.h>
  12. # include <signal.h>
  13. #elif ANKI_OS_WINDOWS
  14. # include <AnKi/Util/Win32Minimal.h>
  15. #else
  16. # error "Unimplemented"
  17. #endif
  18. // For print backtrace
  19. #if ANKI_POSIX && !ANKI_OS_ANDROID
  20. # include <execinfo.h>
  21. # include <cstdlib>
  22. #endif
  23. #if ANKI_OS_ANDROID
  24. # include <android_native_app_glue.h>
  25. # include <fcntl.h>
  26. #endif
  27. namespace anki {
  28. U32 getCpuCoresCount()
  29. {
  30. #if ANKI_POSIX
  31. return U32(sysconf(_SC_NPROCESSORS_ONLN));
  32. #elif ANKI_OS_WINDOWS
  33. SYSTEM_INFO sysinfo;
  34. GetSystemInfo(&sysinfo);
  35. return sysinfo.dwNumberOfProcessors;
  36. #else
  37. # error "Unimplemented"
  38. #endif
  39. }
  40. void backtraceInternal(const Function<void(CString)>& lambda)
  41. {
  42. #if ANKI_POSIX && !ANKI_OS_ANDROID
  43. // Get addresses's for all entries on the stack
  44. const U32 maxStackSize = 64;
  45. void** array = static_cast<void**>(malloc(maxStackSize * sizeof(void*)));
  46. if(array)
  47. {
  48. const I32 size = ::backtrace(array, I32(maxStackSize));
  49. // Get symbols
  50. char** strings = backtrace_symbols(array, size);
  51. if(strings)
  52. {
  53. for(I32 i = 0; i < size; ++i)
  54. {
  55. lambda(strings[i]);
  56. }
  57. free(strings);
  58. }
  59. free(array);
  60. }
  61. #else
  62. lambda("backtrace() not supported in " ANKI_OS_STR);
  63. #endif
  64. }
  65. Bool runningFromATerminal()
  66. {
  67. #if ANKI_POSIX
  68. return isatty(fileno(stdin));
  69. #else
  70. return false;
  71. #endif
  72. }
  73. std::tm getLocalTime()
  74. {
  75. std::time_t t = std::time(nullptr);
  76. std::tm tm;
  77. #if ANKI_POSIX
  78. localtime_r(&t, &tm);
  79. #elif ANKI_OS_WINDOWS
  80. localtime_s(&tm, &t);
  81. #else
  82. # error See file
  83. #endif
  84. return tm;
  85. }
  86. #if ANKI_OS_ANDROID
  87. /// Get the name of the apk. Doesn't use File to open files because /proc files are a bit special.
  88. static Error getAndroidApkName(StringRaii& name)
  89. {
  90. const pid_t pid = getpid();
  91. StringRaii path(&name.getMemoryPool());
  92. path.sprintf("/proc/%d/cmdline", pid);
  93. const int fd = open(path.cstr(), O_RDONLY);
  94. if(fd < 0)
  95. {
  96. ANKI_UTIL_LOGE("open() failed for: %s", path.cstr());
  97. return Error::kFunctionFailed;
  98. }
  99. Array<char, 128> tmp;
  100. const ssize_t readBytes = read(fd, &tmp[0], sizeof(tmp));
  101. if(readBytes < 0 || readBytes == 0)
  102. {
  103. close(fd);
  104. ANKI_UTIL_LOGE("read() failed for: %s", path.cstr());
  105. return Error::kFunctionFailed;
  106. }
  107. name.create('?', readBytes);
  108. memcpy(&name[0], &tmp[0], readBytes);
  109. close(fd);
  110. return Error::kNone;
  111. }
  112. void* getAndroidCommandLineArguments(int& argc, char**& argv)
  113. {
  114. argc = 0;
  115. argv = 0;
  116. ANKI_ASSERT(g_androidApp);
  117. JNIEnv* env;
  118. g_androidApp->activity->vm->AttachCurrentThread(&env, NULL);
  119. // Call getIntent().getStringExtra()
  120. jobject me = g_androidApp->activity->clazz;
  121. jclass acl = env->GetObjectClass(me); // class pointer of NativeActivity;
  122. jmethodID giid = env->GetMethodID(acl, "getIntent", "()Landroid/content/Intent;");
  123. jobject intent = env->CallObjectMethod(me, giid); // Got our intent
  124. jclass icl = env->GetObjectClass(intent); // class pointer of Intent
  125. jmethodID gseid = env->GetMethodID(icl, "getStringExtra", "(Ljava/lang/String;)Ljava/lang/String;");
  126. jstring jsParam1 = static_cast<jstring>(env->CallObjectMethod(intent, gseid, env->NewStringUTF("cmd")));
  127. // Parse the command line args
  128. HeapMemoryPool pool(allocAligned, nullptr, "getAndroidCommandLineArguments temp");
  129. StringListRaii args(&pool);
  130. if(jsParam1)
  131. {
  132. const char* param1 = env->GetStringUTFChars(jsParam1, 0);
  133. args.splitString(param1, ' ');
  134. env->ReleaseStringUTFChars(jsParam1, param1);
  135. }
  136. // Add the apk name
  137. StringRaii apkName(&pool);
  138. if(!getAndroidApkName(apkName))
  139. {
  140. args.pushFront(apkName);
  141. }
  142. else
  143. {
  144. args.pushFront("unknown_apk");
  145. }
  146. // Allocate memory for all
  147. U32 allStringsSize = 0;
  148. for(const String& s : args)
  149. {
  150. allStringsSize += s.getLength() + 1;
  151. ++argc;
  152. }
  153. const PtrSize bufferSize = allStringsSize + sizeof(char*) * argc;
  154. void* buffer = mallocAligned(bufferSize, ANKI_SAFE_ALIGNMENT);
  155. // Set argv
  156. argv = static_cast<char**>(buffer);
  157. char* cbuffer = static_cast<char*>(buffer);
  158. cbuffer += sizeof(char*) * argc;
  159. U32 count = 0;
  160. for(const String& s : args)
  161. {
  162. memcpy(cbuffer, &s[0], s.getLength() + 1);
  163. argv[count++] = &cbuffer[0];
  164. cbuffer += s.getLength() + 1;
  165. }
  166. ANKI_ASSERT(ptrToNumber(cbuffer) == ptrToNumber(buffer) + bufferSize);
  167. return buffer;
  168. }
  169. void cleanupGetAndroidCommandLineArguments(void* ptr)
  170. {
  171. ANKI_ASSERT(ptr);
  172. freeAligned(ptr);
  173. }
  174. #endif
  175. // The 1st thing that executes before main
  176. void preMain()
  177. {
  178. Logger::allocateSingleton();
  179. ANKI_UTIL_LOGV("Pre main executed. This should be the 1st message");
  180. Thread::setCurrentThreadName("Main");
  181. }
  182. // The last thing that executes after main
  183. void postMain()
  184. {
  185. ANKI_UTIL_LOGV("Post main executed. This should be the last message");
  186. Logger::freeSingleton();
  187. }
  188. } // end namespace anki