Replace NULL with nullptr
[libcds.git] / src / dllmain.cpp
1 //$$CDS-header$$
2
3 #include <cds/details/defs.h>
4
5 #if CDS_OS_TYPE == CDS_OS_WIN32 || CDS_OS_TYPE == CDS_OS_WIN64 || CDS_OS_TYPE == CDS_OS_MINGW
6
7 #include <cds/os/thread.h>
8
9 // Visual leak detector (see http://vld.codeplex.com/)
10 #if defined(CDS_USE_VLD) && CDS_COMPILER == CDS_COMPILER_MSVC
11 #   ifdef _DEBUG
12 #       include <vld.h>
13 #   endif
14 #endif
15
16 static cds::OS::ThreadId    s_MainThreadId = 0;
17 static HINSTANCE            s_DllInstance = nullptr;
18
19 #if _WIN32_WINNT < 0x0601
20 // For Windows below Windows 7
21
22 #include <cds/os/topology.h>
23 #include <cds/algo/bitop.h>
24
25 static unsigned int     s_nProcessorCount = 1;
26 static unsigned int     s_nProcessorGroupCount = 1;
27
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;
32
33 static void discover_topology()
34 {
35     // From MSDN: http://msdn.microsoft.com/en-us/library/ms683194%28v=VS.85%29.aspx
36
37     typedef BOOL (WINAPI *LPFN_GLPI)( PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
38
39     LPFN_GLPI glpi;
40     bool bDone = false;
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;
48     DWORD byteOffset = 0;
49
50     s_nProcessorCount = 1;
51     s_nProcessorGroupCount = 1;
52
53     glpi = (LPFN_GLPI) GetProcAddress( GetModuleHandle("kernel32"), "GetLogicalProcessorInformation" );
54     if ( glpi == nullptr ) {
55         return;
56     }
57
58     while (!bDone)
59     {
60         DWORD rc = glpi(buffer, &returnLength);
61
62         if (FALSE == rc) {
63             if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
64                 if (buffer)
65                     free(buffer);
66
67                 buffer = reinterpret_cast<PSYSTEM_LOGICAL_PROCESSOR_INFORMATION>( ::malloc( returnLength ) );
68
69                 if ( buffer == nullptr ) {
70                     // allocation failed
71                     return;
72                 }
73             }
74             else {
75                 // System error
76                 // _tprintf(TEXT("\nError %d\n"), GetLastError());
77                 return;
78             }
79         }
80         else
81             bDone = true;
82     }
83
84     ptr = buffer;
85
86     while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength)
87     {
88         switch (ptr->Relationship)
89         {
90         case RelationNumaNode:
91             // Non-NUMA systems report a single record of this type.
92             numaNodeCount++;
93             break;
94
95         case RelationProcessorCore:
96             processorCoreCount++;
97
98             // A hyperthreaded core supplies more than one logical processor.
99             logicalProcessorCount += cds::bitop::SBC( ptr->ProcessorMask );
100             break;
101
102         case RelationCache:
103             break;
104
105         case RelationProcessorPackage:
106             // Logical processors share a physical package.
107             processorPackageCount++;
108             break;
109
110         default:
111             // Unsupported LOGICAL_PROCESSOR_RELATIONSHIP value
112             break;
113         }
114         byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
115         ptr++;
116     }
117
118     s_nProcessorCount = logicalProcessorCount;
119     s_nProcessorGroupCount = numaNodeCount;
120
121     // Build relationship processor -> cell
122     /*
123     s_arrProcessorCellRelationship = new unsigned int[s_nProcessorCount];
124     memset( s_arrProcessorCellRelationship, 0, s_nProcessorCount * sizeof(s_arrProcessorCellRelationship[0]) );
125     byteOffset = 0;
126     ptr = buffer;
127     while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength)
128     {
129         switch (ptr->Relationship)
130         {
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;
139                 }
140             }
141             break;
142         }
143         byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
144         ptr++;
145     }
146     */
147
148     free(buffer);
149
150     return;
151 }
152
153 namespace cds { namespace OS { namespace Win32 {
154     unsigned int    topology::processor_count()
155     {
156         return s_nProcessorCount;
157     }
158 }}} // namespace cds::OS::Win32
159
160 #endif  // #if _WIN32_WINNT < 0x0601
161
162 #if _WIN32_WINNT < 0x0600
163 #   include <cds/os/win/topology.h>
164     typedef DWORD (WINAPI * fnGetCurrentProcessorNumber)();
165     static fnGetCurrentProcessorNumber s_fnGetCurrentProcessorNumber;
166
167     static void prepare_current_processor_call()
168     {
169         s_fnGetCurrentProcessorNumber = (fnGetCurrentProcessorNumber) GetProcAddress( GetModuleHandle("kernel32"), "GetCurrentProcessorNumber" );
170         if ( s_fnGetCurrentProcessorNumber == nullptr )
171             s_fnGetCurrentProcessorNumber = (fnGetCurrentProcessorNumber) GetProcAddress( GetModuleHandle("ntdll"), "NtGetCurrentProcessorNumber" );
172     }
173
174     namespace cds { namespace OS { namespace Win32 {
175         unsigned int topology::current_processor()
176         {
177             if ( s_fnGetCurrentProcessorNumber != nullptr )
178                 return s_fnGetCurrentProcessorNumber();
179             return 0;
180         }
181     }}} // namespace cds::OS::Win32
182 #endif
183
184 extern "C" __declspec(dllexport)
185 BOOL WINAPI DllMain(
186                 HINSTANCE hinstDLL,
187                 DWORD fdwReason,
188                 LPVOID /*lpvReserved*/
189 )
190 {
191     switch ( fdwReason ) {
192         case DLL_PROCESS_ATTACH:
193             s_DllInstance = hinstDLL;
194             s_MainThreadId = cds::OS::getCurrentThreadId();
195 #if _WIN32_WINNT < 0x0601
196             discover_topology();
197 #endif
198 #   if _WIN32_WINNT < 0x0600
199             prepare_current_processor_call();
200 #endif
201             break;
202
203         case DLL_PROCESS_DETACH:
204 /*
205 #if _WIN32_WINNT < 0x0601
206             if ( s_arrProcessorCellRelationship != nullptr ) {
207                 delete [] s_arrProcessorCellRelationship;
208                 s_arrProcessorCellRelationship = nullptr;
209             }
210 #endif
211 */
212             break;
213     }
214     return TRUE;
215 }
216
217 #endif  // #if CDS_OS_TYPE == CDS_OS_WIN32
218
219