Browse Source

cpuinfo: Added SDL_GetSystemPageSize.

Fixes #14201.
Ryan C. Gordon 1 day ago
parent
commit
f7d5bb3c7a

+ 21 - 0
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
 }

+ 59 - 0
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) {

+ 1 - 0
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: *;
 };

+ 1 - 0
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

+ 1 - 0
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)

+ 1 - 0
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;
 }

+ 1 - 0
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 }
 };