Add SDL_SIMDRealloc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
diff --git a/include/SDL_cpuinfo.h b/include/SDL_cpuinfo.h
index 0d9b821..56908d7 100644
--- a/include/SDL_cpuinfo.h
+++ b/include/SDL_cpuinfo.h
@@ -246,11 +246,34 @@ extern DECLSPEC size_t SDLCALL SDL_SIMDGetAlignment(void);
* \return Pointer to newly-allocated block, NULL if out of memory.
*
* \sa SDL_SIMDAlignment
+ * \sa SDL_SIMDRealloc
* \sa SDL_SIMDFree
*/
extern DECLSPEC void * SDLCALL SDL_SIMDAlloc(const size_t len);
/**
+ * \brief Reallocate memory obtained from SDL_SIMDAlloc
+ *
+ * It is not valid to use this function on a pointer from anything but
+ * SDL_SIMDAlloc(). It can't be used on pointers from malloc, realloc,
+ * SDL_malloc, memalign, new[], etc.
+ *
+ * \param mem The pointer obtained from SDL_SIMDAlloc. This function also
+ * accepts NULL, at which point this function is the same as
+ * calling SDL_realloc with a NULL pointer.
+ * \param len The length, in bytes, of the block to allocated. The actual
+ * allocated block might be larger due to padding, etc. Passing 0
+ * will return a non-NULL pointer, assuming the system isn't out of
+ * memory.
+ * \return Pointer to newly-reallocated block, NULL if out of memory.
+ *
+ * \sa SDL_SIMDAlignment
+ * \sa SDL_SIMDAlloc
+ * \sa SDL_SIMDFree
+ */
+extern DECLSPEC void * SDLCALL SDL_SIMDRealloc(void *mem, size_t len);
+
+/**
* \brief Deallocate memory obtained from SDL_SIMDAlloc
*
* It is not valid to use this function on a pointer from anything but
@@ -260,6 +283,7 @@ extern DECLSPEC void * SDLCALL SDL_SIMDAlloc(const size_t len);
* However, SDL_SIMDFree(NULL) is a legal no-op.
*
* \sa SDL_SIMDAlloc
+ * \sa SDL_SIMDRealloc
*/
extern DECLSPEC void SDLCALL SDL_SIMDFree(void *ptr);
diff --git a/src/cpuinfo/SDL_cpuinfo.c b/src/cpuinfo/SDL_cpuinfo.c
index 9cecb4f..70e268b 100644
--- a/src/cpuinfo/SDL_cpuinfo.c
+++ b/src/cpuinfo/SDL_cpuinfo.c
@@ -956,6 +956,58 @@ SDL_SIMDAlloc(const size_t len)
return retval;
}
+void *
+SDL_SIMDRealloc(void *mem, const size_t len)
+{
+ const size_t alignment = SDL_SIMDGetAlignment();
+ const size_t padding = alignment - (len % alignment);
+ const size_t padded = (padding != alignment) ? (len + padding) : len;
+ Uint8 *retval = (Uint8*) mem;
+ void *oldmem = mem;
+ size_t memdiff, ptrdiff;
+ Uint8 *ptr;
+
+ if (mem) {
+ void **realptr = (void **) mem;
+ realptr--;
+ mem = *(((void **) mem) - 1);
+
+ /* Check the delta between the real pointer and user pointer */
+ memdiff = ((size_t) oldmem) - ((size_t) mem);
+ }
+
+ ptr = (Uint8 *) SDL_realloc(mem, padded + alignment + sizeof (void *));
+
+ if (ptr == mem) {
+ return retval; /* Pointer didn't change, nothing to do */
+ }
+ if (ptr == NULL) {
+ return NULL; /* Out of memory, bail! */
+ }
+
+ /* Store the actual malloc pointer right before our aligned pointer. */
+ retval = ptr + sizeof (void *);
+ retval += alignment - (((size_t) retval) % alignment);
+
+ /* Make sure the delta is the same! */
+ if (mem) {
+ ptrdiff = ((size_t) retval) - ((size_t) ptr);
+ if (memdiff != ptrdiff) { /* Delta has changed, copy to new offset! */
+ oldmem = (void*) (((size_t) ptr) + memdiff);
+
+ /* Even though the data past the old `len` is undefined, this is the
+ * only length value we have, and it guarantees that we copy all the
+ * previous memory anyhow.
+ */
+ SDL_memmove(retval, oldmem, len);
+ }
+ }
+
+ /* Actually store the malloc pointer, finally. */
+ *(((void **) retval) - 1) = ptr;
+ return retval;
+}
+
void
SDL_SIMDFree(void *ptr)
{
diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h
index cb596aa..5223a6c 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -716,6 +716,7 @@
#define SDL_UIKitRunApp SDL_UIKitRunApp_REAL
#define SDL_SIMDGetAlignment SDL_SIMDGetAlignment_REAL
#define SDL_SIMDAlloc SDL_SIMDAlloc_REAL
+#define SDL_SIMDRealloc SDL_SIMDRealloc_REAL
#define SDL_SIMDFree SDL_SIMDFree_REAL
#define SDL_RWsize SDL_RWsize_REAL
#define SDL_RWseek SDL_RWseek_REAL
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index b501d69..90d2075 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -772,6 +772,7 @@ SDL_DYNAPI_PROC(int,SDL_UIKitRunApp,(int a, char *b, SDL_main_func c),(a,b,c),re
#endif
SDL_DYNAPI_PROC(size_t,SDL_SIMDGetAlignment,(void),(),return)
SDL_DYNAPI_PROC(void*,SDL_SIMDAlloc,(const size_t a),(a),return)
+SDL_DYNAPI_PROC(void*,SDL_SIMDRealloc,(void *a, const size_t b),(a, b),return)
SDL_DYNAPI_PROC(void,SDL_SIMDFree,(void *a),(a),)
SDL_DYNAPI_PROC(Sint64,SDL_RWsize,(SDL_RWops *a),(a),return)
SDL_DYNAPI_PROC(Sint64,SDL_RWseek,(SDL_RWops *a, Sint64 b, int c),(a,b,c),return)