1/*-------------------------------------------------------------------------
4 * Basic NUMA portability routines
7 * Copyright (c) 2025, PostgreSQL Global Development Group
13 *-------------------------------------------------------------------------
23 * At this point we provide support only for Linux thanks to libnuma, but in
24 * future support for other platforms e.g. Win32 or FreeBSD might be possible
25 * too. For Win32 NUMA APIs see
26 * https://learn.microsoft.com/en-us/windows/win32/procthread/numa-support
34 * numa_move_pages() chunk size, has to be <= 16 to work around a kernel bug
35 * in do_pages_stat() (chunked by DO_PAGES_STAT_CHUNK_NR). By using the same
36 * chunk size, we make it work even on unfixed kernels.
38 * 64-bit system are not affected by the bug, and so use much larger chunks.
41#define NUMA_QUERY_CHUNK_SIZE 16
43#define NUMA_QUERY_CHUNK_SIZE 1024
46/* libnuma requires initialization as per numa(3) on Linux */
50 int r = numa_available();
56 * We use move_pages(2) syscall here - instead of get_mempolicy(2) - as the
57 * first one allows us to batch and query about many memory pages in one single
58 * giant system call that is way faster.
60 * We call numa_move_pages() for smaller chunks of the whole array. The first
61 * reason is to work around a kernel bug, but also to allow interrupting the
62 * query between the calls (for many pointers processing the whole array can
63 * take a lot of time).
68 unsigned long next = 0;
72 * Chunk pointers passed to numa_move_pages to NUMA_QUERY_CHUNK_SIZE
73 * items, to work around a kernel bug in do_pages_stat().
77 unsigned long count_chunk =
Min(count -
next,
78 NUMA_QUERY_CHUNK_SIZE);
83 * Bail out if any of the chunks errors out (ret<0). We ignore (ret>0)
84 * which is used to return number of nonmigrated pages, but we're not
85 * migrating any pages here.
87 ret = numa_move_pages(pid, count_chunk, &pages[
next], NULL, &status[
next], 0);
90 /* plain error, return as is */
97 /* should have consumed the input array exactly */
106 return numa_max_node();
115 /* We state that NUMA is not available */
Assert(PointerIsAligned(start, uint64))
#define CHECK_FOR_INTERRUPTS()
int pg_numa_query_pages(int pid, unsigned long count, void **pages, int *status)
int pg_numa_get_max_node(void)