2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
6 Source code repo: http://github.com/khizmax/libcds/
7 Download: http://sourceforge.net/projects/libcds/files/
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice, this
13 list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice,
16 this list of conditions and the following disclaimer in the documentation
17 and/or other materials provided with the distribution.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <cds/details/defs.h>
33 #if CDS_OS_TYPE == CDS_OS_WIN32 || CDS_OS_TYPE == CDS_OS_WIN64 || CDS_OS_TYPE == CDS_OS_MINGW
35 #include <cds/os/thread.h>
37 // Visual leak detector (see http://vld.codeplex.com/)
38 #if defined(CDS_USE_VLD) && CDS_COMPILER == CDS_COMPILER_MSVC
44 static cds::OS::ThreadId s_MainThreadId = 0;
45 static HINSTANCE s_DllInstance = nullptr;
47 #if _WIN32_WINNT < 0x0601
48 // For Windows below Windows 7
50 #include <cds/os/topology.h>
51 #include <cds/algo/bitop.h>
53 static unsigned int s_nProcessorCount = 1;
54 static unsigned int s_nProcessorGroupCount = 1;
56 // Array of processor - cell relationship
57 // Array size is s_nProcessorCount
58 // s_arrProcessorCellRelationship[i] is the cell (the processor group) number for i-th processor
59 // static unsigned int * s_arrProcessorCellRelationship = nullptr;
61 static void discover_topology()
63 // From MSDN: http://msdn.microsoft.com/en-us/library/ms683194%28v=VS.85%29.aspx
65 typedef BOOL (WINAPI *LPFN_GLPI)( PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
69 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = nullptr;
70 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = nullptr;
71 DWORD returnLength = 0;
72 DWORD logicalProcessorCount = 0;
73 DWORD numaNodeCount = 0;
74 DWORD processorCoreCount = 0;
75 DWORD processorPackageCount = 0;
78 s_nProcessorCount = 1;
79 s_nProcessorGroupCount = 1;
81 glpi = (LPFN_GLPI) GetProcAddress( GetModuleHandle("kernel32"), "GetLogicalProcessorInformation" );
82 if ( glpi == nullptr ) {
88 DWORD rc = glpi(buffer, &returnLength);
91 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
95 buffer = reinterpret_cast<PSYSTEM_LOGICAL_PROCESSOR_INFORMATION>( ::malloc( returnLength ) );
97 if ( buffer == nullptr ) {
104 // _tprintf(TEXT("\nError %d\n"), GetLastError());
114 while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength)
116 switch (ptr->Relationship)
118 case RelationNumaNode:
119 // Non-NUMA systems report a single record of this type.
123 case RelationProcessorCore:
124 processorCoreCount++;
126 // A hyperthreaded core supplies more than one logical processor.
127 logicalProcessorCount += cds::bitop::SBC( ptr->ProcessorMask );
133 case RelationProcessorPackage:
134 // Logical processors share a physical package.
135 processorPackageCount++;
139 // Unsupported LOGICAL_PROCESSOR_RELATIONSHIP value
142 byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
146 s_nProcessorCount = logicalProcessorCount;
147 s_nProcessorGroupCount = numaNodeCount;
149 // Build relationship processor -> cell
151 s_arrProcessorCellRelationship = new unsigned int[s_nProcessorCount];
152 memset( s_arrProcessorCellRelationship, 0, s_nProcessorCount * sizeof(s_arrProcessorCellRelationship[0]) );
155 while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength)
157 switch (ptr->Relationship)
159 case RelationNumaNode:
160 // Non-NUMA systems report a single record of this type.
161 for ( unsigned int i = 0; i < sizeof(ptr->ProcessorMask) * 8; ++i ) {
162 if ( ptr->ProcessorMask & (1 << i) ) {
163 assert( i < s_nProcessorCount );
164 assert( ptr->NumaNode.NodeNumber < s_nProcessorGroupCount );
165 if ( i < s_nProcessorCount )
166 s_arrProcessorCellRelationship[i] = ptr->NumaNode.NodeNumber;
171 byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
181 namespace cds { namespace OS { CDS_CXX11_INLINE_NAMESPACE namespace Win32 {
182 unsigned int topology::processor_count()
184 return s_nProcessorCount;
186 }}} // namespace cds::OS::Win32
188 #endif // #if _WIN32_WINNT < 0x0601
190 #if _WIN32_WINNT < 0x0600
191 # include <cds/os/win/topology.h>
192 typedef DWORD (WINAPI * fnGetCurrentProcessorNumber)();
193 static fnGetCurrentProcessorNumber s_fnGetCurrentProcessorNumber;
195 static void prepare_current_processor_call()
197 s_fnGetCurrentProcessorNumber = (fnGetCurrentProcessorNumber) GetProcAddress( GetModuleHandle("kernel32"), "GetCurrentProcessorNumber" );
198 if ( s_fnGetCurrentProcessorNumber == nullptr )
199 s_fnGetCurrentProcessorNumber = (fnGetCurrentProcessorNumber) GetProcAddress( GetModuleHandle("ntdll"), "NtGetCurrentProcessorNumber" );
202 namespace cds { namespace OS { CDS_CXX11_INLINE_NAMESPACE namespace Win32 {
203 unsigned int topology::current_processor()
205 if ( s_fnGetCurrentProcessorNumber != nullptr )
206 return s_fnGetCurrentProcessorNumber();
209 }}} // namespace cds::OS::Win32
212 extern "C" __declspec(dllexport)
216 LPVOID /*lpvReserved*/
219 switch ( fdwReason ) {
220 case DLL_PROCESS_ATTACH:
221 s_DllInstance = hinstDLL;
222 s_MainThreadId = cds::OS::get_current_thread_id();
223 #if _WIN32_WINNT < 0x0601
226 # if _WIN32_WINNT < 0x0600
227 prepare_current_processor_call();
231 case DLL_PROCESS_DETACH:
233 #if _WIN32_WINNT < 0x0601
234 if ( s_arrProcessorCellRelationship != nullptr ) {
235 delete [] s_arrProcessorCellRelationship;
236 s_arrProcessorCellRelationship = nullptr;
245 #endif // #if CDS_OS_TYPE == CDS_OS_WIN32