OpenShot Audio Library | OpenShotAudio  0.6.0
juce_SystemStats.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2022 - Raw Material Software Limited
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  The code included in this file is provided under the terms of the ISC license
11  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12  To use, copy, modify, and/or distribute this software for any purpose with or
13  without fee is hereby granted provided that the above copyright notice and
14  this permission notice appear in all copies.
15 
16  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18  DISCLAIMED.
19 
20  ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
27 {
28  // Some basic tests, to keep an eye on things and make sure these types work ok
29  // on all platforms. Let me know if any of these assertions fail on your system!
30  static_assert (sizeof (pointer_sized_int) == sizeof (void*), "Basic sanity test failed: please report!");
31  static_assert (sizeof (int8) == 1, "Basic sanity test failed: please report!");
32  static_assert (sizeof (uint8) == 1, "Basic sanity test failed: please report!");
33  static_assert (sizeof (int16) == 2, "Basic sanity test failed: please report!");
34  static_assert (sizeof (uint16) == 2, "Basic sanity test failed: please report!");
35  static_assert (sizeof (int32) == 4, "Basic sanity test failed: please report!");
36  static_assert (sizeof (uint32) == 4, "Basic sanity test failed: please report!");
37  static_assert (sizeof (int64) == 8, "Basic sanity test failed: please report!");
38  static_assert (sizeof (uint64) == 8, "Basic sanity test failed: please report!");
39 
40  return "JUCE v" JUCE_STRINGIFY (JUCE_MAJOR_VERSION)
41  "." JUCE_STRINGIFY (JUCE_MINOR_VERSION)
42  "." JUCE_STRINGIFY (JUCE_BUILDNUMBER);
43 }
44 
45 #if JUCE_ANDROID && ! defined (JUCE_DISABLE_JUCE_VERSION_PRINTING)
46  #define JUCE_DISABLE_JUCE_VERSION_PRINTING 1
47 #endif
48 
49 #if JUCE_DEBUG && ! JUCE_DISABLE_JUCE_VERSION_PRINTING
50  struct JuceVersionPrinter
51  {
52  JuceVersionPrinter()
53  {
55  }
56  };
57 
58  static JuceVersionPrinter juceVersionPrinter;
59 #endif
60 
62 {
64  if (auto ids = getMachineIdentifiers (flag); ! ids.isEmpty())
65  return ids;
66 
67  jassertfalse; // Failed to create any IDs!
68  return {};
69 }
70 
71 String getLegacyUniqueDeviceID();
72 
74 {
75  auto macAddressProvider = [] (StringArray& arr)
76  {
77  for (const auto& mac : MACAddress::getAllAddresses())
78  arr.add (mac.toString());
79  };
80 
81  auto fileSystemProvider = [] (StringArray& arr)
82  {
83  #if JUCE_WINDOWS
84  File f (File::getSpecialLocation (File::windowsSystemDirectory));
85  #else
86  File f ("~");
87  #endif
88  if (auto num = f.getFileIdentifier())
89  arr.add (String::toHexString ((int64) num));
90  };
91 
92  auto legacyIdProvider = [] ([[maybe_unused]] StringArray& arr)
93  {
94  #if JUCE_WINDOWS
95  arr.add (getLegacyUniqueDeviceID());
96  #endif
97  };
98 
99  auto uniqueIdProvider = [] (StringArray& arr)
100  {
101  arr.add (getUniqueDeviceID());
102  };
103 
104  struct Provider { MachineIdFlags flag; void (*func) (StringArray&); };
105  static const Provider providers[] =
106  {
107  { MachineIdFlags::macAddresses, macAddressProvider },
108  { MachineIdFlags::fileSystemId, fileSystemProvider },
109  { MachineIdFlags::legacyUniqueId, legacyIdProvider },
110  { MachineIdFlags::uniqueId, uniqueIdProvider }
111  };
112 
113  StringArray ids;
114 
115  for (const auto& provider : providers)
116  {
117  if (hasBitValueSet (flags, provider.flag))
118  provider.func (ids);
119  }
120 
121  return ids;
122 }
123 
124 //==============================================================================
125 struct CPUInformation
126 {
127  CPUInformation() noexcept { initialise(); }
128 
129  void initialise() noexcept;
130 
131  int numLogicalCPUs = 0, numPhysicalCPUs = 0;
132 
133  bool hasMMX = false, hasSSE = false, hasSSE2 = false, hasSSE3 = false,
134  has3DNow = false, hasFMA3 = false, hasFMA4 = false, hasSSSE3 = false,
135  hasSSE41 = false, hasSSE42 = false, hasAVX = false, hasAVX2 = false,
136  hasAVX512F = false, hasAVX512BW = false, hasAVX512CD = false,
137  hasAVX512DQ = false, hasAVX512ER = false, hasAVX512IFMA = false,
138  hasAVX512PF = false, hasAVX512VBMI = false, hasAVX512VL = false,
139  hasAVX512VPOPCNTDQ = false,
140  hasNeon = false;
141 };
142 
143 static const CPUInformation& getCPUInformation() noexcept
144 {
145  static CPUInformation info;
146  return info;
147 }
148 
149 int SystemStats::getNumCpus() noexcept { return getCPUInformation().numLogicalCPUs; }
150 int SystemStats::getNumPhysicalCpus() noexcept { return getCPUInformation().numPhysicalCPUs; }
151 bool SystemStats::hasMMX() noexcept { return getCPUInformation().hasMMX; }
152 bool SystemStats::has3DNow() noexcept { return getCPUInformation().has3DNow; }
153 bool SystemStats::hasFMA3() noexcept { return getCPUInformation().hasFMA3; }
154 bool SystemStats::hasFMA4() noexcept { return getCPUInformation().hasFMA4; }
155 bool SystemStats::hasSSE() noexcept { return getCPUInformation().hasSSE; }
156 bool SystemStats::hasSSE2() noexcept { return getCPUInformation().hasSSE2; }
157 bool SystemStats::hasSSE3() noexcept { return getCPUInformation().hasSSE3; }
158 bool SystemStats::hasSSSE3() noexcept { return getCPUInformation().hasSSSE3; }
159 bool SystemStats::hasSSE41() noexcept { return getCPUInformation().hasSSE41; }
160 bool SystemStats::hasSSE42() noexcept { return getCPUInformation().hasSSE42; }
161 bool SystemStats::hasAVX() noexcept { return getCPUInformation().hasAVX; }
162 bool SystemStats::hasAVX2() noexcept { return getCPUInformation().hasAVX2; }
163 bool SystemStats::hasAVX512F() noexcept { return getCPUInformation().hasAVX512F; }
164 bool SystemStats::hasAVX512BW() noexcept { return getCPUInformation().hasAVX512BW; }
165 bool SystemStats::hasAVX512CD() noexcept { return getCPUInformation().hasAVX512CD; }
166 bool SystemStats::hasAVX512DQ() noexcept { return getCPUInformation().hasAVX512DQ; }
167 bool SystemStats::hasAVX512ER() noexcept { return getCPUInformation().hasAVX512ER; }
168 bool SystemStats::hasAVX512IFMA() noexcept { return getCPUInformation().hasAVX512IFMA; }
169 bool SystemStats::hasAVX512PF() noexcept { return getCPUInformation().hasAVX512PF; }
170 bool SystemStats::hasAVX512VBMI() noexcept { return getCPUInformation().hasAVX512VBMI; }
171 bool SystemStats::hasAVX512VL() noexcept { return getCPUInformation().hasAVX512VL; }
172 bool SystemStats::hasAVX512VPOPCNTDQ() noexcept { return getCPUInformation().hasAVX512VPOPCNTDQ; }
173 bool SystemStats::hasNeon() noexcept { return getCPUInformation().hasNeon; }
174 
175 
176 //==============================================================================
178 {
179  String result;
180 
181  #if JUCE_ANDROID || JUCE_MINGW || JUCE_WASM
182  jassertfalse; // sorry, not implemented yet!
183 
184  #elif JUCE_WINDOWS
185  HANDLE process = GetCurrentProcess();
186  SymInitialize (process, nullptr, TRUE);
187 
188  void* stack[128];
189  int frames = (int) CaptureStackBackTrace (0, numElementsInArray (stack), stack, nullptr);
190 
191  HeapBlock<SYMBOL_INFO> symbol;
192  symbol.calloc (sizeof (SYMBOL_INFO) + 256, 1);
193  symbol->MaxNameLen = 255;
194  symbol->SizeOfStruct = sizeof (SYMBOL_INFO);
195 
196  for (int i = 0; i < frames; ++i)
197  {
198  DWORD64 displacement = 0;
199 
200  if (SymFromAddr (process, (DWORD64) stack[i], &displacement, symbol))
201  {
202  result << i << ": ";
203 
204  IMAGEHLP_MODULE64 moduleInfo;
205  zerostruct (moduleInfo);
206  moduleInfo.SizeOfStruct = sizeof (moduleInfo);
207 
208  if (::SymGetModuleInfo64 (process, symbol->ModBase, &moduleInfo))
209  result << moduleInfo.ModuleName << ": ";
210 
211  result << symbol->Name << " + 0x" << String::toHexString ((int64) displacement) << newLine;
212  }
213  }
214 
215  #else
216  void* stack[128];
217  auto frames = backtrace (stack, numElementsInArray (stack));
218  char** frameStrings = backtrace_symbols (stack, frames);
219 
220  for (auto i = (decltype (frames)) 0; i < frames; ++i)
221  result << frameStrings[i] << newLine;
222 
223  ::free (frameStrings);
224  #endif
225 
226  return result;
227 }
228 
229 //==============================================================================
230 #if ! JUCE_WASM
231 
232 static SystemStats::CrashHandlerFunction globalCrashHandler = nullptr;
233 
234 #if JUCE_WINDOWS
235 static LONG WINAPI handleCrash (LPEXCEPTION_POINTERS ep)
236 {
237  globalCrashHandler (ep);
238  return EXCEPTION_EXECUTE_HANDLER;
239 }
240 #else
241 static void handleCrash (int signum)
242 {
243  globalCrashHandler ((void*) (pointer_sized_int) signum);
244  ::kill (getpid(), SIGKILL);
245 }
246 
247 int juce_siginterrupt (int sig, int flag);
248 #endif
249 
251 {
252  jassert (handler != nullptr); // This must be a valid function.
253  globalCrashHandler = handler;
254 
255  #if JUCE_WINDOWS
256  SetUnhandledExceptionFilter (handleCrash);
257  #else
258  const int signals[] = { SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGABRT, SIGSYS };
259 
260  for (int i = 0; i < numElementsInArray (signals); ++i)
261  {
262  ::signal (signals[i], handleCrash);
263  juce_siginterrupt (signals[i], 1);
264  }
265  #endif
266 }
267 
268 #endif
269 
271 {
272  #if JUCE_MAC || JUCE_IOS
273  static bool isRunningInAppSandbox = [&]
274  {
276 
277  #if JUCE_MAC
278  bundle = bundle.getParentDirectory().getParentDirectory();
279  #endif
280 
281  if (bundle.isDirectory())
282  return bundle.getFileExtension() == ".appex";
283 
284  return false;
285  }();
286 
287  return isRunningInAppSandbox;
288  #else
289  return false;
290  #endif
291 }
292 
293 #if JUCE_UNIT_TESTS
294 
295 class UniqueHardwareIDTest final : public UnitTest
296 {
297 public:
298  //==============================================================================
299  UniqueHardwareIDTest() : UnitTest ("UniqueHardwareID", UnitTestCategories::analytics) {}
300 
301  void runTest() override
302  {
303  beginTest ("getUniqueDeviceID returns usable data.");
304  {
305  expect (SystemStats::getUniqueDeviceID().isNotEmpty());
306  }
307  }
308 };
309 
310 static UniqueHardwareIDTest uniqueHardwareIDTest;
311 
312 #endif
313 
314 } // namespace juce
bool isDirectory() const
String getFileExtension() const
Definition: juce_File.cpp:672
static File JUCE_CALLTYPE getSpecialLocation(const SpecialLocationType type)
@ invokedExecutableFile
Definition: juce_File.h:949
File getParentDirectory() const
Definition: juce_File.cpp:358
uint64 getFileIdentifier() const
void calloc(SizeType newNumElements, const size_t elementSize=sizeof(ElementType))
static Array< MACAddress > getAllAddresses()
void add(String stringToAdd)
bool isEmpty() const noexcept
static String toHexString(IntegerType number)
Definition: juce_String.h:1097
static bool hasAVX512CD() noexcept
static String getStackBacktrace()
static bool hasMMX() noexcept
static void setApplicationCrashHandler(CrashHandlerFunction)
static int getNumPhysicalCpus() noexcept
static bool hasAVX512ER() noexcept
static bool has3DNow() noexcept
static bool hasAVX2() noexcept
static bool hasAVX512VPOPCNTDQ() noexcept
static bool hasSSE() noexcept
static bool hasAVX512DQ() noexcept
static bool isRunningInAppExtensionSandbox() noexcept
static bool hasNeon() noexcept
static bool hasAVX512F() noexcept
static bool hasSSE3() noexcept
static bool hasSSE2() noexcept
static bool hasAVX() noexcept
void(*)(void *) CrashHandlerFunction
static bool hasAVX512VBMI() noexcept
static String getUniqueDeviceID()
@ legacyUniqueId
Only implemented on Windows. A hash of the full smbios table, may be unstable on certain machines.
@ uniqueId
The most stable kind of machine identifier. A good default to use.
@ fileSystemId
The filesystem id of the user's home directory (or system directory on Windows).
@ macAddresses
All Mac addresses of the machine.
static bool hasSSSE3() noexcept
static bool hasAVX512VL() noexcept
static bool hasAVX512PF() noexcept
static bool hasSSE41() noexcept
static StringArray getDeviceIdentifiers()
static bool hasFMA4() noexcept
static String getJUCEVersion()
static bool hasSSE42() noexcept
static StringArray getMachineIdentifiers(MachineIdFlags flags)
static bool hasFMA3() noexcept
static bool hasAVX512IFMA() noexcept
static bool hasAVX512BW() noexcept
static int getNumCpus() noexcept