2 ==============================================================================
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
7 JUCE is an open source library subject to commercial or open-source
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.
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
20 ==============================================================================
26 String
SystemStats::getJUCEVersion()
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!");
40 return "JUCE v" JUCE_STRINGIFY(JUCE_MAJOR_VERSION
)
41 "." JUCE_STRINGIFY(JUCE_MINOR_VERSION
)
42 "." JUCE_STRINGIFY(JUCE_BUILDNUMBER
);
45 #if JUCE_ANDROID && ! defined (JUCE_DISABLE_JUCE_VERSION_PRINTING)
46 #define JUCE_DISABLE_JUCE_VERSION_PRINTING 1
49 #if JUCE_DEBUG && ! JUCE_DISABLE_JUCE_VERSION_PRINTING
50 struct JuceVersionPrinter
54 DBG (SystemStats::getJUCEVersion());
58 static JuceVersionPrinter juceVersionPrinter
;
61 StringArray
SystemStats::getDeviceIdentifiers()
66 File
f (File::getSpecialLocation (File::windowsSystemDirectory
));
70 if (auto num
= f
.getFileIdentifier())
72 ids
.add (String::toHexString ((int64
) num
));
75 jassert (! ids
.isEmpty()); // Failed to create any IDs!
79 //==============================================================================
82 CPUInformation() noexcept
{ initialise(); }
84 void initialise() noexcept
;
86 int numLogicalCPUs
= 0, numPhysicalCPUs
= 0;
88 bool hasMMX
= false, hasSSE
= false, hasSSE2
= false, hasSSE3
= false,
89 has3DNow
= false, hasFMA3
= false, hasFMA4
= false, hasSSSE3
= false,
90 hasSSE41
= false, hasSSE42
= false, hasAVX
= false, hasAVX2
= false,
91 hasAVX512F
= false, hasAVX512BW
= false, hasAVX512CD
= false,
92 hasAVX512DQ
= false, hasAVX512ER
= false, hasAVX512IFMA
= false,
93 hasAVX512PF
= false, hasAVX512VBMI
= false, hasAVX512VL
= false,
94 hasAVX512VPOPCNTDQ
= false,
98 static const CPUInformation
& getCPUInformation() noexcept
100 static CPUInformation info
;
104 int SystemStats::getNumCpus() noexcept
{ return getCPUInformation().numLogicalCPUs
; }
105 int SystemStats::getNumPhysicalCpus() noexcept
{ return getCPUInformation().numPhysicalCPUs
; }
106 bool SystemStats::hasMMX() noexcept
{ return getCPUInformation().hasMMX
; }
107 bool SystemStats::has3DNow() noexcept
{ return getCPUInformation().has3DNow
; }
108 bool SystemStats::hasFMA3() noexcept
{ return getCPUInformation().hasFMA3
; }
109 bool SystemStats::hasFMA4() noexcept
{ return getCPUInformation().hasFMA4
; }
110 bool SystemStats::hasSSE() noexcept
{ return getCPUInformation().hasSSE
; }
111 bool SystemStats::hasSSE2() noexcept
{ return getCPUInformation().hasSSE2
; }
112 bool SystemStats::hasSSE3() noexcept
{ return getCPUInformation().hasSSE3
; }
113 bool SystemStats::hasSSSE3() noexcept
{ return getCPUInformation().hasSSSE3
; }
114 bool SystemStats::hasSSE41() noexcept
{ return getCPUInformation().hasSSE41
; }
115 bool SystemStats::hasSSE42() noexcept
{ return getCPUInformation().hasSSE42
; }
116 bool SystemStats::hasAVX() noexcept
{ return getCPUInformation().hasAVX
; }
117 bool SystemStats::hasAVX2() noexcept
{ return getCPUInformation().hasAVX2
; }
118 bool SystemStats::hasAVX512F() noexcept
{ return getCPUInformation().hasAVX512F
; }
119 bool SystemStats::hasAVX512BW() noexcept
{ return getCPUInformation().hasAVX512BW
; }
120 bool SystemStats::hasAVX512CD() noexcept
{ return getCPUInformation().hasAVX512CD
; }
121 bool SystemStats::hasAVX512DQ() noexcept
{ return getCPUInformation().hasAVX512DQ
; }
122 bool SystemStats::hasAVX512ER() noexcept
{ return getCPUInformation().hasAVX512ER
; }
123 bool SystemStats::hasAVX512IFMA() noexcept
{ return getCPUInformation().hasAVX512IFMA
; }
124 bool SystemStats::hasAVX512PF() noexcept
{ return getCPUInformation().hasAVX512PF
; }
125 bool SystemStats::hasAVX512VBMI() noexcept
{ return getCPUInformation().hasAVX512VBMI
; }
126 bool SystemStats::hasAVX512VL() noexcept
{ return getCPUInformation().hasAVX512VL
; }
127 bool SystemStats::hasAVX512VPOPCNTDQ() noexcept
{ return getCPUInformation().hasAVX512VPOPCNTDQ
; }
128 bool SystemStats::hasNeon() noexcept
{ return getCPUInformation().hasNeon
; }
131 //==============================================================================
132 String
SystemStats::getStackBacktrace()
136 #if JUCE_ANDROID || JUCE_MINGW || JUCE_WASM
137 jassertfalse
; // sorry, not implemented yet!
140 HANDLE process
= GetCurrentProcess();
141 SymInitialize (process
, nullptr, TRUE
);
144 int frames
= (int) CaptureStackBackTrace (0, numElementsInArray (stack
), stack
, nullptr);
146 HeapBlock
<SYMBOL_INFO
> symbol
;
147 symbol
.calloc (sizeof (SYMBOL_INFO
) + 256, 1);
148 symbol
->MaxNameLen
= 255;
149 symbol
->SizeOfStruct
= sizeof (SYMBOL_INFO
);
151 for (int i
= 0; i
< frames
; ++i
)
153 DWORD64 displacement
= 0;
155 if (SymFromAddr (process
, (DWORD64
) stack
[i
], &displacement
, symbol
))
159 IMAGEHLP_MODULE64 moduleInfo
;
160 zerostruct (moduleInfo
);
161 moduleInfo
.SizeOfStruct
= sizeof (moduleInfo
);
163 if (::SymGetModuleInfo64 (process
, symbol
->ModBase
, &moduleInfo
))
164 result
<< moduleInfo
.ModuleName
<< ": ";
166 result
<< symbol
->Name
<< " + 0x" << String::toHexString ((int64
) displacement
) << newLine
;
172 auto frames
= backtrace (stack
, numElementsInArray (stack
));
173 char** frameStrings
= backtrace_symbols (stack
, frames
);
175 for (int i
= 0; i
< frames
; ++i
)
176 result
<< frameStrings
[i
] << newLine
;
178 ::free (frameStrings
);
184 //==============================================================================
187 static SystemStats::CrashHandlerFunction globalCrashHandler
= nullptr;
190 static LONG WINAPI
handleCrash (LPEXCEPTION_POINTERS ep
)
192 globalCrashHandler (ep
);
193 return EXCEPTION_EXECUTE_HANDLER
;
196 static void handleCrash (int signum
)
198 globalCrashHandler ((void*) (pointer_sized_int
) signum
);
199 ::kill (getpid(), SIGKILL
);
202 int juce_siginterrupt (int sig
, int flag
);
205 void SystemStats::setApplicationCrashHandler (CrashHandlerFunction handler
)
207 jassert (handler
!= nullptr); // This must be a valid function.
208 globalCrashHandler
= handler
;
211 SetUnhandledExceptionFilter (handleCrash
);
213 const int signals
[] = { SIGFPE
, SIGILL
, SIGSEGV
, SIGBUS
, SIGABRT
, SIGSYS
};
215 for (int i
= 0; i
< numElementsInArray (signals
); ++i
)
217 ::signal (signals
[i
], handleCrash
);
218 juce_siginterrupt (signals
[i
], 1);
225 bool SystemStats::isRunningInAppExtensionSandbox() noexcept
227 #if JUCE_MAC || JUCE_IOS
228 static bool firstQuery
= true;
229 static bool isRunningInAppSandbox
= false;
235 File bundle
= File::getSpecialLocation (File::invokedExecutableFile
).getParentDirectory();
238 bundle
= bundle
.getParentDirectory().getParentDirectory();
241 if (bundle
.isDirectory())
242 isRunningInAppSandbox
= (bundle
.getFileExtension() == ".appex");
245 return isRunningInAppSandbox
;