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

Commit 48ebab8

Browse files
authored
Add NUMA and thread affinity support for Unix (#10938)
* Add NUMA and thread affinity support for Unix This change adds new PAL functions for NUMA and thread affinity support for Unix and also enables related code in GC and VM for FEATURE_PAL. It doesn't reflect the limits imposed by CGROUPS on systems with CGROUPS enables yet.
1 parent 9b9989d commit 48ebab8

File tree

15 files changed

+977
-45
lines changed

15 files changed

+977
-45
lines changed

src/dlls/mscordac/mscordac_unixexports.src

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ PAL_GetPALDirectoryW
2121
PAL_GetResourceString
2222
PAL_get_stdout
2323
PAL_get_stderr
24+
PAL_GetCurrentThread
2425
PAL_GetSymbolModuleBase
2526
PAL_GetTransportPipeName
2627
PAL_InitializeDLL

src/gc/gc.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5151,7 +5151,6 @@ void gc_heap::destroy_thread_support ()
51515151
}
51525152
}
51535153

5154-
#if !defined(FEATURE_PAL)
51555154
void set_thread_group_affinity_for_heap(int heap_number, GCThreadAffinity* affinity)
51565155
{
51575156
affinity->Group = GCThreadAffinity::None;
@@ -5231,7 +5230,6 @@ void set_thread_affinity_mask_for_heap(int heap_number, GCThreadAffinity* affini
52315230
}
52325231
}
52335232
}
5234-
#endif // !FEATURE_PAL
52355233

52365234
bool gc_heap::create_gc_thread ()
52375235
{
@@ -5241,7 +5239,6 @@ bool gc_heap::create_gc_thread ()
52415239
affinity.Group = GCThreadAffinity::None;
52425240
affinity.Processor = GCThreadAffinity::None;
52435241

5244-
#if !defined(FEATURE_PAL)
52455242
if (!gc_thread_no_affinitize_p)
52465243
{
52475244
// We are about to set affinity for GC threads. It is a good place to set up NUMA and
@@ -5252,7 +5249,6 @@ bool gc_heap::create_gc_thread ()
52525249
else
52535250
set_thread_affinity_mask_for_heap(heap_number, &affinity);
52545251
}
5255-
#endif // !FEATURE_PAL
52565252

52575253
return GCToOSInterface::CreateThread(gc_thread_stub, this, &affinity);
52585254
}

src/inc/utilcode.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1380,7 +1380,7 @@ class NumaNodeInfo
13801380
static BOOL CanEnableGCNumaAware();
13811381
static void InitNumaNodeInfo();
13821382

1383-
#if !defined(FEATURE_REDHAWK)&& !defined(FEATURE_PAL)
1383+
#if !defined(FEATURE_REDHAWK)
13841384
private: // apis types
13851385

13861386
//GetNumaHighestNodeNumber()
@@ -1448,7 +1448,7 @@ class CPUGroupInfo
14481448
static DWORD CalculateCurrentProcessorNumber();
14491449
//static void PopulateCPUUsageArray(void * infoBuffer, ULONG infoSize);
14501450

1451-
#if !defined(FEATURE_REDHAWK) && !defined(FEATURE_PAL)
1451+
#if !defined(FEATURE_REDHAWK)
14521452
private:
14531453
//GetLogicalProcessorInforomationEx()
14541454
typedef BOOL

