[PATCH 7/7] Add support for MSVC
Mike Hommey
mh+jemalloc at glandium.org
Mon Apr 30 03:38:31 PDT 2012
From: Mike Hommey <mh at glandium.org>
Tested with MSVC 8 32 and 64 bits.
---
Makefile.in | 21 +++++++--
configure.ac | 54 ++++++++++++++++++++--
include/compat/stdbool.h | 16 +++++++
include/compat/strings.h | 22 +++++++++
include/jemalloc/internal/atomic.h | 24 ++++++++++
include/jemalloc/internal/jemalloc_internal.h.in | 23 +++++++--
include/jemalloc/jemalloc_defs.h.in | 10 ++++
src/jemalloc.c | 11 ++++-
src/tsd.c | 8 ++++
9 files changed, 173 insertions(+), 16 deletions(-)
create mode 100644 include/compat/stdbool.h
create mode 100644 include/compat/strings.h
diff --git a/Makefile.in b/Makefile.in
index a351a1f..08541a7 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -26,9 +26,11 @@ abs_objroot := @abs_objroot@
CPPFLAGS := @CPPFLAGS@ -I$(srcroot)include -I$(objroot)include
CFLAGS := @CFLAGS@
LDFLAGS := @LDFLAGS@
+EXTRA_LDFLAGS := @EXTRA_LDFLAGS@
LIBS := @LIBS@
RPATH_EXTRA := @RPATH_EXTRA@
SO := @so@
+IMPORTLIB := @importlib@
O := @o@
A := @a@
EXE := @exe@
@@ -49,6 +51,9 @@ enable_experimental := @enable_experimental@
DSO_LDFLAGS = @DSO_LDFLAGS@
SOREV = @SOREV@
PIC_CFLAGS = @PIC_CFLAGS@
+CTARGET = @CTARGET@
+LDTARGET = @LDTARGET@
+MKLIB = @MKLIB@
ifeq (macho, $(ABI))
TEST_LIBRARY_PATH := DYLD_FALLBACK_LIBRARY_PATH="$(objroot)lib"
@@ -77,9 +82,13 @@ CSRCS := $(srcroot)src/jemalloc.c $(srcroot)src/arena.c $(srcroot)src/atomic.c \
ifeq (macho, $(ABI))
CSRCS += $(srcroot)src/zone.c
endif
+ifeq ($(IMPORTLIB),$(SO))
STATIC_LIBS := $(objroot)lib/$(LIBJEMALLOC).$(A)
+endif
ifdef PIC_CFLAGS
STATIC_LIBS += $(objroot)lib/$(LIBJEMALLOC)_pic.$(A)
+else
+STATIC_LIBS += $(objroot)lib/$(LIBJEMALLOC)_s.$(A)
endif
DSOS := $(objroot)lib/$(LIBJEMALLOC).$(SOREV)
ifneq ($(SOREV),$(SO))
@@ -129,6 +138,9 @@ $(CPICOBJS): $(objroot)src/%.pic.$(O): $(srcroot)src/%.c
$(CPICOBJS): CFLAGS += $(PIC_CFLAGS)
$(CTESTOBJS): $(objroot)test/%.$(O): $(srcroot)test/%.c
$(CTESTOBJS): CPPFLAGS += -I$(objroot)test
+ifneq ($(IMPORTLIB),$(SO))
+$(COBJS): CPPFLAGS += -DDLLEXPORT
+endif
# Dependencies
HEADER_DIRS = $(srcroot)include/jemalloc/internal \
@@ -139,7 +151,7 @@ $(CTESTOBJS): $(objroot)test/jemalloc_test.h
$(COBJS) $(CPICOBJS) $(CTESTOBJS): %.$(O):
@mkdir -p $(@D)
- $(CC) $(CFLAGS) -c $(CPPFLAGS) -o $@ $<
+ $(CC) $(CFLAGS) -c $(CPPFLAGS) $(CTARGET) $<
ifneq ($(SOREV),$(SO))
%.$(SO) : %.$(SOREV)
@@ -149,20 +161,21 @@ endif
$(objroot)lib/$(LIBJEMALLOC).$(SOREV) : $(if $(PIC_CFLAGS),$(CPICOBJS),$(COBJS))
@mkdir -p $(@D)
- $(CC) $(DSO_LDFLAGS) $(call RPATH,$(RPATH_EXTRA)) -o $@ $+ $(LDFLAGS) $(LIBS)
+ $(CC) $(DSO_LDFLAGS) $(call RPATH,$(RPATH_EXTRA)) $(LDTARGET) $+ $(LDFLAGS) $(LIBS) $(EXTRA_LDFLAGS)
$(objroot)lib/$(LIBJEMALLOC)_pic.$(A) : $(CPICOBJS)
$(objroot)lib/$(LIBJEMALLOC).$(A) : $(COBJS)
+$(objroot)lib/$(LIBJEMALLOC)_s.$(A) : $(COBJS)
$(STATIC_LIBS):
@mkdir -p $(@D)
- ar crus $@ $+
+ $(MKLIB) $+
$(objroot)test/bitmap$(EXE): $(objroot)src/bitmap.$(O)
$(objroot)test/%$(EXE): $(objroot)test/%.$(O) $(objroot)src/util.$(O) $(DSOS)
@mkdir -p $(@D)
- $(CC) -o $@ $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) -L$(objroot)lib -ljemalloc$(install_suffix) $(filter -lpthread,$(LIBS))
+ $(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) $(filter -lpthread,$(LIBS)) $(EXTRA_LDFLAGS)
build_lib_shared: $(DSOS)
build_lib_static: $(STATIC_LIBS)
diff --git a/configure.ac b/configure.ac
index 6e74238..500e21c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -111,6 +111,19 @@ dnl If CFLAGS isn't defined, set CFLAGS to something reasonable. Otherwise,
dnl just prevent autoconf from molesting CFLAGS.
CFLAGS=$CFLAGS
AC_PROG_CC
+if test "x$GCC" != "xyes" ; then
+ AC_CACHE_CHECK([whether compiler is MSVC],
+ [je_cv_msvc],
+ [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
+ [
+#ifndef _MSC_VER
+ int fail[-1];
+#endif
+])],
+ [je_cv_msvc=yes],
+ [je_cv_msvc=no])])
+fi
+
if test "x$CFLAGS" = "x" ; then
no_CFLAGS="yes"
if test "x$GCC" = "xyes" ; then
@@ -118,6 +131,12 @@ if test "x$CFLAGS" = "x" ; then
JE_CFLAGS_APPEND([-Wall])
JE_CFLAGS_APPEND([-pipe])
JE_CFLAGS_APPEND([-g3])
+ elif test "x$je_cv_msvc" = "xyes" ; then
+ CC="$CC -nologo"
+ JE_CFLAGS_APPEND([-Zi])
+ JE_CFLAGS_APPEND([-MT])
+ JE_CFLAGS_APPEND([-W3])
+ CPPFLAGS="$CPPFLAGS -I${srcroot}/include/compat"
fi
fi
dnl Append EXTRA_CFLAGS to CFLAGS, if defined.
@@ -195,6 +214,7 @@ AC_DEFINE_UNQUOTED([CPU_SPINWAIT], [$CPU_SPINWAIT])
LD_PRELOAD_VAR="LD_PRELOAD"
so="so"
+importlib="${so}"
o="$ac_objext"
a="a"
exe="$ac_exeext"
@@ -203,9 +223,10 @@ DSO_LDFLAGS='-shared -Wl,-soname,$(@F)'
RPATH='-Wl,-rpath,$(1)'
SOREV="${so}.${rev}"
PIC_CFLAGS='-fPIC -DPIC'
-
-dnl Heap profiling uses the log(3) function.
-LIBS="$LIBS -lm"
+CTARGET='-o $@'
+LDTARGET='-o $@'
+EXTRA_LDFLAGS=
+MKLIB='ar crus $@'
dnl Platform-specific settings. abi and RPATH can probably be determined
dnl programmatically, but doing so is error-prone, which makes it generally
@@ -223,6 +244,7 @@ case "${host}" in
RPATH=""
LD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
so="dylib"
+ importlib="${so}"
force_tls="0"
DSO_LDFLAGS='-shared -Wl,-dylib_install_name,$(@F)'
SOREV="${rev}.${so}"
@@ -278,7 +300,17 @@ case "${host}" in
force_tls="0"
RPATH=""
so="dll"
- DSO_LDFLAGS="-shared"
+ if test "x$je_cv_msvc" = "xyes" ; then
+ importlib="lib"
+ DSO_LDFLAGS="-LD"
+ EXTRA_LDFLAGS="-link -DEBUG"
+ CTARGET='-Fo$@'
+ LDTARGET='-Fe$@'
+ MKLIB='lib -nologo -out:$@'
+ else
+ importlib="${so}"
+ DSO_LDFLAGS="-shared"
+ fi
a="lib"
libprefix=""
SOREV="${so}"
@@ -293,13 +325,23 @@ AC_SUBST([abi])
AC_SUBST([RPATH])
AC_SUBST([LD_PRELOAD_VAR])
AC_SUBST([so])
+AC_SUBST([importlib])
AC_SUBST([o])
AC_SUBST([a])
AC_SUBST([exe])
AC_SUBST([libprefix])
AC_SUBST([DSO_LDFLAGS])
+AC_SUBST([EXTRA_LDFLAGS])
AC_SUBST([SOREV])
AC_SUBST([PIC_CFLAGS])
+AC_SUBST([CTARGET])
+AC_SUBST([LDTARGET])
+AC_SUBST([MKLIB])
+
+if test "x$abi" != "xpecoff"; then
+ dnl Heap profiling uses the log(3) function.
+ LIBS="$LIBS -lm"
+fi
JE_COMPILABLE([__attribute__ syntax],
[static __attribute__((unused)) void foo(void){}],
@@ -530,6 +572,8 @@ if test "x$enable_debug" = "x0" -a "x$no_CFLAGS" = "xyes" ; then
if test "x$GCC" = "xyes" ; then
JE_CFLAGS_APPEND([-O3])
JE_CFLAGS_APPEND([-funroll-loops])
+ elif test "x$je_cv_msvc" = "xyes" ; then
+ JE_CFLAGS_APPEND([-O2])
else
JE_CFLAGS_APPEND([-O])
fi
@@ -833,11 +877,11 @@ AC_CACHE_CHECK([STATIC_PAGE_SHIFT],
[je_cv_static_page_shift],
AC_RUN_IFELSE([AC_LANG_PROGRAM(
[[
+#include <strings.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
-#include <strings.h>
#endif
#include <stdio.h>
]],
diff --git a/include/compat/stdbool.h b/include/compat/stdbool.h
new file mode 100644
index 0000000..da9ee8b
--- /dev/null
+++ b/include/compat/stdbool.h
@@ -0,0 +1,16 @@
+#ifndef stdbool_h
+#define stdbool_h
+
+#include <wtypes.h>
+
+/* MSVC doesn't define _Bool or bool in C, but does have BOOL */
+/* Note this doesn't pass autoconf's test because (bool) 0.5 != true */
+typedef BOOL _Bool;
+
+#define bool _Bool
+#define true 1
+#define false 0
+
+#define __bool_true_false_are_defined 1
+
+#endif /* stdbool_h */
diff --git a/include/compat/strings.h b/include/compat/strings.h
new file mode 100644
index 0000000..6ad8039
--- /dev/null
+++ b/include/compat/strings.h
@@ -0,0 +1,22 @@
+#ifndef strings_h
+#define strings_h
+
+/* MSVC doesn't define ffs/ffsl. This dummy strings.h header is provided
+ * for both */
+#include <intrin.h>
+#pragma intrinsic(_BitScanForward)
+static __forceinline int ffsl(long x)
+{
+ unsigned long i;
+
+ if (_BitScanForward(&i, x))
+ return (i + 1);
+ return (0);
+}
+
+static __forceinline int ffs(int x)
+{
+ return ffsl(x);
+}
+
+#endif
diff --git a/include/jemalloc/internal/atomic.h b/include/jemalloc/internal/atomic.h
index 016c472..4b6f623 100644
--- a/include/jemalloc/internal/atomic.h
+++ b/include/jemalloc/internal/atomic.h
@@ -47,6 +47,18 @@ atomic_sub_uint64(uint64_t *p, uint64_t x)
return (__sync_sub_and_fetch(p, x));
}
+#elif (defined(_MSC_VER))
+JEMALLOC_INLINE uint64_t
+atomic_add_uint64(uint64_t *p, uint64_t x)
+{
+ return InterlockedExchangeAdd64(p, x);
+}
+
+JEMALLOC_INLINE uint64_t
+atomic_sub_uint64(uint64_t *p, uint64_t x)
+{
+ return InterlockedExchangeAdd64(p, -x);
+}
#elif (defined(JEMALLOC_OSATOMIC))
JEMALLOC_INLINE uint64_t
atomic_add_uint64(uint64_t *p, uint64_t x)
@@ -145,6 +157,18 @@ atomic_sub_uint32(uint32_t *p, uint32_t x)
return (__sync_sub_and_fetch(p, x));
}
+#elif (defined(_MSC_VER))
+JEMALLOC_INLINE uint32_t
+atomic_add_uint32(uint32_t *p, uint32_t x)
+{
+ return InterlockedExchangeAdd(p, x);
+}
+
+JEMALLOC_INLINE uint32_t
+atomic_sub_uint32(uint32_t *p, uint32_t x)
+{
+ return InterlockedExchangeAdd(p, -x);
+}
#elif (defined(JEMALLOC_OSATOMIC))
JEMALLOC_INLINE uint32_t
atomic_add_uint32(uint32_t *p, uint32_t x)
diff --git a/include/jemalloc/internal/jemalloc_internal.h.in b/include/jemalloc/internal/jemalloc_internal.h.in
index d4c4b4c..97c1794 100644
--- a/include/jemalloc/internal/jemalloc_internal.h.in
+++ b/include/jemalloc/internal/jemalloc_internal.h.in
@@ -1,6 +1,5 @@
#ifndef JEMALLOC_INTERNAL_H
#define JEMALLOC_INTERNAL_H
-#include <sys/param.h>
#include <math.h>
#ifdef _WIN32
# include <windows.h>
@@ -13,6 +12,7 @@
# undef ERANGE
# define ERANGE ERROR_INVALID_DATA
#else
+# include <sys/param.h>
# include <sys/mman.h>
# include <sys/syscall.h>
# if !defined(SYS_write) && defined(__NR_write)
@@ -41,7 +41,17 @@
#include <string.h>
#include <strings.h>
#include <ctype.h>
-#include <unistd.h>
+#ifdef _MSC_VER
+# include <io.h>
+typedef intptr_t ssize_t;
+# define PATH_MAX 1024
+# define STDERR_FILENO 2
+# define __func__ __FUNCTION__
+/* Disable warnings about deprecated system functions */
+# pragma warning(disable: 4996)
+#else
+# include <unistd.h>
+#endif
#include <fcntl.h>
#define JEMALLOC_NO_DEMANGLE
@@ -221,6 +231,9 @@ static const bool config_ivsalloc =
#else
# define JEMALLOC_ENABLE_INLINE
# define JEMALLOC_INLINE static inline
+# ifdef _MSC_VER
+# define inline _inline
+# endif
#endif
/* Smallest size class to support. */
@@ -232,7 +245,7 @@ static const bool config_ivsalloc =
* classes).
*/
#ifndef LG_QUANTUM
-# ifdef __i386__
+# if (defined(__i386__) || defined(_M_IX86))
# define LG_QUANTUM 4
# endif
# ifdef __ia64__
@@ -244,7 +257,7 @@ static const bool config_ivsalloc =
# ifdef __sparc64__
# define LG_QUANTUM 4
# endif
-# if (defined(__amd64__) || defined(__x86_64__))
+# if (defined(__amd64__) || defined(__x86_64__) || defined(_M_X64))
# define LG_QUANTUM 4
# endif
# ifdef __arm__
@@ -296,7 +309,7 @@ static const bool config_ivsalloc =
* In addition, this controls the spacing of cacheline-spaced size classes.
*/
#define LG_CACHELINE 6
-#define CACHELINE ((size_t)(1U << LG_CACHELINE))
+#define CACHELINE 64
#define CACHELINE_MASK (CACHELINE - 1)
/* Return the smallest cacheline multiple that is >= s. */
diff --git a/include/jemalloc/jemalloc_defs.h.in b/include/jemalloc/jemalloc_defs.h.in
index 3e1f047..f110ed3 100644
--- a/include/jemalloc/jemalloc_defs.h.in
+++ b/include/jemalloc/jemalloc_defs.h.in
@@ -109,6 +109,16 @@
# define JEMALLOC_ALIGNED(s) JEMALLOC_ATTR(aligned(s))
# define JEMALLOC_SECTION(s) JEMALLOC_ATTR(section(s))
# define JEMALLOC_NOINLINE JEMALLOC_ATTR(noinline)
+#elif _MSC_VER
+# define JEMALLOC_ATTR(s)
+#ifdef DLLEXPORT
+# define EXPORT __declspec(dllexport)
+#else
+# define EXPORT __declspec(dllimport)
+#endif
+# define JEMALLOC_ALIGNED(s) __declspec(align(s))
+# define JEMALLOC_SECTION(s) __declspec(allocate(s))
+# define JEMALLOC_NOINLINE __declspec(noinline)
#else
# define JEMALLOC_ATTR(s)
# define EXPORT
diff --git a/src/jemalloc.c b/src/jemalloc.c
index fa24b05..40c775d 100644
--- a/src/jemalloc.c
+++ b/src/jemalloc.c
@@ -56,12 +56,19 @@ static bool malloc_initializer = NO_INITIALIZER;
static malloc_mutex_t init_lock;
JEMALLOC_ATTR(constructor)
-static void
-init_init_lock()
+static void WINAPI
+_init_init_lock(void)
{
malloc_mutex_init(&init_lock);
}
+
+#ifdef _MSC_VER
+# pragma section(".CRT$XCU", read)
+JEMALLOC_SECTION(".CRT$XCU") JEMALLOC_ATTR(used)
+static const void (WINAPI *init_init_lock)(void) = _init_init_lock;
+#endif
+
#else
static malloc_mutex_t init_lock = MALLOC_MUTEX_INITIALIZER;
#endif
diff --git a/src/tsd.c b/src/tsd.c
index cee57c9..84492b3 100644
--- a/src/tsd.c
+++ b/src/tsd.c
@@ -93,6 +93,14 @@ _tls_callback(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
return (true);
}
+#ifdef _MSC_VER
+# ifdef _M_IX86
+# pragma comment(linker, "/INCLUDE:__tls_used")
+# else
+# pragma comment(linker, "/INCLUDE:_tls_used")
+# endif
+# pragma section(".CRT$XLY",long,read)
+#endif
JEMALLOC_SECTION(".CRT$XLY") JEMALLOC_ATTR(used)
static const BOOL (WINAPI *tls_callback)(HINSTANCE hinstDLL,
DWORD fdwReason, LPVOID lpvReserved) = _tls_callback;
--
1.7.10
More information about the jemalloc-discuss
mailing list