Add support for Mingw

This commit is contained in:
Mike Hommey 2012-04-21 21:27:46 -07:00 committed by Jason Evans
parent a8f8d7540d
commit a19e87fbad
12 changed files with 357 additions and 71 deletions

View File

@ -32,7 +32,7 @@ SO := @so@
O := @o@ O := @o@
A := @a@ A := @a@
EXE := @exe@ EXE := @exe@
LIB := @lib@ LIBPREFIX := @libprefix@
REV := @rev@ REV := @rev@
install_suffix := @install_suffix@ install_suffix := @install_suffix@
ABI := @abi@ ABI := @abi@
@ -51,12 +51,16 @@ SOREV = @SOREV@
PIC_CFLAGS = @PIC_CFLAGS@ PIC_CFLAGS = @PIC_CFLAGS@
ifeq (macho, $(ABI)) ifeq (macho, $(ABI))
TEST_LIBRARY_PATH := DYLD_FALLBACK_LIBRARY_PATH=$(objroot)lib TEST_LIBRARY_PATH := DYLD_FALLBACK_LIBRARY_PATH="$(objroot)lib"
else
ifeq (pecoff, $(ABI))
TEST_LIBRARY_PATH := PATH="$(PATH):$(objroot)lib"
else else
TEST_LIBRARY_PATH := TEST_LIBRARY_PATH :=
endif endif
endif
LIBJEMALLOC := $(LIB)jemalloc$(install_suffix) LIBJEMALLOC := $(LIBPREFIX)jemalloc$(install_suffix)
# Lists of files. # Lists of files.
BINS := $(srcroot)bin/pprof $(objroot)bin/jemalloc.sh BINS := $(srcroot)bin/pprof $(objroot)bin/jemalloc.sh

View File

