msvcrt: add _aligned_malloc functions

Robert Reif reif at earthlink.net
Fri Jul 27 19:02:23 CDT 2007


Add _aligned_malloc family of functions.
-------------- next part --------------
diff --git a/dlls/msvcrt/heap.c b/dlls/msvcrt/heap.c
index ab6dd01..c81f5f2 100644
--- a/dlls/msvcrt/heap.c
+++ b/dlls/msvcrt/heap.c
@@ -23,6 +23,7 @@
 
 #include "msvcrt.h"
 #include "mtdll.h"
+#include "msvcrt/errno.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
@@ -31,6 +32,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
 #define LOCK_HEAP   _mlock( _HEAP_LOCK )
 #define UNLOCK_HEAP _munlock( _HEAP_LOCK )
 
+/* _aligned */
+#define SAVED_PTR(x) (void *)((DWORD_PTR)((char *)x - sizeof(void *)) & \
+                     ~(sizeof(void *) - 1))
+#define ALIGN_PTR(ptr, alignment, offset) (void *) \
+    ((((DWORD_PTR)((char *)ptr + alignment + sizeof(void *) + offset)) & \
+    ~(alignment - 1)) - offset)
+
 
 typedef void (*MSVCRT_new_handler_func)(unsigned long size);
 
@@ -314,3 +322,150 @@ int CDECL _set_sbh_threshold(size_t thre
      MSVCRT_sbh_threshold = threshold;
   return 1;
 }
+
+/*********************************************************************
+ *		_aligned_free (MSVCRT.@)
+ */
+void CDECL _aligned_free(void *memblock)
+{
+    TRACE("(%p)\n", memblock);
+
+    if (memblock)
+    {
+        void **saved = SAVED_PTR(memblock);
+        MSVCRT_free(*saved);
+    }
+}
+
+/*********************************************************************
+ *		_aligned_offset_malloc (MSVCRT.@)
+ */
+void * CDECL _aligned_offset_malloc(size_t size, size_t alignment,
+                                    size_t offset)
+{
+    void *memblock, *temp, **saved;
+    TRACE("(%u, %u, %u)\n", size, alignment, offset);
+
+    /* alignment must be a power of 2 */
+    if ((alignment & (alignment - 1)) != 0)
+    {
+        msvcrt_set_errno(EINVAL);
+        return NULL;
+    }
+
+    /* offset must be less than size */
+    if (offset >= size)
+    {
+        msvcrt_set_errno(EINVAL);
+        return NULL;
+    }
+
+    /* don't align to less than void pointer size */
+    if (alignment < sizeof(void *))
+        alignment = sizeof(void *);
+
+    /* allocate enough space for void pointer and alignment */
+    temp = MSVCRT_malloc(size + alignment + sizeof(void *));
+
+    if (!temp)
+        return NULL;
+
+    /* adjust pointer for proper alignment and offset */
+    memblock = ALIGN_PTR(temp, alignment, offset);
+
+    /* Save the real allocation address below returned address */
+    /* so it can be found later to free. */ 
+    saved = SAVED_PTR(memblock);
+    *saved = temp;
+
+    return memblock; 
+}
+
+/*********************************************************************
+ *		_aligned_malloc (MSVCRT.@)
+ */
+void * CDECL _aligned_malloc(size_t size, size_t alignment)
+{
+    TRACE("(%u, %u)\n", size, alignment);
+    return _aligned_offset_malloc(size, alignment, 0);; 
+}
+
+/*********************************************************************
+ *		_aligned_offset_realloc (MSVCRT.@)
+ */
+void * CDECL _aligned_offset_realloc(void *memblock, size_t size,
+                                     size_t alignment, size_t offset)
+{
+    void * temp, **saved;
+    long old_padding, new_padding;
+    TRACE("(%p, %u, %u, %u)\n", memblock, size, alignment, offset);
+
+    if (!memblock)
+        return _aligned_offset_malloc(size, alignment, offset);
+
+    /* alignment must be a power of 2 */
+    if ((alignment & (alignment - 1)) != 0)
+    {
+        msvcrt_set_errno(EINVAL);
+        return NULL;
+    }
+
+    /* offset must be less than size */
+    if (offset >= size)
+    {
+        msvcrt_set_errno(EINVAL);
+        return NULL;
+    }
+
+    if (size == 0)
+    {
+        _aligned_free(memblock);
+        return NULL;
+    }
+
+    /* don't align to less than void pointer size */
+    if (alignment < sizeof(void *))
+        alignment = sizeof(void *);
+
+    /* make sure alignment and offset didn't change */
+    saved = SAVED_PTR(memblock);
+    if (memblock != ALIGN_PTR(*saved, alignment, offset))
+    {
+        msvcrt_set_errno(EINVAL);
+        return NULL;
+    }
+
+    old_padding = (long)*saved - (long)memblock;
+
+    temp = MSVCRT_realloc(*saved, size + alignment + sizeof(void *));
+
+    if (!temp)
+        return NULL;
+
+    /* adjust pointer for proper alignment and offset */
+    memblock = ALIGN_PTR(temp, alignment, offset);
+
+    /* Save the real allocation address below returned address */
+    /* so it can be found later to free. */ 
+    saved = SAVED_PTR(memblock);
+
+    /* a new start address may require different padding to get the */
+    /* proper alignment */
+    new_padding = (long)temp - (long)memblock;
+    if (new_padding != old_padding)
+        memmove((char *)memblock + old_padding, (char *)memblock + new_padding, size);
+
+    *saved = temp;
+
+    return memblock; 
+}
+
+/*********************************************************************
+ *		_aligned_realloc (MSVCRT.@)
+ */
+void * CDECL _aligned_realloc(void *memblock, size_t size,
+                              size_t alignment)
+{
+    TRACE("(%p, %u, %u)\n", memblock, size, alignment);
+    return _aligned_offset_realloc(memblock, size, alignment, 0);
+}
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec
index cb427ab..fc81898 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -163,6 +163,11 @@ # msvcrt.dll - MS VC++ Run Time Library
 @ cdecl _adj_fptan()
 @ extern _adjust_fdiv MSVCRT__adjust_fdiv 
 # extern _aexit_rtn
+@ cdecl _aligned_free(ptr)
+@ cdecl _aligned_malloc(long long)
+@ cdecl _aligned_offset_malloc(long long long)
+@ cdecl _aligned_offset_realloc(ptr long long long)
+@ cdecl _aligned_realloc(ptr long long)
 @ cdecl _amsg_exit(long)
 @ cdecl _assert(str str long) MSVCRT__assert
 @ stub _atodbl #(ptr str)
diff --git a/include/msvcrt/malloc.h b/include/msvcrt/malloc.h
index 25ae615..bee2173 100644
--- a/include/msvcrt/malloc.h
+++ b/include/msvcrt/malloc.h
@@ -86,6 +86,12 @@ void        free(void*);
 void*       malloc(size_t);
 void*       realloc(void*,size_t);
 
+void        _aligned_free(void*);
+void*       _aligned_malloc(size_t,size_t);
+void*       _aligned_offset_malloc(size_t,size_t,size_t);
+void*       _aligned_realloc(void*,size_t,size_t);
+void*       _aligned_offset_realloc(void*,size_t,size_t,size_t);
+
 size_t _get_sbh_threshold(void);
 int _set_sbh_threshold(size_t size);
 


More information about the wine-patches mailing list