Add SDL_SIMDRealloc
authorEthan Lee
Thu, 11 Jun 2020 12:03:33 -0400
changeset 13910f7db85ea3b3c
parent 13909 7c2f418f701b
child 13911 2aa5945a2336
Add SDL_SIMDRealloc
include/SDL_cpuinfo.h
src/cpuinfo/SDL_cpuinfo.c
src/dynapi/SDL_dynapi_overrides.h
src/dynapi/SDL_dynapi_procs.h
     1.1 --- a/include/SDL_cpuinfo.h	Wed Jun 10 09:38:43 2020 -0700
     1.2 +++ b/include/SDL_cpuinfo.h	Thu Jun 11 12:03:33 2020 -0400
     1.3 @@ -246,11 +246,34 @@
     1.4   * \return Pointer to newly-allocated block, NULL if out of memory.
     1.5   *
     1.6   * \sa SDL_SIMDAlignment
     1.7 + * \sa SDL_SIMDRealloc
     1.8   * \sa SDL_SIMDFree
     1.9   */
    1.10  extern DECLSPEC void * SDLCALL SDL_SIMDAlloc(const size_t len);
    1.11  
    1.12  /**
    1.13 + * \brief Reallocate memory obtained from SDL_SIMDAlloc
    1.14 + *
    1.15 + * It is not valid to use this function on a pointer from anything but
    1.16 + *  SDL_SIMDAlloc(). It can't be used on pointers from malloc, realloc,
    1.17 + *  SDL_malloc, memalign, new[], etc.
    1.18 + *
    1.19 + *  \param mem The pointer obtained from SDL_SIMDAlloc. This function also
    1.20 + *             accepts NULL, at which point this function is the same as
    1.21 + *             calling SDL_realloc with a NULL pointer.
    1.22 + *  \param len The length, in bytes, of the block to allocated. The actual
    1.23 + *             allocated block might be larger due to padding, etc. Passing 0
    1.24 + *             will return a non-NULL pointer, assuming the system isn't out of
    1.25 + *             memory.
    1.26 + * \return Pointer to newly-reallocated block, NULL if out of memory.
    1.27 + *
    1.28 + * \sa SDL_SIMDAlignment
    1.29 + * \sa SDL_SIMDAlloc
    1.30 + * \sa SDL_SIMDFree
    1.31 + */
    1.32 +extern DECLSPEC void * SDLCALL SDL_SIMDRealloc(void *mem, size_t len);
    1.33 +
    1.34 +/**
    1.35   * \brief Deallocate memory obtained from SDL_SIMDAlloc
    1.36   *
    1.37   * It is not valid to use this function on a pointer from anything but
    1.38 @@ -260,6 +283,7 @@
    1.39   * However, SDL_SIMDFree(NULL) is a legal no-op.
    1.40   *
    1.41   * \sa SDL_SIMDAlloc
    1.42 + * \sa SDL_SIMDRealloc
    1.43   */
    1.44  extern DECLSPEC void SDLCALL SDL_SIMDFree(void *ptr);
    1.45  
     2.1 --- a/src/cpuinfo/SDL_cpuinfo.c	Wed Jun 10 09:38:43 2020 -0700
     2.2 +++ b/src/cpuinfo/SDL_cpuinfo.c	Thu Jun 11 12:03:33 2020 -0400
     2.3 @@ -956,6 +956,58 @@
     2.4      return retval;
     2.5  }
     2.6  
     2.7 +void *
     2.8 +SDL_SIMDRealloc(void *mem, const size_t len)
     2.9 +{
    2.10 +    const size_t alignment = SDL_SIMDGetAlignment();
    2.11 +    const size_t padding = alignment - (len % alignment);
    2.12 +    const size_t padded = (padding != alignment) ? (len + padding) : len;
    2.13 +    Uint8 *retval = (Uint8*) mem;
    2.14 +    void *oldmem = mem;
    2.15 +    size_t memdiff, ptrdiff;
    2.16 +    Uint8 *ptr;
    2.17 +
    2.18 +    if (mem) {
    2.19 +        void **realptr = (void **) mem;
    2.20 +        realptr--;
    2.21 +        mem = *(((void **) mem) - 1);
    2.22 +
    2.23 +        /* Check the delta between the real pointer and user pointer */
    2.24 +        memdiff = ((size_t) oldmem) - ((size_t) mem);
    2.25 +    }
    2.26 +
    2.27 +    ptr = (Uint8 *) SDL_realloc(mem, padded + alignment + sizeof (void *));
    2.28 +
    2.29 +    if (ptr == mem) {
    2.30 +        return retval; /* Pointer didn't change, nothing to do */
    2.31 +    }
    2.32 +    if (ptr == NULL) {
    2.33 +        return NULL; /* Out of memory, bail! */
    2.34 +    }
    2.35 +
    2.36 +    /* Store the actual malloc pointer right before our aligned pointer. */
    2.37 +    retval = ptr + sizeof (void *);
    2.38 +    retval += alignment - (((size_t) retval) % alignment);
    2.39 +
    2.40 +    /* Make sure the delta is the same! */
    2.41 +    if (mem) {
    2.42 +        ptrdiff = ((size_t) retval) - ((size_t) ptr);
    2.43 +        if (memdiff != ptrdiff) { /* Delta has changed, copy to new offset! */
    2.44 +            oldmem = (void*) (((size_t) ptr) + memdiff);
    2.45 +
    2.46 +            /* Even though the data past the old `len` is undefined, this is the
    2.47 +             * only length value we have, and it guarantees that we copy all the
    2.48 +             * previous memory anyhow.
    2.49 +             */
    2.50 +            SDL_memmove(retval, oldmem, len);
    2.51 +        }
    2.52 +    }
    2.53 +
    2.54 +    /* Actually store the malloc pointer, finally. */
    2.55 +    *(((void **) retval) - 1) = ptr;
    2.56 +    return retval;
    2.57 +}
    2.58 +
    2.59  void
    2.60  SDL_SIMDFree(void *ptr)
    2.61  {
     3.1 --- a/src/dynapi/SDL_dynapi_overrides.h	Wed Jun 10 09:38:43 2020 -0700
     3.2 +++ b/src/dynapi/SDL_dynapi_overrides.h	Thu Jun 11 12:03:33 2020 -0400
     3.3 @@ -716,6 +716,7 @@
     3.4  #define SDL_UIKitRunApp SDL_UIKitRunApp_REAL
     3.5  #define SDL_SIMDGetAlignment SDL_SIMDGetAlignment_REAL
     3.6  #define SDL_SIMDAlloc SDL_SIMDAlloc_REAL
     3.7 +#define SDL_SIMDRealloc SDL_SIMDRealloc_REAL
     3.8  #define SDL_SIMDFree SDL_SIMDFree_REAL
     3.9  #define SDL_RWsize SDL_RWsize_REAL
    3.10  #define SDL_RWseek SDL_RWseek_REAL
     4.1 --- a/src/dynapi/SDL_dynapi_procs.h	Wed Jun 10 09:38:43 2020 -0700
     4.2 +++ b/src/dynapi/SDL_dynapi_procs.h	Thu Jun 11 12:03:33 2020 -0400
     4.3 @@ -772,6 +772,7 @@
     4.4  #endif
     4.5  SDL_DYNAPI_PROC(size_t,SDL_SIMDGetAlignment,(void),(),return)
     4.6  SDL_DYNAPI_PROC(void*,SDL_SIMDAlloc,(const size_t a),(a),return)
     4.7 +SDL_DYNAPI_PROC(void*,SDL_SIMDRealloc,(void *a, const size_t b),(a, b),return)
     4.8  SDL_DYNAPI_PROC(void,SDL_SIMDFree,(void *a),(a),)
     4.9  SDL_DYNAPI_PROC(Sint64,SDL_RWsize,(SDL_RWops *a),(a),return)
    4.10  SDL_DYNAPI_PROC(Sint64,SDL_RWseek,(SDL_RWops *a, Sint64 b, int c),(a,b,c),return)