Add support for Mingw
This commit is contained in:
parent
a8f8d7540d
commit
a19e87fbad
10
Makefile.in
10
Makefile.in
@ -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
|
||||||
|
46
configure.ac
46
configure.ac
@ -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.
|
||||||
|
|
||||||
AC_CHECK_HEADERS([pthread.h], , [AC_MSG_ERROR([pthread.h is missing])])
|
if test "x$abi" != "xpecoff" ; then
|
||||||
dnl Some systems may embed pthreads functionality in libc; check for libpthread
|
AC_CHECK_HEADERS([pthread.h], , [AC_MSG_ERROR([pthread.h is missing])])
|
||||||
dnl first, but try libc too before failing.
|
dnl Some systems may embed pthreads functionality in libc; check for libpthread
|
||||||
AC_CHECK_LIB([pthread], [pthread_create], [LIBS="$LIBS -lpthread"],
|
dnl first, but try libc too before failing.
|
||||||
|
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])
|
||||||
|
@ -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>
|
||||||
#include <sys/syscall.h>
|
#ifdef _WIN32
|
||||||
#if !defined(SYS_write) && defined(__NR_write)
|
# include <windows.h>
|
||||||
#define SYS_write __NR_write
|
#else
|
||||||
|
# include <sys/mman.h>
|
||||||
|
# include <sys/syscall.h>
|
||||||
|
# if !defined(SYS_write) && defined(__NR_write)
|
||||||
|
# define SYS_write __NR_write
|
||||||
|
# endif
|
||||||
|
# include <sys/uio.h>
|
||||||
|
# include <pthread.h>
|
||||||
#endif
|
#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
|
||||||
|
@ -3,10 +3,12 @@
|
|||||||
|
|
||||||
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 {0}
|
# define MALLOC_MUTEX_INITIALIZER
|
||||||
|
#elif (defined(JEMALLOC_OSSPIN))
|
||||||
|
# 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}
|
||||||
#else
|
#else
|
||||||
# if (defined(PTHREAD_MUTEX_ADAPTIVE_NP) && \
|
# if (defined(PTHREAD_MUTEX_ADAPTIVE_NP) && \
|
||||||
defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP))
|
defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP))
|
||||||
@ -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);
|
||||||
|
@ -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) \
|
||||||
|
@ -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,55 +59,94 @@ 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 JEMALLOC_PURGE_MADVISE_DONTNEED
|
#ifdef _WIN32
|
||||||
# define JEMALLOC_MADV_PURGE MADV_DONTNEED
|
VirtualAlloc(addr, length, MEM_RESET, PAGE_READWRITE);
|
||||||
#elif defined(JEMALLOC_PURGE_MADVISE_FREE)
|
|
||||||
# define JEMALLOC_MADV_PURGE MADV_FREE
|
|
||||||
#else
|
#else
|
||||||
|
# ifdef JEMALLOC_PURGE_MADVISE_DONTNEED
|
||||||
|
# define JEMALLOC_MADV_PURGE MADV_DONTNEED
|
||||||
|
# elif defined(JEMALLOC_PURGE_MADVISE_FREE)
|
||||||
|
# define JEMALLOC_MADV_PURGE MADV_FREE
|
||||||
|
# else
|
||||||
# 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);
|
||||||
|
@ -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,13 +387,14 @@ 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
|
||||||
"/etc/"JEMALLOC_PREFIX"malloc.conf"
|
"/etc/"JEMALLOC_PREFIX"malloc.conf"
|
||||||
#else
|
# else
|
||||||
"/etc/malloc.conf"
|
"/etc/malloc.conf"
|
||||||
#endif
|
# endif
|
||||||
;
|
;
|
||||||
|
|
||||||
if ((linklen = readlink(linkname, buf,
|
if ((linklen = readlink(linkname, buf,
|
||||||
@ -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) {
|
||||||
|
16
src/mutex.c
16
src/mutex.c
@ -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) {
|
||||||
|
27
src/tsd.c
27
src/tsd.c
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user