Add support for MSVC
Tested with MSVC 8 32 and 64 bits.
diff --git a/Makefile.in b/Makefile.in
index 7685f15..94f4869 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -26,9 +26,11 @@
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 @@
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 @@
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))
@@ -136,10 +145,13 @@
$(CPICOBJS): CFLAGS += $(PIC_CFLAGS)
$(CTESTOBJS): $(objroot)test/%.$(O): $(srcroot)test/%.c
$(CTESTOBJS): CPPFLAGS += -I$(objroot)test
+ifneq ($(IMPORTLIB),$(SO))
+$(COBJS): CPPFLAGS += -DDLLEXPORT
+endif
$(COBJS) $(CPICOBJS) $(CTESTOBJS): %.$(O):
@mkdir -p $(@D)
- $(CC) $(CFLAGS) -c $(CPPFLAGS) -o $@ $<
+ $(CC) $(CFLAGS) -c $(CPPFLAGS) $(CTARGET) $<
@$(CC) -MM $(CPPFLAGS) -MT $@ -o $(@:%.$(O)=%.d) $<
ifneq ($(SOREV),$(SO))
@@ -150,20 +162,21 @@
$(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..50eaae6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -111,6 +111,19 @@
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 @@
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/msvc_compat"
fi
fi
dnl Append EXTRA_CFLAGS to CFLAGS, if defined.
@@ -195,6 +214,7 @@
LD_PRELOAD_VAR="LD_PRELOAD"
so="so"
+importlib="${so}"
o="$ac_objext"
a="a"
exe="$ac_exeext"
@@ -203,9 +223,10 @@
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 @@
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 @@
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([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$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 @@
[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/jemalloc/internal/atomic.h b/include/jemalloc/internal/atomic.h
index 016c472..11a7b47 100644
--- a/include/jemalloc/internal/atomic.h
+++ b/include/jemalloc/internal/atomic.h
@@ -47,6 +47,20 @@
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, -((int64_t)x)));
+}
#elif (defined(JEMALLOC_OSATOMIC))
JEMALLOC_INLINE uint64_t
atomic_add_uint64(uint64_t *p, uint64_t x)
@@ -145,6 +159,20 @@
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, -((int32_t)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..1886147 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 @@
#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 @@
* classes).
*/
#ifndef LG_QUANTUM
-# ifdef __i386__
+# if (defined(__i386__) || defined(_M_IX86))
# define LG_QUANTUM 4
# endif
# ifdef __ia64__
@@ -244,7 +257,7 @@
# 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__
diff --git a/include/jemalloc/jemalloc_defs.h.in b/include/jemalloc/jemalloc_defs.h.in
index 126f6b7..e61597c 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 JEMALLOC_EXPORT
diff --git a/include/msc_compat/inttypes.h b/include/msvc_compat/inttypes.h
similarity index 100%
rename from include/msc_compat/inttypes.h
rename to include/msvc_compat/inttypes.h
diff --git a/include/msvc_compat/stdbool.h b/include/msvc_compat/stdbool.h
new file mode 100644
index 0000000..da9ee8b
--- /dev/null
+++ b/include/msvc_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/msc_compat/stdint.h b/include/msvc_compat/stdint.h
similarity index 100%
rename from include/msc_compat/stdint.h
rename to include/msvc_compat/stdint.h
diff --git a/include/msvc_compat/strings.h b/include/msvc_compat/strings.h
new file mode 100644
index 0000000..c84975b
--- /dev/null
+++ b/include/msvc_compat/strings.h
@@ -0,0 +1,23 @@
+#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/src/jemalloc.c b/src/jemalloc.c
index 2f858c3..d42e91d 100644
--- a/src/jemalloc.c
+++ b/src/jemalloc.c
@@ -56,12 +56,19 @@
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 0506c8a..00d7b45 100644
--- a/src/tsd.c
+++ b/src/tsd.c
@@ -93,6 +93,14 @@
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;