24
24
#define YieldProcessor System_YieldProcessor
25
25
#endif
26
26
27
- #define NUMA_NODE_UNDEFINED UINT32_MAX
27
+ #define NUMA_NODE_UNDEFINED UINT16_MAX
28
+
29
+ bool ParseIndexOrRange (const char ** config_string, size_t * start_index, size_t * end_index);
28
30
29
31
// Critical section used by the GC
30
32
class CLRCriticalSection
@@ -55,17 +57,6 @@ struct VirtualReserveFlags
55
57
};
56
58
};
57
59
58
- // Affinity of a GC thread
59
- struct GCThreadAffinity
60
- {
61
- static const int None = -1 ;
62
-
63
- // Processor group index, None if no group is specified
64
- int Group;
65
- // Processor index, None if no affinity is specified
66
- int Processor;
67
- };
68
-
69
60
// An event is a synchronization object whose state can be set and reset
70
61
// indicating that an event has occured. It is used pervasively throughout
71
62
// the GC.
@@ -149,6 +140,86 @@ class GCEvent {
149
140
// GC thread function prototype
150
141
typedef void (*GCThreadFunction)(void * param);
151
142
143
+ #ifdef BIT64
144
+ // Right now we support maximum 1024 procs - meaning that we will create at most
145
+ // that many GC threads and GC heaps.
146
+ #define MAX_SUPPORTED_CPUS 1024
147
+ #else
148
+ #define MAX_SUPPORTED_CPUS 64
149
+ #endif // BIT64
150
+
151
+ // Add of processor indices used to store affinity.
152
+ class AffinitySet
153
+ {
154
+ static const size_t BitsPerBitsetEntry = 8 * sizeof (uintptr_t );
155
+
156
+ uintptr_t m_bitset[MAX_SUPPORTED_CPUS / BitsPerBitsetEntry];
157
+
158
+ static uintptr_t GetBitsetEntryMask (size_t cpuIndex)
159
+ {
160
+ return (uintptr_t )1 << (cpuIndex & (BitsPerBitsetEntry - 1 ));
161
+ }
162
+
163
+ static size_t GetBitsetEntryIndex (size_t cpuIndex)
164
+ {
165
+ return cpuIndex / BitsPerBitsetEntry;
166
+ }
167
+
168
+ public:
169
+
170
+ AffinitySet ()
171
+ {
172
+ memset (m_bitset, 0 , sizeof (m_bitset));
173
+ }
174
+
175
+ // Check if the set contains a processor
176
+ bool Contains (size_t cpuIndex) const
177
+ {
178
+ return (m_bitset[GetBitsetEntryIndex (cpuIndex)] & GetBitsetEntryMask (cpuIndex)) != 0 ;
179
+ }
180
+
181
+ // Add a processor to the set
182
+ void Add (size_t cpuIndex)
183
+ {
184
+ m_bitset[GetBitsetEntryIndex (cpuIndex)] |= GetBitsetEntryMask (cpuIndex);
185
+ }
186
+
187
+ // Remove a processor from the set
188
+ void Remove (size_t cpuIndex)
189
+ {
190
+ m_bitset[GetBitsetEntryIndex (cpuIndex)] &= ~GetBitsetEntryMask (cpuIndex);
191
+ }
192
+
193
+ // Check if the set is empty
194
+ bool IsEmpty () const
195
+ {
196
+ for (size_t i = 0 ; i < MAX_SUPPORTED_CPUS / BitsPerBitsetEntry; i++)
197
+ {
198
+ if (m_bitset[i] != 0 )
199
+ {
200
+ return false ;
201
+ }
202
+ }
203
+
204
+ return true ;
205
+ }
206
+
207
+ // Return number of processors in the affinity set
208
+ size_t Count () const
209
+ {
210
+ size_t count = 0 ;
211
+ for (size_t i = 0 ; i < MAX_SUPPORTED_CPUS; i++)
212
+ {
213
+ if (Contains (i))
214
+ {
215
+ count++;
216
+ }
217
+ }
218
+
219
+ return count;
220
+ }
221
+ };
222
+
152
223
// Interface that the GC uses to invoke OS specific functionality
153
224
class GCToOSInterface
154
225
{
@@ -202,7 +273,7 @@ class GCToOSInterface
202
273
// size - size of the virtual memory range
203
274
// Return:
204
275
// true if it has succeeded, false if it has failed
205
- static bool VirtualCommit (void *address, size_t size, uint32_t node = NUMA_NODE_UNDEFINED);
276
+ static bool VirtualCommit (void *address, size_t size, uint16_t node = NUMA_NODE_UNDEFINED);
206
277
207
278
// Decomit virtual memory range.
208
279
// Parameters:
@@ -269,11 +340,11 @@ class GCToOSInterface
269
340
270
341
// Set ideal processor for the current thread
271
342
// Parameters:
272
- // processorIndex - index of the processor in the group
273
- // affinity - ideal processor affinity for the thread
343
+ // srcProcNo - processor number the thread currently runs on
344
+ // dstProcNo - processor number the thread should be migrated to
274
345
// Return:
275
346
// true if it has succeeded, false if it has failed
276
- static bool SetCurrentThreadIdealAffinity (GCThreadAffinity* affinity );
347
+ static bool SetCurrentThreadIdealAffinity (uint16_t srcProcNo, uint16_t dstProcNo );
277
348
278
349
// Get numeric id of the current thread if possible on the
279
350
// current platform. It is indended for logging purposes only.
@@ -303,14 +374,13 @@ class GCToOSInterface
303
374
// The number of processors
304
375
static uint32_t GetCurrentProcessCpuCount ();
305
376
306
- // Sets the calling thread's affinity to only run on the processor specified
307
- // in the GCThreadAffinity structure.
377
+ // Sets the calling thread's affinity to only run on the processor specified.
308
378
// Parameters:
309
- // affinity - The requested affinity for the calling thread. At most one processor
310
- // can be provided.
379
+ // procNo - The requested affinity for the calling thread.
380
+ //
311
381
// Return:
312
382
// true if setting the affinity was successful, false otherwise.
313
- static bool SetThreadAffinity (GCThreadAffinity* affinity );
383
+ static bool SetThreadAffinity (uint16_t procNo );
314
384
315
385
// Boosts the calling thread's thread priority to a level higher than the default
316
386
// for new threads.
@@ -320,20 +390,13 @@ class GCToOSInterface
320
390
// true if the priority boost was successful, false otherwise.
321
391
static bool BoostThreadPriority ();
322
392
323
- // Get affinity mask of the current process
393
+ // Set the set of processors enabled for GC threads for the current process based on config specified affinity mask and set
324
394
// Parameters:
325
- // processMask - affinity mask for the specified process
326
- // systemMask - affinity mask for the system
395
+ // configAffinityMask - mask specified by the GCHeapAffinitizeMask config
396
+ // configAffinitySet - affinity set specified by the GCHeapAffinitizeRanges config
327
397
// Return:
328
- // true if it has succeeded, false if it has failed
329
- // Remarks:
330
- // A process affinity mask is a bit vector in which each bit represents the processors that
331
- // a process is allowed to run on. A system affinity mask is a bit vector in which each bit
332
- // represents the processors that are configured into a system.
333
- // A process affinity mask is a subset of the system affinity mask. A process is only allowed
334
- // to run on the processors configured into a system. Therefore, the process affinity mask cannot
335
- // specify a 1 bit for a processor when the system affinity mask specifies a 0 bit for that processor.
336
- static bool GetCurrentProcessAffinityMask (uintptr_t *processMask, uintptr_t *systemMask);
398
+ // set of enabled processors
399
+ static const AffinitySet* SetGCThreadsAffinitySet (uintptr_t configAffinityMask, const AffinitySet* configAffinitySet);
337
400
338
401
//
339
402
// Global memory info
@@ -408,13 +471,25 @@ class GCToOSInterface
408
471
static bool CanEnableGCNumaAware ();
409
472
410
473
// Gets the NUMA node for the processor
411
- static bool GetNumaProcessorNode (PPROCESSOR_NUMBER proc_no, uint16_t *node_no);
474
+ static bool GetNumaProcessorNode (uint16_t proc_no, uint16_t *node_no);
412
475
413
- // Are CPU groups enabled
414
- static bool CanEnableGCCPUGroups ();
476
+ // Get processor number and optionally its NUMA node number for the specified heap number
477
+ // Parameters:
478
+ // heap_number - heap number to get the result for
479
+ // proc_no - set to the selected processor number
480
+ // node_no - set to the NUMA node of the selected processor or to NUMA_NODE_UNDEFINED
481
+ // Return:
482
+ // true if it succeeded
483
+ static bool GetProcessorForHeap (uint16_t heap_number, uint16_t * proc_no, uint16_t * node_no);
415
484
416
- // Get the CPU group for the specified processor
417
- static void GetGroupForProcessor (uint16_t processor_number, uint16_t * group_number, uint16_t * group_processor_number);
485
+ // Parse the confing string describing affinitization ranges and update the passed in affinitySet accordingly
486
+ // Parameters:
487
+ // config_string - string describing the affinitization range, platform specific
488
+ // start_index - the range start index extracted from the config_string
489
+ // end_index - the range end index extracted from the config_string, equal to the start_index if only an index and not a range was passed in
490
+ // Return:
491
+ // true if the configString was successfully parsed, false if it was not correct
492
+ static bool ParseGCHeapAffinitizeRangesEntry (const char ** config_string, size_t * start_index, size_t * end_index);
418
493
419
494
};
420
495
0 commit comments