@ -198,7 +198,7 @@ so="so"
o="o" o="o"
a="a" a="a"
exe= exe=
lib="lib" libprefix="lib"
DSO_LDFLAGS='-shared -Wl,-soname,$(@F)' DSO_LDFLAGS='-shared -Wl,-soname,$(@F)'
RPATH='-Wl,-rpath,$(1)' RPATH='-Wl,-rpath,$(1)'
SOREV='$(SO).$(REV)' SOREV='$(SO).$(REV)'
@ -273,6 +273,19 @@ case "${host}" in
fi fi
abi="xcoff" abi="xcoff"
;; ;;
*-*-mingw*)
abi="pecoff"
force_tls="0"
RPATH=""
so="dll"
DSO_LDFLAGS="-shared"
o="obj"
a="lib"
libprefix=""
exe=".exe"
SOREV='$(SO)'
PIC_CFLAGS=""
;;
*) *)
AC_MSG_RESULT([Unsupported operating system: ${host}]) AC_MSG_RESULT([Unsupported operating system: ${host}])
abi="elf" abi="elf"
@ -285,7 +298,7 @@ AC_SUBST([so])
AC_SUBST([o]) AC_SUBST([o])
AC_SUBST([a]) AC_SUBST([a])
AC_SUBST([exe]) AC_SUBST([exe])
AC_SUBST([lib]) AC_SUBST([libprefix])
AC_SUBST([DSO_LDFLAGS]) AC_SUBST([DSO_LDFLAGS])
AC_SUBST([SOREV]) AC_SUBST([SOREV])
AC_SUBST([PIC_CFLAGS]) AC_SUBST([PIC_CFLAGS])
@ -817,23 +830,36 @@ AC_SUBST([enable_xmalloc])
AC_CACHE_CHECK([STATIC_PAGE_SHIFT], AC_CACHE_CHECK([STATIC_PAGE_SHIFT],
[je_cv_static_page_shift], [je_cv_static_page_shift],
AC_RUN_IFELSE([AC_LANG_PROGRAM( AC_RUN_IFELSE([AC_LANG_PROGRAM(
[[#include <stdio.h> [[
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h> #include <unistd.h>
#include <strings.h> #include <strings.h>
#endif
#include <stdio.h>
]], ]],
[[ [[
long result; long result;
FILE *f; FILE *f;
#ifdef _WIN32
SYSTEM_INFO si;
GetSystemInfo(&si);
result = si.dwPageSize;
#else
result = sysconf(_SC_PAGESIZE); result = sysconf(_SC_PAGESIZE);
#endif
if (result == -1) { if (result == -1) {
return 1; return 1;
} }
result = ffsl(result) - 1;
f = fopen("conftest.out", "w"); f = fopen("conftest.out", "w");
if (f == NULL) { if (f == NULL) {
return 1; return 1;
} }
fprintf(f, "%u\n", ffs((int)result) - 1); fprintf(f, "%u\n", result);
fclose(f); fclose(f);
return 0; return 0;
@ -871,12 +897,14 @@ AC_SUBST([jemalloc_version_gid])
dnl ============================================================================ dnl ============================================================================
dnl Configure pthreads. dnl Configure pthreads.
if test "x$abi" != "xpecoff" ; then
AC_CHECK_HEADERS([pthread.h], , [AC_MSG_ERROR([pthread.h is missing])]) AC_CHECK_HEADERS([pthread.h], , [AC_MSG_ERROR([pthread.h is missing])])
dnl Some systems may embed pthreads functionality in libc; check for libpthread dnl Some systems may embed pthreads functionality in libc; check for libpthread
dnl first, but try libc too before failing. dnl first, but try libc too before failing.
AC_CHECK_LIB([pthread], [pthread_create], [LIBS="$LIBS -lpthread"], AC_CHECK_LIB([pthread], [pthread_create], [LIBS="$LIBS -lpthread"],
[AC_SEARCH_LIBS([pthread_create], , , [AC_SEARCH_LIBS([pthread_create], , ,
AC_MSG_ERROR([libpthread is missing]))]) AC_MSG_ERROR([libpthread is missing]))])
fi
CPPFLAGS="$CPPFLAGS -D_REENTRANT" CPPFLAGS="$CPPFLAGS -D_REENTRANT"
@ -921,11 +949,13 @@ if test "x$enable_lazy_lock" = "x0" -a "x${force_lazy_lock}" = "x1" ; then
enable_lazy_lock="1" enable_lazy_lock="1"
fi fi
if test "x$enable_lazy_lock" = "x1" ; then if test "x$enable_lazy_lock" = "x1" ; then
if test "x$abi" != "xpecoff" ; then
AC_CHECK_HEADERS([dlfcn.h], , [AC_MSG_ERROR([dlfcn.h is missing])]) AC_CHECK_HEADERS([dlfcn.h], , [AC_MSG_ERROR([dlfcn.h is missing])])
AC_CHECK_FUNC([dlsym], [], AC_CHECK_FUNC([dlsym], [],
[AC_CHECK_LIB([dl], [dlsym], [LIBS="$LIBS -ldl"], [AC_CHECK_LIB([dl], [dlsym], [LIBS="$LIBS -ldl"],
[AC_MSG_ERROR([libdl is missing])]) [AC_MSG_ERROR([libdl is missing])])
]) ])
fi
AC_DEFINE([JEMALLOC_LAZY_LOCK], [ ]) AC_DEFINE([JEMALLOC_LAZY_LOCK], [ ])
fi fi
AC_SUBST([enable_lazy_lock]) AC_SUBST([enable_lazy_lock])

View File

@ -1,21 +1,25 @@
#ifndef JEMALLOC_INTERNAL_H #ifndef JEMALLOC_INTERNAL_H
#define JEMALLOC_INTERNAL_H #define JEMALLOC_INTERNAL_H
#include <sys/mman.h>
#include <sys/param.h> #include <sys/param.h>
#ifdef _WIN32
# include <windows.h>
#else
# include <sys/mman.h>
# include <sys/syscall.h> # include <sys/syscall.h>
# if !defined(SYS_write) && defined(__NR_write) # if !defined(SYS_write) && defined(__NR_write)
# define SYS_write __NR_write # define SYS_write __NR_write
# endif # endif
# include <sys/uio.h>
# include <pthread.h>
#endif
#include <sys/time.h> #include <sys/time.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/uio.h>
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#ifndef SIZE_T_MAX #ifndef SIZE_T_MAX
# define SIZE_T_MAX SIZE_MAX # define SIZE_T_MAX SIZE_MAX
#endif #endif
#include <pthread.h>
#include <sched.h> #include <sched.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdbool.h> #include <stdbool.h>
@ -32,7 +36,6 @@
#include <ctype.h> #include <ctype.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <pthread.h>
#include <math.h> #include <math.h>
#define JEMALLOC_NO_DEMANGLE #define JEMALLOC_NO_DEMANGLE

View File

@ -3,7 +3,9 @@
typedef struct malloc_mutex_s malloc_mutex_t; typedef struct malloc_mutex_s malloc_mutex_t;
#ifdef JEMALLOC_OSSPIN #ifdef _WIN32
# define MALLOC_MUTEX_INITIALIZER
#elif (defined(JEMALLOC_OSSPIN))
# define MALLOC_MUTEX_INITIALIZER {0} # define MALLOC_MUTEX_INITIALIZER {0}
#elif (defined(JEMALLOC_MUTEX_INIT_CB)) #elif (defined(JEMALLOC_MUTEX_INIT_CB))
# define MALLOC_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER, NULL} # define MALLOC_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER, NULL}
@ -23,7 +25,9 @@ typedef struct malloc_mutex_s malloc_mutex_t;
#ifdef JEMALLOC_H_STRUCTS #ifdef JEMALLOC_H_STRUCTS
struct malloc_mutex_s { struct malloc_mutex_s {
#ifdef JEMALLOC_OSSPIN #ifdef _WIN32
CRITICAL_SECTION lock;
#elif (defined(JEMALLOC_OSSPIN))
OSSpinLock lock; OSSpinLock lock;
#elif (defined(JEMALLOC_MUTEX_INIT_CB)) #elif (defined(JEMALLOC_MUTEX_INIT_CB))
pthread_mutex_t lock; pthread_mutex_t lock;
@ -65,7 +69,9 @@ malloc_mutex_lock(malloc_mutex_t *mutex)
{ {
if (isthreaded) { if (isthreaded) {
#ifdef JEMALLOC_OSSPIN #ifdef _WIN32
EnterCriticalSection(&mutex->lock);
#elif (defined(JEMALLOC_OSSPIN))
OSSpinLockLock(&mutex->lock); OSSpinLockLock(&mutex->lock);
#else #else
pthread_mutex_lock(&mutex->lock); pthread_mutex_lock(&mutex->lock);
@ -78,7 +84,9 @@ malloc_mutex_unlock(malloc_mutex_t *mutex)
{ {
if (isthreaded) { if (isthreaded) {
#ifdef JEMALLOC_OSSPIN #ifdef _WIN32
LeaveCriticalSection(&mutex->lock);
#elif (defined(JEMALLOC_OSSPIN))
OSSpinLockUnlock(&mutex->lock); OSSpinLockUnlock(&mutex->lock);
#else #else
pthread_mutex_unlock(&mutex->lock); pthread_mutex_unlock(&mutex->lock);

View File

@ -74,6 +74,10 @@ extern bool a_name##_booted;
extern __thread a_type a_name##_tls; \ extern __thread a_type a_name##_tls; \
extern pthread_key_t a_name##_tsd; \ extern pthread_key_t a_name##_tsd; \
extern bool a_name##_booted; extern bool a_name##_booted;
#elif (defined(_WIN32))
#define malloc_tsd_externs(a_name, a_type) \
extern DWORD a_name##_tsd; \
extern bool a_name##_booted;
#else #else
#define malloc_tsd_externs(a_name, a_type) \ #define malloc_tsd_externs(a_name, a_type) \
extern pthread_key_t a_name##_tsd; \ extern pthread_key_t a_name##_tsd; \
@ -94,6 +98,10 @@ a_attr __thread a_type JEMALLOC_TLS_MODEL \
a_name##_tls = a_initializer; \ a_name##_tls = a_initializer; \
a_attr pthread_key_t a_name##_tsd; \ a_attr pthread_key_t a_name##_tsd; \
a_attr bool a_name##_booted = false; a_attr bool a_name##_booted = false;
#elif (defined(_WIN32))
#define malloc_tsd_data(a_attr, a_name, a_type, a_initializer) \
a_attr DWORD a_name##_tsd; \
a_attr bool a_name##_booted = false;
#else #else
#define malloc_tsd_data(a_attr, a_name, a_type, a_initializer) \ #define malloc_tsd_data(a_attr, a_name, a_type, a_initializer) \
a_attr pthread_key_t a_name##_tsd; \ a_attr pthread_key_t a_name##_tsd; \
@ -182,6 +190,99 @@ a_name##_tsd_set(a_type *val) \
} \ } \
} \ } \
} }
#elif (defined(_WIN32))
#define malloc_tsd_funcs(a_attr, a_name, a_type, a_initializer, \
a_cleanup) \
/* Data structure. */ \
typedef struct { \
bool initialized; \
a_type val; \
} a_name##_tsd_wrapper_t; \
/* Initialization/cleanup. */ \
a_attr bool \
a_name##_tsd_cleanup_wrapper(void) \
{ \
a_name##_tsd_wrapper_t *wrapper; \
\
wrapper = (a_name##_tsd_wrapper_t *) TlsGetValue(a_name##_tsd); \
if (wrapper == NULL) \
return (false); \
if (a_cleanup != malloc_tsd_no_cleanup && \
wrapper->initialized) { \
a_type val = wrapper->val; \
a_type tsd_static_data = a_initializer; \
wrapper->initialized = false; \
wrapper->val = tsd_static_data; \
a_cleanup(&val); \
if (wrapper->initialized) { \
/* Trigger another cleanup round. */ \
return (true); \
} \
} \
malloc_tsd_dalloc(wrapper); \
return (false); \
} \
a_attr bool \
a_name##_tsd_boot(void) \
{ \
\
a_name##_tsd = TlsAlloc(); \
if (a_name##_tsd == TLS_OUT_OF_INDEXES) \
return (true); \
if (a_cleanup != malloc_tsd_no_cleanup) { \
malloc_tsd_cleanup_register( \
&a_name##_tsd_cleanup_wrapper); \
} \
a_name##_booted = true; \
return (false); \
} \
/* Get/set. */ \
a_attr a_name##_tsd_wrapper_t * \
a_name##_tsd_get_wrapper(void) \
{ \
a_name##_tsd_wrapper_t *wrapper = (a_name##_tsd_wrapper_t *) \
TlsGetValue(a_name##_tsd); \
\
if (wrapper == NULL) { \
wrapper = (a_name##_tsd_wrapper_t *) \
malloc_tsd_malloc(sizeof(a_name##_tsd_wrapper_t)); \
if (wrapper == NULL) { \
malloc_write("<jemalloc>: Error allocating" \
" TSD for "#a_name"\n"); \
abort(); \
} else { \
static a_type tsd_static_data = a_initializer; \
wrapper->initialized = false; \
wrapper->val = tsd_static_data; \
} \
if (!TlsSetValue(a_name##_tsd, (void *)wrapper)) { \
malloc_write("<jemalloc>: Error setting" \
" TSD for "#a_name"\n"); \
abort(); \
} \
} \
return (wrapper); \
} \
a_attr a_type * \
a_name##_tsd_get(void) \
{ \
a_name##_tsd_wrapper_t *wrapper; \
\
assert(a_name##_booted); \
wrapper = a_name##_tsd_get_wrapper(); \
return (&wrapper->val); \
} \
a_attr void \
a_name##_tsd_set(a_type *val) \
{ \
a_name##_tsd_wrapper_t *wrapper; \
\
assert(a_name##_booted); \
wrapper = a_name##_tsd_get_wrapper(); \
wrapper->val = *(val); \
if (a_cleanup != malloc_tsd_no_cleanup) \
wrapper->initialized = true; \
}
#else #else
#define malloc_tsd_funcs(a_attr, a_name, a_type, a_initializer, \ #define malloc_tsd_funcs(a_attr, a_name, a_type, a_initializer, \
a_cleanup) \ a_cleanup) \

View File

@ -7,7 +7,7 @@
static void *pages_map(void *addr, size_t size); static void *pages_map(void *addr, size_t size);
static void pages_unmap(void *addr, size_t size); static void pages_unmap(void *addr, size_t size);
static void *chunk_alloc_mmap_slow(size_t size, size_t alignment, static void *chunk_alloc_mmap_slow(size_t size, size_t alignment,
bool unaligned, bool *zero); bool *zero);
/******************************************************************************/ /******************************************************************************/
@ -16,6 +16,14 @@ pages_map(void *addr, size_t size)
{ {
void *ret; void *ret;
#ifdef _WIN32
/*
* If VirtualAlloc can't allocate at the given address when one is
* given, it fails and returns NULL.
*/
ret = VirtualAlloc(addr, size, MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE);
#else
/* /*
* We don't use MAP_FIXED here, because it can cause the *replacement* * We don't use MAP_FIXED here, because it can cause the *replacement*
* of existing mappings, and we only want to create new mappings. * of existing mappings, and we only want to create new mappings.
@ -41,7 +49,7 @@ pages_map(void *addr, size_t size)
} }
ret = NULL; ret = NULL;
} }
#endif
assert(ret == NULL || (addr == NULL && ret != addr) assert(ret == NULL || (addr == NULL && ret != addr)
|| (addr != NULL && ret == addr)); || (addr != NULL && ret == addr));
return (ret); return (ret);
@ -51,20 +59,65 @@ static void
pages_unmap(void *addr, size_t size) pages_unmap(void *addr, size_t size)
{ {
if (munmap(addr, size) == -1) { #ifdef _WIN32
if (VirtualFree(addr, 0, MEM_RELEASE) == 0)
#else
if (munmap(addr, size) == -1)
#endif
{
char buf[BUFERROR_BUF]; char buf[BUFERROR_BUF];
buferror(errno, buf, sizeof(buf)); buferror(errno, buf, sizeof(buf));
malloc_printf("<jemalloc>: Error in munmap(): %s\n", buf); malloc_printf("<jemalloc>: Error in "
#ifdef _WIN32
"VirtualFree"
#else
"munmap"
#endif
"(): %s\n", buf);
if (opt_abort) if (opt_abort)
abort(); abort();
} }
} }
static void *
pages_trim(void *addr, size_t alloc_size, size_t leadsize, size_t size)
{
void *ret = (void *)((uintptr_t)addr + leadsize);
assert(alloc_size >= leadsize + size);
#ifdef _WIN32
{
void *new_addr;
pages_unmap(addr, alloc_size);
new_addr = pages_map(ret, size);
if (new_addr == ret)
return (ret);
if (new_addr)
pages_unmap(new_addr, size);
return (NULL);
}
#else
{
size_t trailsize = alloc_size - leadsize - size;
if (leadsize != 0)
pages_unmap(addr, leadsize);
if (trailsize != 0)
pages_unmap((void *)((uintptr_t)ret + size), trailsize);
return (ret);
}
#endif
}
void void
pages_purge(void *addr, size_t length) pages_purge(void *addr, size_t length)
{ {
#ifdef _WIN32
VirtualAlloc(addr, length, MEM_RESET, PAGE_READWRITE);
#else
# ifdef JEMALLOC_PURGE_MADVISE_DONTNEED # ifdef JEMALLOC_PURGE_MADVISE_DONTNEED
# define JEMALLOC_MADV_PURGE MADV_DONTNEED # define JEMALLOC_MADV_PURGE MADV_DONTNEED
# elif defined(JEMALLOC_PURGE_MADVISE_FREE) # elif defined(JEMALLOC_PURGE_MADVISE_FREE)
@ -73,33 +126,27 @@ pages_purge(void *addr, size_t length)
# error "No method defined for purging unused dirty pages." # error "No method defined for purging unused dirty pages."
# endif # endif
madvise(addr, length, JEMALLOC_MADV_PURGE); madvise(addr, length, JEMALLOC_MADV_PURGE);
#endif
} }
static void * static void *
chunk_alloc_mmap_slow(size_t size, size_t alignment, bool unaligned, bool *zero) chunk_alloc_mmap_slow(size_t size, size_t alignment, bool *zero)
{ {
void *ret, *pages; void *ret, *pages;
size_t alloc_size, leadsize, trailsize; size_t alloc_size, leadsize;
alloc_size = size + alignment - PAGE; alloc_size = size + alignment - PAGE;
/* Beware size_t wrap-around. */ /* Beware size_t wrap-around. */
if (alloc_size < size) if (alloc_size < size)
return (NULL); return (NULL);
do {
pages = pages_map(NULL, alloc_size); pages = pages_map(NULL, alloc_size);
if (pages == NULL) if (pages == NULL)
return (NULL); return (NULL);
leadsize = ALIGNMENT_CEILING((uintptr_t)pages, alignment) - leadsize = ALIGNMENT_CEILING((uintptr_t)pages, alignment) -
(uintptr_t)pages; (uintptr_t)pages;
assert(alloc_size >= leadsize + size); ret = pages_trim(pages, alloc_size, leadsize, size);
trailsize = alloc_size - leadsize - size; } while (ret == NULL);
ret = (void *)((uintptr_t)pages + leadsize);
if (leadsize != 0) {
/* Note that mmap() returned an unaligned mapping. */
unaligned = true;
pages_unmap(pages, leadsize);
}
if (trailsize != 0)
pages_unmap((void *)((uintptr_t)ret + size), trailsize);
assert(ret != NULL); assert(ret != NULL);
*zero = true; *zero = true;
@ -144,6 +191,9 @@ chunk_alloc_mmap(size_t size, size_t alignment, bool *zero)
offset = ALIGNMENT_ADDR2OFFSET(ret, alignment); offset = ALIGNMENT_ADDR2OFFSET(ret, alignment);
if (offset != 0) { if (offset != 0) {
#ifdef _WIN32
return (chunk_alloc_mmap_slow(size, alignment, zero));
#else
/* Try to extend chunk boundary. */ /* Try to extend chunk boundary. */
if (pages_map((void *)((uintptr_t)ret + size), chunksize - if (pages_map((void *)((uintptr_t)ret + size), chunksize -
offset) == NULL) { offset) == NULL) {
@ -152,13 +202,13 @@ chunk_alloc_mmap(size_t size, size_t alignment, bool *zero)
* reliable-but-expensive method. * reliable-but-expensive method.
*/ */
pages_unmap(ret, size); pages_unmap(ret, size);
return (chunk_alloc_mmap_slow(size, alignment, true, return (chunk_alloc_mmap_slow(size, alignment, zero));
zero));
} else { } else {
/* Clean up unneeded leading space. */ /* Clean up unneeded leading space. */
pages_unmap(ret, chunksize - offset); pages_unmap(ret, chunksize - offset);
ret = (void *)((uintptr_t)ret + (chunksize - offset)); ret = (void *)((uintptr_t)ret + (chunksize - offset));
} }
#endif
} }
assert(ret != NULL); assert(ret != NULL);

View File

@ -52,7 +52,19 @@ static bool malloc_initializer = NO_INITIALIZER;
#endif #endif
/* Used to avoid initialization races. */ /* Used to avoid initialization races. */
#ifdef _WIN32
static malloc_mutex_t init_lock;
JEMALLOC_ATTR(constructor)
static void
init_init_lock()
{
malloc_mutex_init(&init_lock);
}
#else
static malloc_mutex_t init_lock = MALLOC_MUTEX_INITIALIZER; static malloc_mutex_t init_lock = MALLOC_MUTEX_INITIALIZER;
#endif
typedef struct { typedef struct {
void *p; /* Input pointer (as in realloc(p, s)). */ void *p; /* Input pointer (as in realloc(p, s)). */
@ -229,11 +241,17 @@ malloc_ncpus(void)
unsigned ret; unsigned ret;
long result; long result;
#ifdef _WIN32
SYSTEM_INFO si;
GetSystemInfo(&si);
result = si.dwNumberOfProcessors;
#else
result = sysconf(_SC_NPROCESSORS_ONLN); result = sysconf(_SC_NPROCESSORS_ONLN);
if (result == -1) { if (result == -1) {
/* Error. */ /* Error. */
ret = 1; ret = 1;
} }
#endif
ret = (unsigned)result; ret = (unsigned)result;
return (ret); return (ret);
@ -369,6 +387,7 @@ malloc_conf_init(void)
} }
break; break;
case 1: { case 1: {
#ifndef _WIN32
int linklen; int linklen;
const char *linkname = const char *linkname =
# ifdef JEMALLOC_PREFIX # ifdef JEMALLOC_PREFIX
@ -386,7 +405,9 @@ malloc_conf_init(void)
*/ */
buf[linklen] = '\0'; buf[linklen] = '\0';
opts = buf; opts = buf;
} else { } else
#endif
{
/* No configuration specified. */ /* No configuration specified. */
buf[0] = '\0'; buf[0] = '\0';
opts = buf; opts = buf;
@ -610,7 +631,8 @@ malloc_init_hard(void)
malloc_conf_init(); malloc_conf_init();
#if (!defined(JEMALLOC_MUTEX_INIT_CB) && !defined(JEMALLOC_ZONE)) #if (!defined(JEMALLOC_MUTEX_INIT_CB) && !defined(JEMALLOC_ZONE) \
&& !defined(_WIN32))
/* Register fork handlers. */ /* Register fork handlers. */
if (pthread_atfork(jemalloc_prefork, jemalloc_postfork_parent, if (pthread_atfork(jemalloc_prefork, jemalloc_postfork_parent,
jemalloc_postfork_child) != 0) { jemalloc_postfork_child) != 0) {

View File

@ -1,10 +1,14 @@
#define JEMALLOC_MUTEX_C_ #define JEMALLOC_MUTEX_C_
#include "jemalloc/internal/jemalloc_internal.h" #include "jemalloc/internal/jemalloc_internal.h"
#ifdef JEMALLOC_LAZY_LOCK #if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32)
#include <dlfcn.h> #include <dlfcn.h>
#endif #endif
#ifndef _CRT_SPINCOUNT
#define _CRT_SPINCOUNT 4000
#endif
/******************************************************************************/ /******************************************************************************/
/* Data. */ /* Data. */
@ -16,7 +20,7 @@ static bool postpone_init = true;
static malloc_mutex_t *postponed_mutexes = NULL; static malloc_mutex_t *postponed_mutexes = NULL;
#endif #endif
#ifdef JEMALLOC_LAZY_LOCK #if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32)
static void pthread_create_once(void); static void pthread_create_once(void);
#endif #endif
@ -26,7 +30,7 @@ static void pthread_create_once(void);
* process goes multi-threaded. * process goes multi-threaded.
*/ */
#ifdef JEMALLOC_LAZY_LOCK #if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32)
static int (*pthread_create_fptr)(pthread_t *__restrict, const pthread_attr_t *, static int (*pthread_create_fptr)(pthread_t *__restrict, const pthread_attr_t *,
void *(*)(void *), void *__restrict); void *(*)(void *), void *__restrict);
@ -68,7 +72,11 @@ int _pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex,
bool bool
malloc_mutex_init(malloc_mutex_t *mutex) malloc_mutex_init(malloc_mutex_t *mutex)
{ {
#ifdef JEMALLOC_OSSPIN #ifdef _WIN32
if (!InitializeCriticalSectionAndSpinCount(&mutex->lock,
_CRT_SPINCOUNT))
return (true);
#elif (defined(JEMALLOC_OSSPIN))
mutex->lock = 0; mutex->lock = 0;
#elif (defined(JEMALLOC_MUTEX_INIT_CB)) #elif (defined(JEMALLOC_MUTEX_INIT_CB))
if (postpone_init) { if (postpone_init) {

View File

@ -31,7 +31,7 @@ malloc_tsd_no_cleanup(void *arg)
not_reached(); not_reached();
} }
#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP #if defined(JEMALLOC_MALLOC_THREAD_CLEANUP) || defined(_WIN32)
JEMALLOC_ATTR(visibility("default")) JEMALLOC_ATTR(visibility("default"))
void void
_malloc_thread_cleanup(void) _malloc_thread_cleanup(void)
@ -70,3 +70,28 @@ malloc_tsd_boot(void)
ncleanups = 0; ncleanups = 0;
} }
#ifdef _WIN32
static BOOL WINAPI
_tls_callback(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason) {
#ifdef JEMALLOC_LAZY_LOCK
case DLL_THREAD_ATTACH:
isthreaded = true;
break;
#endif
case DLL_THREAD_DETACH:
_malloc_thread_cleanup();
break;
default:
break;
}
return (true);
}
JEMALLOC_ATTR(section(".CRT$XLY")) JEMALLOC_ATTR(used)
static const BOOL (WINAPI *tls_callback)(HINSTANCE hinstDLL,
DWORD fdwReason, LPVOID lpvReserved) = _tls_callback;
#endif

View File

@ -67,7 +67,12 @@ void (*je_malloc_message)(void *, const char *s)
int int
buferror(int errnum, char *buf, size_t buflen) buferror(int errnum, char *buf, size_t buflen)
{ {
#ifdef _GNU_SOURCE
#ifdef _WIN32
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
(LPSTR)buf, buflen, NULL);
return (0);
#elif defined(_GNU_SOURCE)
char *b = strerror_r(errno, buf, buflen); char *b = strerror_r(errno, buf, buflen);
if (b != buf) { if (b != buf) {
strncpy(buf, b, buflen); strncpy(buf, b, buflen);

View File

@ -7,6 +7,29 @@
#include "jemalloc/internal/jemalloc_internal.h" #include "jemalloc/internal/jemalloc_internal.h"
/* Abstraction layer for threading in tests */ /* Abstraction layer for threading in tests */
#ifdef _WIN32
#include <windows.h>
typedef HANDLE je_thread_t;
void
je_thread_create(je_thread_t *thread, void *(*proc)(void *), void *arg)
{
LPTHREAD_START_ROUTINE routine = (LPTHREAD_START_ROUTINE)proc;
*thread = CreateThread(NULL, 0, routine, arg, 0, NULL);
if (*thread == NULL) {
malloc_printf("Error in CreateThread()\n");
exit(1);
}
}
void
je_thread_join(je_thread_t thread, void **ret)
{
WaitForSingleObject(thread, INFINITE);
}
#else
#include <pthread.h> #include <pthread.h>
typedef pthread_t je_thread_t; typedef pthread_t je_thread_t;
@ -27,3 +50,4 @@ je_thread_join(je_thread_t thread, void **ret)
pthread_join(thread, ret); pthread_join(thread, ret);
} }
#endif

View File

@ -19,9 +19,15 @@ main(void)
/* Get page size. */ /* Get page size. */
{ {
#ifdef _WIN32
SYSTEM_INFO si;
GetSystemInfo(&si);
pagesize = (size_t)si.dwPageSize;
#else
long result = sysconf(_SC_PAGESIZE); long result = sysconf(_SC_PAGESIZE);
assert(result != -1); assert(result != -1);
pagesize = (size_t)result; pagesize = (size_t)result;
#endif
} }
r = allocm(&p, &sz, 42, 0); r = allocm(&p, &sz, 42, 0);