Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 126aaf4

Browse files
authored
Merge pull request #23537 from janvorli/remove-gc-cpu-group-knowledge
Remove CPU groups notion from the gc.cpp
2 parents 6936877 + 6e629e9 commit 126aaf4

File tree

17 files changed

+955
-483
lines changed

17 files changed

+955
-483
lines changed

src/gc/env/gcenv.base.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ inline HRESULT HRESULT_FROM_WIN32(unsigned long x)
7171
#define E_FAIL 0x80004005
7272
#define E_OUTOFMEMORY 0x8007000E
7373
#define COR_E_EXECUTIONENGINE 0x80131506
74+
#define CLR_E_GC_BAD_AFFINITY_CONFIG 0x8013200A
75+
#define CLR_E_GC_BAD_AFFINITY_CONFIG_FORMAT 0x8013200B
7476

7577
#define NOERROR 0x0
7678
#define ERROR_TIMEOUT 1460

src/gc/env/gcenv.os.h

Lines changed: 113 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@
2424
#define YieldProcessor System_YieldProcessor
2525
#endif
2626

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);
2830

2931
// Critical section used by the GC
3032
class CLRCriticalSection
@@ -55,17 +57,6 @@ struct VirtualReserveFlags
5557
};
5658
};
5759

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-
6960
// An event is a synchronization object whose state can be set and reset
7061
// indicating that an event has occured. It is used pervasively throughout
7162
// the GC.
@@ -149,6 +140,86 @@ class GCEvent {
149140
// GC thread function prototype
150141
typedef void (*GCThreadFunction)(void* param);
151142

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+
152223
// Interface that the GC uses to invoke OS specific functionality
153224
class GCToOSInterface
154225
{
@@ -202,7 +273,7 @@ class GCToOSInterface
202273
// size - size of the virtual memory range
203274
// Return:
204275
// 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);
206277

207278
// Decomit virtual memory range.
208279
// Parameters:
@@ -269,11 +340,11 @@ class GCToOSInterface
269340

270341
// Set ideal processor for the current thread
271342
// 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
274345
// Return:
275346
// 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);
277348

278349
// Get numeric id of the current thread if possible on the
279350
// current platform. It is indended for logging purposes only.
@@ -303,14 +374,13 @@ class GCToOSInterface
303374
// The number of processors
304375
static uint32_t GetCurrentProcessCpuCount();
305376

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.
308378
// 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+
//
311381
// Return:
312382
// true if setting the affinity was successful, false otherwise.
313-
static bool SetThreadAffinity(GCThreadAffinity* affinity);
383+
static bool SetThreadAffinity(uint16_t procNo);
314384

315385
// Boosts the calling thread's thread priority to a level higher than the default
316386
// for new threads.
@@ -320,20 +390,13 @@ class GCToOSInterface
320390
// true if the priority boost was successful, false otherwise.
321391
static bool BoostThreadPriority();
322392

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
324394
// 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
327397
// 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);
337400

338401
//
339402
// Global memory info
@@ -408,13 +471,25 @@ class GCToOSInterface
408471
static bool CanEnableGCNumaAware();
409472

410473
// 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);
412475

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);
415484

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);
418493

419494
};
420495

0 commit comments

Comments
 (0)