diff --git a/include/SDL3/SDL_cpuinfo.h b/include/SDL3/SDL_cpuinfo.h index 1745bd9349..87432ed909 100644 --- a/include/SDL3/SDL_cpuinfo.h +++ b/include/SDL3/SDL_cpuinfo.h @@ -344,6 +344,27 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetSystemRAM(void); */ extern SDL_DECLSPEC size_t SDLCALL SDL_GetSIMDAlignment(void); +/** + * Report the size of a page of memory. + * + * Different platforms might have different memory page sizes. In current + * times, 4 kilobytes is not unusual, but newer systems are moving to larger + * page sizes, and esoteric platforms might have any unexpected size. + * + * Note that this function can return 0, which means SDL can't determine + * the page size on this platform. It will _not_ set an error string to be + * retrieved with SDL_GetError() in this case! In this case, defaulting to + * 4096 is often a reasonable option. + * + * \returns the size of a single page of memory, in bytes, or 0 if SDL can't + * determine this information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.4.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_GetSystemPageSize(void); + /* Ends C function definitions when using C++ */ #ifdef __cplusplus } diff --git a/src/cpuinfo/SDL_cpuinfo.c b/src/cpuinfo/SDL_cpuinfo.c index 1ec1655135..a097170e11 100644 --- a/src/cpuinfo/SDL_cpuinfo.c +++ b/src/cpuinfo/SDL_cpuinfo.c @@ -1213,6 +1213,65 @@ int SDL_GetSystemRAM(void) return SDL_SystemRAM; } + +static int SDL_SystemPageSize = -1; + +int SDL_GetSystemPageSize(void) +{ + if (SDL_SystemPageSize == -1) { +#ifdef SDL_PLATFORM_SYSTEM_PAGE_SIZE_PRIVATE // consoles will define this in a platform-specific internal header. + SDL_SystemPageSize = SDL_PLATFORM_SYSTEM_PAGE_SIZE_PRIVATE; +#endif +#ifdef SDL_PLATFORM_3DS + SDL_SystemPageSize = 4096; // It's an ARM11 CPU; I assume this is 4K. +#endif +#ifdef SDL_PLATFORM_VITA + SDL_SystemPageSize = 4096; // It's an ARMv7 CPU; I assume this is 4K. +#endif +#ifdef SDL_PLATFORM_PS2 + SDL_SystemPageSize = 4096; // It's a MIPS R5900 CPU; I assume this is 4K. +#endif +#if defined(HAVE_SYSCONF) && (defined(_SC_PAGESIZE) || defined(_SC_PAGE_SIZE)) + if (SDL_SystemPageSize <= 0) { + #if defined(_SC_PAGE_SIZE) + SDL_SystemPageSize = sysconf(_SC_PAGE_SIZE); + #else + SDL_SystemPageSize = sysconf(_SC_PAGESIZE); + #endif + } +#endif +#if defined(HAVE_SYSCTLBYNAME) && defined(HW_PAGESIZE) + if (SDL_SystemPageSize <= 0) { + // NetBSD, OpenBSD, FreeBSD, Darwin...everything agrees to use HW_PAGESIZE. + int mib[2] = { CTL_HW, HW_PAGESIZE }; + int pagesize = 0; + size_t len = sizeof(pagesize); + + if (sysctl(mib, 2, &pagesize, &len, NULL, 0) == 0) { + SDL_SystemPageSize = pagesize; + } + } +#endif +#ifdef HAVE_GETPAGESIZE + if (SDL_SystemPageSize <= 0) { + SDL_SystemPageSize = getpagesize(); + } +#endif +#if defined(SDL_PLATFORM_WINDOWS) + if (SDL_SystemPageSize <= 0) { + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + SDL_SystemPageSize = (int) sysinfo.dwPageSize; + } +#endif + if (SDL_SystemPageSize < 0) { // in case we got a weird result somewhere, or no better information, force it to 0. + SDL_SystemPageSize = 0; // unknown page size, sorry. + } + } + return SDL_SystemPageSize; +} + + size_t SDL_GetSIMDAlignment(void) { if (SDL_SIMDAlignment == 0xFFFFFFFF) { diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 3aa7a822e6..dce512ba9b 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -1264,6 +1264,7 @@ SDL3_0.0.0 { SDL_LoadPNG; SDL_SavePNG_IO; SDL_SavePNG; + SDL_GetSystemPageSize; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index f0693ad980..c4fa08b353 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -1290,3 +1290,4 @@ #define SDL_LoadPNG SDL_LoadPNG_REAL #define SDL_SavePNG_IO SDL_SavePNG_IO_REAL #define SDL_SavePNG SDL_SavePNG_REAL +#define SDL_GetSystemPageSize SDL_GetSystemPageSize_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 4e3ca27e3e..7c6a6f8388 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1298,3 +1298,4 @@ SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadPNG_IO,(SDL_IOStream *a,bool b),(a,b),retur SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadPNG,(const char *a),(a),return) SDL_DYNAPI_PROC(bool,SDL_SavePNG_IO,(SDL_Surface *a,SDL_IOStream *b,bool c),(a,b,c),return) SDL_DYNAPI_PROC(bool,SDL_SavePNG,(SDL_Surface *a,const char *b),(a,b),return) +SDL_DYNAPI_PROC(int,SDL_GetSystemPageSize,(void),(),return) diff --git a/test/testplatform.c b/test/testplatform.c index c1eb6aa62f..1b8945c49d 100644 --- a/test/testplatform.c +++ b/test/testplatform.c @@ -412,6 +412,7 @@ static int TestCPUInfo(bool verbose) SDL_Log("LSX %s", SDL_HasLSX() ? "detected" : "not detected"); SDL_Log("LASX %s", SDL_HasLASX() ? "detected" : "not detected"); SDL_Log("System RAM %d MB", SDL_GetSystemRAM()); + SDL_Log("System memory page size %d bytes", SDL_GetSystemPageSize()); } return 0; } diff --git a/test/testsymbols.c b/test/testsymbols.c index 7b5a9df2ed..f8655a8460 100644 --- a/test/testsymbols.c +++ b/test/testsymbols.c @@ -1339,6 +1339,7 @@ const static struct { SDL_SYMBOL_ITEM(SDL_LoadPNG), SDL_SYMBOL_ITEM(SDL_SavePNG_IO), SDL_SYMBOL_ITEM(SDL_SavePNG), + SDL_SYMBOL_ITEM(SDL_GetSystemPageSize), /* extra symbols go here (don't modify this line) */ { NULL, NULL } };