@@ -29,6 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2929*/
3030
3131#ifdef _MSC_VER
32+ #include < intrin.h>
33+
3234 #include " Windows.h"
3335
3436 #include < powerbase.h>
@@ -44,10 +46,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4446 #include < pthread.h>
4547#endif
4648
49+ #include " Thread/Core.h"
4750#include " Thread/ThreadCommon.h"
51+ #include " SysAllocator.h"
4852#include " Bit.h"
4953#include " DynamicArray.h"
5054#include " Timer.h"
55+ #include " Parser.h"
5156
5257#include " CPUInfo.h"
5358
@@ -82,6 +87,9 @@ void OSThread::SetAffinity( const uint32 newCore ) {
8287
8388 if ( !ret ) {
8489 Log::Warn ( " SetThreadGroupAffinity error: %i" , GetLastError () );
90+ baseMaxFrequency = 1.0 ;
91+
92+ return ;
8593 }
8694
8795 // PROCESSOR_POWER_INFORMATION, which is missing from windows headers
@@ -127,7 +135,7 @@ void OSThread::SetAffinity( const uint32 newCore ) {
127135 int ret = pthread_setaffinity_np ( thread, sizeof ( cpu ), &cpu );
128136
129137 if ( ret != 0 ) {
130- Log::Warn ( " sched_setaffinity error: %s" , strerror ( errno ) );
138+ Log::Warn ( " pthread_setaffinity_np error: %s" , strerror ( errno ) );
131139 }
132140 #endif
133141}
@@ -185,4 +193,173 @@ double OSThread::GetMaxFrequencyScale() {
185193 #else // Can't set thread affinity on apple, so no point in scaling by max frequency
186194 return 1.0 ;
187195 #endif
196+ }
197+
198+ struct File {
199+ FILE * file;
200+ uint32_t size;
201+
202+ File ( const std::string& path, const char * mode ) {
203+ file = fopen ( path.c_str (), mode );
204+
205+ if ( !file ) {
206+ printf ( " Failed to open file: %s, mode: %s\n " , path.c_str (), mode );
207+ printf ( strerror ( errno ) );
208+ exit ( 1 );
209+ }
210+
211+ fseek ( file, 0 , SEEK_END );
212+ size = ftell ( file );
213+
214+ fseek ( file, 0 , 0 );
215+ }
216+
217+ File ( const std::string& path, const std::string& path2, const char * mode ) {
218+ file = fopen ( path.c_str (), mode );
219+
220+ if ( !file ) {
221+ file = fopen ( path2.c_str (), mode );
222+
223+ if ( !file ) {
224+ Log::Warn ( " Failed to open file: %s, mode: %s\n " , path.c_str (), mode );
225+ Log::Warn ( strerror ( errno ) );
226+ }
227+ }
228+
229+ fseek ( file, 0 , SEEK_END );
230+ size = ftell ( file );
231+
232+ fseek ( file, 0 , 0 );
233+ }
234+
235+ ~File () {
236+ fclose ( file );
237+ }
238+
239+ std::string ReadAll () {
240+ std::string data;
241+ data.resize ( size );
242+ size = fread ( data.data (), sizeof ( char ), size, file );
243+
244+ data.resize ( size );
245+ data.shrink_to_fit ();
246+
247+ return data;
248+ }
249+ };
250+
251+ Core OSThread::GetCoreInfo () {
252+ #ifdef _MSC_VER
253+ DWORD size = 0 ;
254+
255+ GetLogicalProcessorInformationEx ( RelationProcessorCore, nullptr , &size );
256+ SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX * buf = ( SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX * ) sysAllocator.Alloc ( size, 64 );
257+ bool ret = GetLogicalProcessorInformationEx ( RelationProcessorCore, buf, &size );
258+
259+ if ( !ret ) {
260+ Log::Warn ( " GetLogicalProcessorInformationEx error: %i" , GetLastError () );
261+
262+ return {
263+ .type = CORE_UNKNOWN ,
264+ .hyperthreading = false ,
265+ .maxFrequencyScale = GetMaxFrequencyScale ()
266+ };
267+ }
268+
269+ SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX * coreInfo = ( SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX * ) ( ( ( byte* ) buf ) + core * buf->Size );
270+
271+ return {
272+ .type = coreInfo->Processor .EfficiencyClass ? CORE_PERFORMANCE : CORE_EFFICIENCY ,
273+ .hyperthreading = coreInfo->Processor .Flags == LTP_PC_SMT ,
274+ .maxFrequencyScale = GetMaxFrequencyScale ()
275+ };
276+ #elifndef __APPLE__
277+ return {
278+ .type = CORE_UNKNOWN ,
279+ .hyperthreading = false ,
280+ .maxFrequencyScale = GetMaxFrequencyScale ()
281+ };
282+ #else
283+ return {
284+ .type = CORE_PERFORMANCE ,
285+ .hyperthreading = false ,
286+ .maxFrequencyScale = GetMaxFrequencyScale ()
287+ };
288+ #endif
289+ }
290+
291+ #ifdef __linux__
292+ bool IsHyperthreadingEnabled () {
293+ File cpuInfoFile { " /proc/cpuinfo" , " r" };
294+ std::string cpuInfo = cpuInfoFile.ReadAll ();
295+
296+ StringView v { cpuInfo.c_str (), cpuInfo.size () };
297+
298+ int physicalCores = 0 ;
299+ int logicalCores = 0 ;
300+
301+ do {
302+ StringView o = Parse ( v );
303+
304+ if ( o == " cpu" ) {
305+ if ( Parse ( v ) == " cores" ) {
306+ Parse ( v ); // :
307+ Str::ParseInt ( physicalCores, std::string ( o.memory , o.size ) );
308+ }
309+ } else if ( o == " siblings" ) {
310+ Parse ( v ); // :
311+ Str::ParseInt ( logicalCores, std::string ( o.memory , o.size ) );
312+ }
313+ } while ( v.size && !( physicalCores && logicalCores ) );
314+
315+ return physicalCores == logicalCores;
316+ }
317+ #elif __APPLE__
318+ bool IsHyperthreadingEnabled () {
319+ return false ;
320+ }
321+ #endif
322+
323+ std::string GetCPUModel () {
324+ #ifdef _MSC_VER
325+ int info[4 ] {};
326+ std::string model;
327+
328+ static constexpr uint32 infoSize = 4 * sizeof ( int );
329+
330+ model.resize ( 65 );
331+
332+ __cpuid ( info, 0x80000002 );
333+ memcpy ( model.data (), info, infoSize );
334+
335+ __cpuid ( info, 0x80000003 );
336+ memcpy ( model.data () + infoSize, info, infoSize );
337+
338+ __cpuid ( info, 0x80000004 );
339+ memcpy ( model.data () + 2 * infoSize, info, infoSize );
340+
341+ model.resize ( strlen ( model.c_str () ) ); // Avoid the ugly NUL characters in logger
342+
343+ return model;
344+ #elifdef __linux__
345+ File cpuInfoFile { " /proc/cpuinfo" , " r" };
346+ std::string cpuInfo = cpuInfoFile.ReadAll ();
347+
348+ StringView v { cpuInfo.c_str (), cpuInfo.size () };
349+
350+ do {
351+ StringView o = Parse ( v );
352+
353+ if ( o == " model" ) {
354+ if ( Parse ( v ) == " name" ) {
355+ Parse ( v ); // :
356+ return Parse ( v );
357+ }
358+ }
359+ } while ( v.size );
360+
361+ return " Unknown" ;
362+ #else
363+ return " Unknown" ;
364+ #endif
188365}
0 commit comments