#define E_OUTOFMEMORY 0x8007000E
#define COR_E_EXECUTIONENGINE 0x80131506
#define CLR_E_GC_BAD_AFFINITY_CONFIG 0x8013200A
+#define CLR_E_GC_BAD_AFFINITY_CONFIG_FORMAT 0x8013200B
#define NOERROR 0x0
#define ERROR_TIMEOUT 1460
// Check if the OS supports getting current processor number
static bool CanGetCurrentProcessorNumber();
- // Add ideal processor for the current thread
+ // Set ideal processor for the current thread
// Parameters:
// srcProcNo - processor number the thread currently runs on
// dstProcNo - processor number the thread should be migrated to
// Return:
// true if it has succeeded, false if it has failed
- static bool MigrateThread(uint16_t srcProcNo, uint16_t dstProcNo);
+ static bool SetCurrentThreadIdealAffinity(uint16_t srcProcNo, uint16_t dstProcNo);
// Get numeric id of the current thread if possible on the
// current platform. It is indended for logging purposes only.
uint16_t src_proc_no = heap_select::find_proc_no_from_heap_no(org_hp->heap_number);
uint16_t dst_proc_no = heap_select::find_proc_no_from_heap_no(max_hp->heap_number);
- if (!GCToOSInterface::MigrateThread(src_proc_no, dst_proc_no))
+ if (!GCToOSInterface::SetCurrentThreadIdealAffinity(src_proc_no, dst_proc_no))
{
dprintf (3, ("Failed to set the ideal processor for heap %d.",
org_hp->heap_number));
#ifdef MULTIPLE_HEAPS
AffinitySet config_affinity_set;
-
- // Get the affinity set configured by the user
- uintptr_t heap_affinity_mask = GCConfig::GetGCHeapAffinitizeMask();
- if (heap_affinity_mask != 0)
+ if (!ParseGCHeapAffinitySettings(&config_affinity_set))
{
- for (size_t i = 0; i < 8 * sizeof(uintptr_t); i++)
- {
- if (heap_affinity_mask & ((uintptr_t)1 << i))
- {
- config_affinity_set.Add(i);
- }
- }
- }
- else
- {
- GCConfigStringHolder cpu_index_ranges_holder(GCConfig::GetGCHeapAffinitizeRanges());
- const char* cpu_index_ranges = cpu_index_ranges_holder.Get();
-
- // The cpu index ranges is a comma separated list of indices or ranges of indices (e.g. 1-5).
- // Example 1,3,5,7-9,12
-
- if (cpu_index_ranges != NULL)
- {
- char* number_end;
-
- do
- {
- size_t start_index = strtoul(cpu_index_ranges, &number_end, 10);
-
- if (number_end == cpu_index_ranges)
- {
- // No number found, invalid format
- break;
- }
-
- size_t end_index = start_index;
-
- if (*number_end == '-')
- {
- char* range_end_start = number_end + 1;
- end_index = strtoul(range_end_start, &number_end, 10);
- if (number_end == range_end_start)
- {
- // No number found, invalid format
- break;
- }
- }
-
- if ((start_index < MAX_SUPPORTED_CPUS) && end_index < (MAX_SUPPORTED_CPUS))
- {
- for (size_t i = start_index; i <= end_index; i++)
- {
- config_affinity_set.Add(i);
- }
- }
-
- cpu_index_ranges = number_end + 1;
- }
- while (*number_end == ',');
- }
+ return CLR_E_GC_BAD_AFFINITY_CONFIG;
}
AffinitySet* process_affinity_set = GCToOSInterface::GetCurrentProcessAffinitySet();
if (process_affinity_set->IsEmpty())
{
- return CLR_E_GC_BAD_AFFINITY_CONFIG;
+ return CLR_E_GC_BAD_AFFINITY_CONFIG_FORMAT;
}
nhp_from_config = static_cast<uint32_t>(GCConfig::GetHeapCount());
#undef BOOL_CONFIG
#undef INT_CONFIG
}
+
+bool ParseGCHeapAffinitySettings(AffinitySet* config_affinity_set)
+{
+ bool success = true;
+
+ // Get the affinity set configured by the user
+ uintptr_t heap_affinity_mask = GCConfig::GetGCHeapAffinitizeMask();
+ if (heap_affinity_mask != 0)
+ {
+ for (size_t i = 0; i < 8 * sizeof(uintptr_t); i++)
+ {
+ if (heap_affinity_mask & ((uintptr_t)1 << i))
+ {
+ config_affinity_set->Add(i);
+ }
+ }
+ }
+ else
+ {
+ GCConfigStringHolder cpu_index_ranges_holder(GCConfig::GetGCHeapAffinitizeRanges());
+ const char* cpu_index_ranges = cpu_index_ranges_holder.Get();
+
+ // The cpu index ranges is a comma separated list of indices or ranges of indices (e.g. 1-5).
+ // Example 1,3,5,7-9,12
+
+ if (cpu_index_ranges != NULL)
+ {
+ char* number_end;
+
+ do
+ {
+ size_t start_index = strtoul(cpu_index_ranges, &number_end, 10);
+
+ if (number_end == cpu_index_ranges)
+ {
+ // No number found, invalid format
+ break;
+ }
+
+ size_t end_index = start_index;
+
+ if (*number_end == '-')
+ {
+ char* range_end_start = number_end + 1;
+ end_index = strtoul(range_end_start, &number_end, 10);
+ if (number_end == range_end_start)
+ {
+ // No number found, invalid format
+ break;
+ }
+ }
+
+ if ((start_index < MAX_SUPPORTED_CPUS) && end_index < (MAX_SUPPORTED_CPUS))
+ {
+ for (size_t i = start_index; i <= end_index; i++)
+ {
+ config_affinity_set->Add(i);
+ }
+ }
+
+ cpu_index_ranges = number_end + 1;
+ }
+ while (*number_end == ',');
+
+ success = (*number_end == '\0');
+ }
+ }
+
+ return success;
+}
INT_CONFIG(GCHeapAffinitizeMask, "GCHeapAffinitizeMask", 0, \
"Specifies processor mask for Server GC threads") \
STRING_CONFIG(GCHeapAffinitizeRanges, "GCHeapAffinitizeRanges", \
- "Specifies list of processors for Server GC threads") \
+ "Specifies list of processors for Server GC threads. The format is a comma separated " \
+ "list of processor numbers or ranges of processor numbers. Example: 1,3,5,7-9,12") \
INT_CONFIG(GCHighMemPercent, "GCHighMemPercent", 0, \
"The percent for GC to consider as high memory") \
INT_CONFIG(GCProvModeStress, "GCProvModeStress", 0, \
};
+bool ParseGCHeapAffinitySettings(AffinitySet* config_affinity_set);
+
#endif // __GCCONFIG_H__
// dstProcNo - processor number the thread should be migrated to
// Return:
// true if it has succeeded, false if it has failed
-bool GCToOSInterface::MigrateThread(uint16_t srcProcNo, uint16_t dstProcNo)
+bool GCToOSInterface::SetCurrentThreadIdealAffinity(uint16_t srcProcNo, uint16_t dstProcNo)
{
return GCToOSInterface::SetThreadAffinity(dstProcNo);
}
// dstProcNo - processor number the thread should be migrated to
// Return:
// true if it has succeeded, false if it has failed
-bool GCToOSInterface::MigrateThread(uint16_t srcProcNo, uint16_t dstProcNo)
+bool GCToOSInterface::SetCurrentThreadIdealAffinity(uint16_t srcProcNo, uint16_t dstProcNo)
{
LIMITED_METHOD_CONTRACT;
RETAIL_CONFIG_STRING_INFO(EXTERNAL_GCName, W("GCName"), "")
RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_GCHeapHardLimit, W("GCHeapHardLimit"), "Specifies the maximum commit size for the GC heap")
RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_GCHeapHardLimitPercent, W("GCHeapHardLimitPercent"), "Specifies the GC heap usage as a percentage of the total memory")
+RETAIL_CONFIG_STRING_INFO(EXTERNAL_GCHeapAffinitizeRanges, W("GCHeapAffinitizeRanges"), "Specifies list of processors for Server GC threads. The format is a comma separated list of processor numbers or ranges of processor numbers. Example: 1,3,5,7-9,12")
///
/// IBC
<HRESULT NumericValue="0x8013200A">
<SymbolicName>CLR_E_GC_BAD_AFFINITY_CONFIG</SymbolicName>
- <Message>"GC affinity mask or set doesn't contain any CPUs the current process is affinitized to."</Message>
+ <Message>"GCHeapAffinitizeMask or GCHeapAffinitizeRanges didn't specify any CPUs the current process is affinitized to."</Message>
<Comment>During a GC initialization, the affinity mask specified via GCHeapAffinitizeMask or GCHeapAffinitizeRanges didn't contain any CPUs the current process is affinitized to.</Comment>
</HRESULT>
+<HRESULT NumericValue="0x8013200B">
+ <SymbolicName>CLR_E_GC_BAD_AFFINITY_CONFIG_FORMAT</SymbolicName>
+ <Message>"GCHeapAffinitizeRanges configuration string has invalid format."</Message>
+ <Comment>During a GC initialization, the GCHeapAffinitizeRanges config couldn't be parsed due to its invalid format.</Comment>
+</HRESULT>
+
<HRESULT NumericValue="E_ACCESSDENIED">
<SymbolicName>COR_E_UNAUTHORIZEDACCESS</SymbolicName>
<Comment> 0x80070005 // Access is denied.</Comment>
MSG_FOR_URT_HR(CLR_E_BIND_NI_SECURITY_FAILURE) "Native image was generated in a different trust level than present at runtime"
MSG_FOR_URT_HR(CLR_E_BIND_NI_DEP_IDENTITY_MISMATCH) "Native image identity mismatch with respect to its dependencies"
MSG_FOR_URT_HR(CLR_E_GC_OOM) "Failfast due to an OOM during a GC"
- MSG_FOR_URT_HR(CLR_E_GC_BAD_AFFINITY_CONFIG) "GC affinity mask or set doesn't contain any CPUs the current process is affinitized to."
+ MSG_FOR_URT_HR(CLR_E_GC_BAD_AFFINITY_CONFIG) "GCHeapAffinitizeMask or GCHeapAffinitizeRanges didn't specify any CPUs the current process is affinitized to."
+ MSG_FOR_URT_HR(CLR_E_GC_BAD_AFFINITY_CONFIG_FORMAT) "GCHeapAffinitizeRanges configuration string has invalid format."
MSG_FOR_URT_HR(COR_E_BADIMAGEFORMAT) "The format of a DLL or executable being loaded is invalid."
END
#define CLR_E_BIND_NI_DEP_IDENTITY_MISMATCH EMAKEHR(0x2008)
#define CLR_E_GC_OOM EMAKEHR(0x2009)
#define CLR_E_GC_BAD_AFFINITY_CONFIG EMAKEHR(0x200a)
+#define CLR_E_GC_BAD_AFFINITY_CONFIG_FORMAT EMAKEHR(0x200b)
#define COR_E_UNAUTHORIZEDACCESS E_ACCESSDENIED
#define COR_E_ARGUMENT E_INVALIDARG
#define COR_E_INVALIDCAST E_NOINTERFACE
// dstProcNo - processor number the thread should be migrated to
// Return:
// true if it has succeeded, false if it has failed
-bool GCToOSInterface::MigrateThread(uint16_t srcProcNo, uint16_t dstProcNo)
+bool GCToOSInterface::SetCurrentThreadIdealAffinity(uint16_t srcProcNo, uint16_t dstProcNo)
{
LIMITED_METHOD_CONTRACT;