src/pal/inc/pal.h

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4825,6 +4825,161 @@ RegisterEventSourceW (
48254825
#define RegisterEventSource RegisterEventSourceA
48264826
#endif // !UNICODE
48274827

4828+
//
4829+
// NUMA related APIs
4830+
//
4831+
4832+
typedef enum _PROCESSOR_CACHE_TYPE {
4833+
CacheUnified,
4834+
CacheInstruction,
4835+
CacheData,
4836+
CacheTrace
4837+
} PROCESSOR_CACHE_TYPE;
4838+
4839+
typedef struct _PROCESSOR_NUMBER {
4840+
WORD Group;
4841+
BYTE Number;
4842+
BYTE Reserved;
4843+
} PROCESSOR_NUMBER, *PPROCESSOR_NUMBER;
4844+
4845+
typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP {
4846+
RelationProcessorCore,
4847+
RelationNumaNode,
4848+
RelationCache,
4849+
RelationProcessorPackage,
4850+
RelationGroup,
4851+
RelationAll = 0xffff
4852+
} LOGICAL_PROCESSOR_RELATIONSHIP;
4853+
4854+
typedef ULONG_PTR KAFFINITY;
4855+
4856+
#define ANYSIZE_ARRAY 1
4857+
4858+
typedef struct _GROUP_AFFINITY {
4859+
KAFFINITY Mask;
4860+
WORD Group;
4861+
WORD Reserved[3];
4862+
} GROUP_AFFINITY, *PGROUP_AFFINITY;
4863+
4864+
typedef struct _PROCESSOR_GROUP_INFO {
4865+
BYTE MaximumProcessorCount;
4866+
BYTE ActiveProcessorCount;
4867+
BYTE Reserved[38];
4868+
KAFFINITY ActiveProcessorMask;
4869+
} PROCESSOR_GROUP_INFO, *PPROCESSOR_GROUP_INFO;
4870+
4871+
typedef struct _PROCESSOR_RELATIONSHIP {
4872+
BYTE Flags;
4873+
BYTE EfficiencyClass;
4874+
BYTE Reserved[21];
4875+
WORD GroupCount;
4876+
GROUP_AFFINITY GroupMask[ANYSIZE_ARRAY];
4877+
} PROCESSOR_RELATIONSHIP, *PPROCESSOR_RELATIONSHIP;
4878+
4879+
typedef struct _GROUP_RELATIONSHIP {
4880+
WORD MaximumGroupCount;
4881+
WORD ActiveGroupCount;
4882+
BYTE Reserved[20];
4883+
PROCESSOR_GROUP_INFO GroupInfo[ANYSIZE_ARRAY];
4884+
} GROUP_RELATIONSHIP, *PGROUP_RELATIONSHIP;
4885+
4886+
typedef struct _NUMA_NODE_RELATIONSHIP {
4887+
DWORD NodeNumber;
4888+
BYTE Reserved[20];
4889+
GROUP_AFFINITY GroupMask;
4890+
} NUMA_NODE_RELATIONSHIP, *PNUMA_NODE_RELATIONSHIP;
4891+
4892+
typedef struct _CACHE_RELATIONSHIP {
4893+
BYTE Level;
4894+
BYTE Associativity;
4895+
WORD LineSize;
4896+
DWORD CacheSize;
4897+
PROCESSOR_CACHE_TYPE Type;
4898+
BYTE Reserved[20];
4899+
GROUP_AFFINITY GroupMask;
4900+
} CACHE_RELATIONSHIP, *PCACHE_RELATIONSHIP;
4901+
4902+
typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX {
4903+
LOGICAL_PROCESSOR_RELATIONSHIP Relationship;
4904+
DWORD Size;
4905+
union {
4906+
PROCESSOR_RELATIONSHIP Processor;
4907+
NUMA_NODE_RELATIONSHIP NumaNode;
4908+
CACHE_RELATIONSHIP Cache;
4909+
GROUP_RELATIONSHIP Group;
4910+
};
4911+
} SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX;
4912+
4913+
4914+
PALIMPORT
4915+
BOOL
4916+
PALAPI
4917+
GetNumaHighestNodeNumber(
4918+
OUT PULONG HighestNodeNumber
4919+
);
4920+
4921+
PALIMPORT
4922+
BOOL
4923+
PALAPI
4924+
GetNumaProcessorNodeEx(
4925+
IN PPROCESSOR_NUMBER Processor,
4926+
OUT PUSHORT NodeNumber
4927+
);
4928+
4929+
PALIMPORT
4930+
LPVOID
4931+
PALAPI
4932+
VirtualAllocExNuma(
4933+
IN HANDLE hProcess,
4934+
IN OPTIONAL LPVOID lpAddress,
4935+
IN SIZE_T dwSize,
4936+
IN DWORD flAllocationType,
4937+
IN DWORD flProtect,
4938+
IN DWORD nndPreferred
4939+
);
4940+
4941+
PALIMPORT
4942+
BOOL
4943+
PALAPI
4944+
GetLogicalProcessorInformationEx(
4945+
IN LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType,
4946+
OUT OPTIONAL PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer,
4947+
IN OUT PDWORD ReturnedLength
4948+
);
4949+
4950+
PALIMPORT
4951+
BOOL
4952+
PALAPI
4953+
SetThreadGroupAffinity(
4954+
IN HANDLE hThread,
4955+
IN const GROUP_AFFINITY *GroupAffinity,
4956+
OUT OPTIONAL PGROUP_AFFINITY PreviousGroupAffinity
4957+
);
4958+
4959+
PALIMPORT
4960+
BOOL
4961+
PALAPI
4962+
GetThreadGroupAffinity(
4963+
IN HANDLE hThread,
4964+
OUT PGROUP_AFFINITY GroupAffinity
4965+
);
4966+
4967+
PALIMPORT
4968+
VOID
4969+
PALAPI
4970+
GetCurrentProcessorNumberEx(
4971+
OUT PPROCESSOR_NUMBER ProcNumber
4972+
);
4973+
4974+
PALIMPORT
4975+
BOOL
4976+
PALAPI
4977+
GetProcessAffinityMask(
4978+
IN HANDLE hProcess,
4979+
OUT PDWORD_PTR lpProcessAffinityMask,
4980+
OUT PDWORD_PTR lpSystemAffinityMask
4981+
);
4982+
48284983
//
48294984
// The types of events that can be logged.
48304985
//

src/pal/src/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ set(SOURCES
181181
misc/sysinfo.cpp
182182
misc/time.cpp
183183
misc/utils.cpp
184+
numa/numa.cpp
184185
objmgr/palobjbase.cpp
185186
objmgr/shmobject.cpp
186187
objmgr/shmobjectmanager.cpp
@@ -372,6 +373,12 @@ if(CMAKE_SYSTEM_NAME STREQUAL NetBSD)
372373
)
373374
endif(CMAKE_SYSTEM_NAME STREQUAL NetBSD)
374375

376+
if(HAVE_NUMA_H)
377+
target_link_libraries(coreclrpal
378+
numa
379+
)
380+
endif(HAVE_NUMA_H)
381+
375382
add_subdirectory(examples)
376383

377384
if(FEATURE_EVENT_TRACE)

src/pal/src/config.h.in

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#cmakedefine01 HAVE_SYS_SYSCTL_H
2222
#cmakedefine01 HAVE_GNU_LIBNAMES_H
2323
#cmakedefine01 HAVE_PRCTL_H
24+
#cmakedefine01 HAVE_NUMA_H
25+
#cmakedefine01 HAVE_PTHREAD_NP_H
2426

2527
#cmakedefine01 HAVE_KQUEUE
2628
#cmakedefine01 HAVE_GETPWUID_R
@@ -33,6 +35,8 @@
3335
#cmakedefine01 HAVE_PTHREAD_GETATTR_NP
3436
#cmakedefine01 HAVE_PTHREAD_GETCPUCLOCKID
3537
#cmakedefine01 HAVE_PTHREAD_SIGQUEUE
38+
#cmakedefine01 HAVE_PTHREAD_GETAFFINITY_NP
39+
#cmakedefine01 HAVE_CPUSET_T
3640
#cmakedefine01 HAVE_SIGRETURN
3741
#cmakedefine01 HAVE__THREAD_SYS_SIGRETURN
3842
#cmakedefine01 HAVE_COPYSIGN
@@ -57,6 +61,7 @@
5761
#cmakedefine01 HAS_SYSV_SEMAPHORES
5862
#cmakedefine01 HAS_PTHREAD_MUTEXES
5963
#cmakedefine01 HAVE_TTRACE
64+
#cmakedefine01 HAVE_SCHED_GETAFFINITY
6065
#cmakedefine HAVE_UNW_GET_SAVE_LOC
6166
#cmakedefine HAVE_UNW_GET_ACCESSORS
6267
#cmakedefine01 HAVE_XSWDEV

src/pal/src/configure.cmake

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ check_include_files(libunwind.h HAVE_LIBUNWIND_H)
3535
check_include_files(runetype.h HAVE_RUNETYPE_H)
3636
check_include_files(semaphore.h HAVE_SEMAPHORE_H)
3737
check_include_files(sys/prctl.h HAVE_PRCTL_H)
38+
check_include_files(numa.h HAVE_NUMA_H)
39+
check_include_files(pthread_np.h HAVE_PTHREAD_NP_H)
3840

3941
if(NOT CMAKE_SYSTEM_NAME STREQUAL FreeBSD AND NOT CMAKE_SYSTEM_NAME STREQUAL NetBSD)
4042
set(CMAKE_REQUIRED_FLAGS "-ldl")
@@ -69,6 +71,7 @@ check_library_exists(${PTHREAD_LIBRARY} pthread_attr_get_np "" HAVE_PTHREAD_ATTR
6971
check_library_exists(${PTHREAD_LIBRARY} pthread_getattr_np "" HAVE_PTHREAD_GETATTR_NP)
7072
check_library_exists(${PTHREAD_LIBRARY} pthread_getcpuclockid "" HAVE_PTHREAD_GETCPUCLOCKID)
7173
check_library_exists(${PTHREAD_LIBRARY} pthread_sigqueue "" HAVE_PTHREAD_SIGQUEUE)
74+
check_library_exists(${PTHREAD_LIBRARY} pthread_getaffinity_np "" HAVE_PTHREAD_GETAFFINITY_NP)
7275

7376
check_function_exists(sigreturn HAVE_SIGRETURN)
7477
check_function_exists(_thread_sys_sigreturn HAVE__THREAD_SYS_SIGRETURN)
@@ -119,6 +122,14 @@ int main(int argc, char **argv) {
119122
}" HAVE_UNW_GET_ACCESSORS)
120123
set(CMAKE_REQUIRED_LIBRARIES)
121124

125+
check_cxx_source_compiles("
126+
#include <pthread_np.h>
127+
int main(int argc, char **argv) {
128+
cpuset_t cpuSet;
129+
130+
return 0;
131+
}" HAVE_CPUSET_T)
132+
122133
check_struct_has_member ("struct stat" st_atimespec "sys/types.h;sys/stat.h" HAVE_STAT_TIMESPEC)
123134
check_struct_has_member ("struct stat" st_atimensec "sys/types.h;sys/stat.h" HAVE_STAT_NSEC)
124135
check_struct_has_member ("struct tm" tm_gmtoff time.h HAVE_TM_GMTOFF)

src/pal/src/include/pal/dbgmsg.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ typedef enum
194194
#ifdef FEATURE_PAL_SXS
195195
DCI_SXS,
196196
#endif // FEATURE_PAL_SXS
197-
197+
DCI_NUMA,
198198
DCI_LAST
199199
} DBG_CHANNEL_ID;
200200

src/pal/src/include/pal/numa.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
/*++
6+
7+
8+
9+
Module Name:
10+
11+
include/pal/numa.h
12+
13+
Abstract:
14+
15+
Header file for the NUMA functions.
16+
17+
18+
19+
--*/
20+
21+
#ifndef _PAL_NUMA_H_
22+
#define _PAL_NUMA_H_
23+
24+
#ifdef __cplusplus
25+
extern "C"
26+
{
27+
#endif // __cplusplus
28+
29+
BOOL
30+
NUMASupportInitialize();
31+
32+
VOID
33+
NUMASupportCleanup();
34+
35+
#ifdef __cplusplus
36+
}
37+
#endif // __cplusplus
38+
39+
#endif /* _PAL_CRITSECT_H_ */

src/pal/src/init/pal.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ SET_DEFAULT_DEBUG_CHANNEL(PAL); // some headers have code with asserts, so do th
4242
#include "pal/debug.h"
4343
#include "pal/locale.h"
4444
#include "pal/init.h"
45+
#include "pal/numa.h"
4546
#include "pal/stackstring.hpp"
4647

4748
#if HAVE_MACH_EXCEPTIONS
@@ -523,6 +524,12 @@ Initialize(
523524
goto CLEANUP15;
524525
}
525526

527+
if (FALSE == NUMASupportInitialize())
528+
{
529+
ERROR("Unable to initialize NUMA support\n");
530+
goto CLEANUP15;
531+
}
532+
526533
TRACE("First-time PAL initialization complete.\n");
527534
init_count++;
528535

@@ -548,6 +555,7 @@ Initialize(
548555
}
549556
goto done;
550557

558+
NUMASupportCleanup();
551559
/* No cleanup required for CRTInitStdStreams */
552560
CLEANUP15:
553561
FILECleanupStdHandles();

0 commit comments

Comments
 (0)