Commit: 74e70fcf0afd46916f0172834405f2d605a5bf13
Parent: 29a0c74a146dbe0c0fc56df3efa7fb674f6cf7f6
Author: Randy Palamar
Date: Sun, 11 Jan 2026 19:47:31 -0700
os_linux: get actual page size and less wasteful processor count
The Linux kernel passes a 4th vector on the stack to our process
when it is loaded. Unlike the optional 3rd argument to main (envp)
we cannot access this ourselves. In that vector there exists an
entry AT_PAGESZ, which gives the actual system pagesize. This is
required no ARM64 which has configurable pagesize. On AMD64 we can
just hardcode 4K.
As for the number of processors the compiler is not able to figure
out that popcount should be used in the musl code. Since I want to
replace all the syscall wrappers eventually doing this part now is
fine and generates less wasteful code.
Diffstat:
3 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/intrinsics.c b/intrinsics.c
@@ -105,6 +105,8 @@
#define exp_f64(a) __builtin_exp(a)
#define sqrt_f64(a) __builtin_sqrt(a)
+
+ #define popcount_u64(a) __builtin_popcountll(a)
#endif
#if COMPILER_MSVC
diff --git a/main_linux.c b/main_linux.c
@@ -128,7 +128,7 @@ os_lookup_symbol(OSLibrary library, const char *symbol)
function void *
allocate_shared_memory(char *name, iz requested_capacity, u64 *capacity)
{
- u64 rounded_capacity = round_up_to(requested_capacity, os_linux_context.system_info.page_size);
+ u64 rounded_capacity = round_up_to(requested_capacity, ARCH_X64? KB(4) : os_linux_context.system_info.page_size);
void *result = 0;
i32 fd = shm_open(name, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
if (fd > 0 && ftruncate(fd, rounded_capacity) != -1) {
@@ -297,8 +297,8 @@ extern i32
main(void)
{
os_linux_context.system_info.timer_frequency = os_get_timer_frequency();
- os_linux_context.system_info.logical_processor_count = (u32)get_nprocs();
- os_linux_context.system_info.page_size = (u32)getpagesize();
+ os_linux_context.system_info.logical_processor_count = os_number_of_processors();
+ os_linux_context.system_info.page_size = ARCH_X64? KB(4) : getauxval(AT_PAGESZ);
os_linux_context.system_info.path_separator_byte = '/';
Arena program_memory = os_alloc_arena(MB(16) + KB(16));
diff --git a/os_linux.c b/os_linux.c
@@ -15,6 +15,7 @@
#include <linux/futex.h>
#include <poll.h>
#include <pthread.h>
+#include <sys/auxv.h>
#include <sys/inotify.h>
#include <sys/mman.h>
#include <sys/stat.h>
@@ -56,10 +57,22 @@ os_get_timer_counter(void)
return result;
}
+function u64
+os_number_of_processors(void)
+{
+ u64 set[128 / sizeof(u64)] = {0};
+ syscall(SYS_sched_getaffinity, 0, sizeof(set), set);
+
+ u64 result = 0;
+ for EachElement(set, it)
+ result += popcount_u64(set[it]);
+ return result > 0 ? result : 1;
+}
+
function OS_ALLOC_ARENA_FN(os_alloc_arena)
{
Arena result = {0};
- capacity = round_up_to(capacity, getpagesize());
+ capacity = round_up_to(capacity, ARCH_X64? KB(4) : getauxval(AT_PAGESZ));
void *memory = mmap(0, (uz)capacity, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
if (memory != MAP_FAILED) {
result.beg = memory;