3 #include <cds/details/defs.h>
5 #if CDS_OS_TYPE == CDS_OS_WIN32 || CDS_OS_TYPE == CDS_OS_WIN64 || CDS_OS_TYPE == CDS_OS_MINGW
7 #include <cds/os/thread.h>
9 // Visual leak detector (see http://vld.codeplex.com/)
10 #if defined(CDS_USE_VLD) && CDS_COMPILER == CDS_COMPILER_MSVC
16 static cds::OS::ThreadId s_MainThreadId = 0;
17 static HINSTANCE s_DllInstance = nullptr;
19 #if _WIN32_WINNT < 0x0601
20 // For Windows below Windows 7
22 #include <cds/os/topology.h>
23 #include <cds/algo/bitop.h>
25 static unsigned int s_nProcessorCount = 1;
26 static unsigned int s_nProcessorGroupCount = 1;
28 // Array of processor - cell relationship
29 // Array size is s_nProcessorCount
30 // s_arrProcessorCellRelationship[i] is the cell (the processor group) number for i-th processor
31 // static unsigned int * s_arrProcessorCellRelationship = nullptr;
33 static void discover_topology()
35 // From MSDN: http://msdn.microsoft.com/en-us/library/ms683194%28v=VS.85%29.aspx
37 typedef BOOL (WINAPI *LPFN_GLPI)( PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
41 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = nullptr;
42 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = nullptr;
43 DWORD returnLength = 0;
44 DWORD logicalProcessorCount = 0;
45 DWORD numaNodeCount = 0;
46 DWORD processorCoreCount = 0;
47 DWORD processorPackageCount = 0;
50 s_nProcessorCount = 1;
51 s_nProcessorGroupCount = 1;
53 glpi = (LPFN_GLPI) GetProcAddress( GetModuleHandle("kernel32"), "GetLogicalProcessorInformation" );
54 if ( glpi == nullptr ) {
60 DWORD rc = glpi(buffer, &returnLength);
63 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
67 buffer = reinterpret_cast<PSYSTEM_LOGICAL_PROCESSOR_INFORMATION>( ::malloc( returnLength ) );
69 if ( buffer == nullptr ) {
76 // _tprintf(TEXT("\nError %d\n"), GetLastError());
86 while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength)
88 switch (ptr->Relationship)
90 case RelationNumaNode:
91 // Non-NUMA systems report a single record of this type.
95 case RelationProcessorCore:
98 // A hyperthreaded core supplies more than one logical processor.
99 logicalProcessorCount += cds::bitop::SBC( ptr->ProcessorMask );
105 case RelationProcessorPackage:
106 // Logical processors share a physical package.
107 processorPackageCount++;
111 // Unsupported LOGICAL_PROCESSOR_RELATIONSHIP value
114 byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
118 s_nProcessorCount = logicalProcessorCount;
119 s_nProcessorGroupCount = numaNodeCount;
121 // Build relationship processor -> cell
123 s_arrProcessorCellRelationship = new unsigned int[s_nProcessorCount];
124 memset( s_arrProcessorCellRelationship, 0, s_nProcessorCount * sizeof(s_arrProcessorCellRelationship[0]) );
127 while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength)
129 switch (ptr->Relationship)
131 case RelationNumaNode:
132 // Non-NUMA systems report a single record of this type.
133 for ( unsigned int i = 0; i < sizeof(ptr->ProcessorMask) * 8; ++i ) {
134 if ( ptr->ProcessorMask & (1 << i) ) {
135 assert( i < s_nProcessorCount );
136 assert( ptr->NumaNode.NodeNumber < s_nProcessorGroupCount );
137 if ( i < s_nProcessorCount )
138 s_arrProcessorCellRelationship[i] = ptr->NumaNode.NodeNumber;
143 byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
153 namespace cds { namespace OS { namespace Win32 {
154 unsigned int topology::processor_count()
156 return s_nProcessorCount;
158 }}} // namespace cds::OS::Win32
160 #endif // #if _WIN32_WINNT < 0x0601
162 #if _WIN32_WINNT < 0x0600
163 # include <cds/os/win/topology.h>
164 typedef DWORD (WINAPI * fnGetCurrentProcessorNumber)();
165 static fnGetCurrentProcessorNumber s_fnGetCurrentProcessorNumber;
167 static void prepare_current_processor_call()
169 s_fnGetCurrentProcessorNumber = (fnGetCurrentProcessorNumber) GetProcAddress( GetModuleHandle("kernel32"), "GetCurrentProcessorNumber" );
170 if ( s_fnGetCurrentProcessorNumber == nullptr )
171 s_fnGetCurrentProcessorNumber = (fnGetCurrentProcessorNumber) GetProcAddress( GetModuleHandle("ntdll"), "NtGetCurrentProcessorNumber" );
174 namespace cds { namespace OS { namespace Win32 {
175 unsigned int topology::current_processor()
177 if ( s_fnGetCurrentProcessorNumber != nullptr )
178 return s_fnGetCurrentProcessorNumber();
181 }}} // namespace cds::OS::Win32
184 extern "C" __declspec(dllexport)
188 LPVOID /*lpvReserved*/
191 switch ( fdwReason ) {
192 case DLL_PROCESS_ATTACH:
193 s_DllInstance = hinstDLL;
194 s_MainThreadId = cds::OS::get_current_thread_id();
195 #if _WIN32_WINNT < 0x0601
198 # if _WIN32_WINNT < 0x0600
199 prepare_current_processor_call();
203 case DLL_PROCESS_DETACH:
205 #if _WIN32_WINNT < 0x0601
206 if ( s_arrProcessorCellRelationship != nullptr ) {
207 delete [] s_arrProcessorCellRelationship;
208 s_arrProcessorCellRelationship = nullptr;
217 #endif // #if CDS_OS_TYPE == CDS_OS_WIN32