diff --git a/conf.h.in b/conf.h.in index ecd1811..48de4cb 100644 --- a/conf.h.in +++ b/conf.h.in @@ -60,6 +60,16 @@ #define USE_MMAP 0 #define HAVE_MUNMAP 0 +/* + * On Windows, use VirtualAlloc() to allocate memory and use VirtualFree + * to deallocate it. To be absolutely sure, try to find it in one of the + * two sets of header files. + */ +#define HAVE_DECL_VIRTUALALLOC 0 +#define HAVE_DECL_VIRTUALFREE 0 +#define HAVE_VIRTUALALLOC_MEMORYAPI_H 0 +#define HAVE_VIRTUALALLOC_WINDOWS_H 0 + /* * This is the basic block size in bits. If possible, the configure * script will set this to be the value returned by the getpagesize() diff --git a/configure.ac b/configure.ac index a5295f1..7d84310 100644 --- a/configure.ac +++ b/configure.ac @@ -345,7 +345,31 @@ AC_MSG_NOTICE([important functionality]) AC_CHECK_FUNCS(mmap munmap sbrk) -if test "x$ac_cv_func_mmap" != "xyes" && test "x$ac_cv_func_sbrk" != "xyes"; then +ac_cv_target_win32=no +AC_MSG_CHECKING([for VirtualAlloc in (Windows)]) +AC_CHECK_DECLS( + [[VirtualAlloc(LPVOID, SIZE_T, DWORD, DWORD)], + [VirtualFree(LPVOID, SIZE_T, DWORD)]], + [ ac_cv_target_win32=yes; AC_DEFINE(HAVE_VIRTUALALLOC_WINDOWS_H) ], + [ + AC_MSG_CHECKING([for VirtualAlloc in , (Windows)]) + AC_CHECK_DECLS( + [[VirtualAlloc(LPVOID, SIZE_T, DWORD, DWORD)], + [VirtualFree(LPVOID, SIZE_T, DWORD)]], + [ ac_cv_target_win32=yes; AC_DEFINE(HAVE_VIRTUALALLOC_MEMORYAPI_H) ], + [ ac_cv_target_win32=no ], + [[#define WIN32_LEAN_AND_MEAN + #include + #include ]] + ) + ], + [[#define WIN32_LEAN_AND_MEAN + #include ]] +) + +if test "x$ac_cv_func_mmap" != "xyes" && test "x$ac_cv_func_sbrk" != "xyes" && \ + test "x$ac_cv_target_win32" != "xyes"; +then AC_MSG_WARN() AC_MSG_WARN(no mmap nor sbrk function. See INTERNAL_MEMORY_SPACE in settings.dist.) AC_MSG_WARN() diff --git a/dmalloc_t.c b/dmalloc_t.c index 13143b2..e9417db 100644 --- a/dmalloc_t.c +++ b/dmalloc_t.c @@ -61,7 +61,7 @@ #define INTER_CHAR 'i' #define DEFAULT_ITERATIONS 10000 #define MAX_POINTERS 1024 -#if HAVE_SBRK == 0 && HAVE_MMAP == 0 +#if HAVE_SBRK == 0 && HAVE_MMAP == 0 && (HAVE_DECL_VIRTUALALLOC == 0 || HAVE_DECL_VIRTUALFREE == 0) /* if we have a small memory area then just take 1/10 of the internal space */ #define MAX_ALLOC (INTERNAL_MEMORY_SPACE / 10) #else diff --git a/heap.c b/heap.c index 210c29e..8edcd3c 100644 --- a/heap.c +++ b/heap.c @@ -24,12 +24,22 @@ * heap as well as reporting the current position of the heap. */ +#include "conf.h" + #if HAVE_SYS_TYPES_H # include #endif #if HAVE_SYS_MMAN_H # include /* for mmap stuff */ #endif +#if HAVE_VIRTUALALLOC_WINDOWS_H +# define WIN32_LEAN_AND_MEAN +# include +#elif HAVE_VIRTUALALLOC_MEMORYAPI_H +# define WIN32_LEAN_AND_MEAN +# include +# include +#endif #define DMALLOC_DISABLE @@ -95,6 +105,9 @@ static void *heap_extend(const int incr) #else #if HAVE_SBRK ret = sbrk(incr); +#elif HAVE_DECL_VIRTUALALLOC && HAVE_DECL_VIRTUALFREE + ret = VirtualAlloc(NULL, incr, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (!ret) ret = SBRK_ERROR; #endif /* if HAVE_SBRK */ #endif /* if not HAVE_MMAP && USE_MMAP */ #endif /* if not INTERNAL_MEMORY_SPACE */ @@ -149,6 +162,12 @@ static void heap_release(void *addr, const int size) dmalloc_message("munmap failed to release heap memory %p, size %d", addr, size); } +#elif HAVE_DECL_VIRTUALALLOC && HAVE_DECL_VIRTUALFREE + /* NB: Assuming that heap_release is always called with the same size as + ** heap_extend. WinAPI requires the second parameter to VirtualFree + ** to be 0 to avoid reserving and then abandoning blocks of uncommitted + ** address space. */ + VirtualFree(addr, 0, MEM_RELEASE); #else /* no-op */ #endif /* if not HAVE_MMAP && USE_MMAP */ diff --git a/settings.dist b/settings.dist index eec24fc..3535ae9 100644 --- a/settings.dist +++ b/settings.dist @@ -387,7 +387,7 @@ * HAVE_MMAP are 0. Please send me email with any problems or * comments on this feature. */ -#if HAVE_SBRK == 0 && HAVE_MMAP == 0 +#if HAVE_SBRK == 0 && HAVE_MMAP == 0 && (HAVE_DECL_VIRTUALALLOC == 0 || HAVE_DECL_VIRTUALFREE == 0) #define INTERNAL_MEMORY_SPACE (1024 * 1024) #endif