Bug 446090: Fix assertions in jemalloc, r=pavlov
authorJason Evans <jasone@canonware.com>
Fri, 25 Jul 2008 14:52:27 -0700
changeset 16217 dfaa3fa1c9b109576bbff59b6736f9a12d7e726f
parent 16216 2f5781fc6eeb97428e81121aecec81e99a2cb5c8
child 16218 d6bbea319540609e528d103a8826f027c07ef66b
push id856
push userjasone@canonware.com
push dateFri, 25 Jul 2008 21:54:35 +0000
treeherdermozilla-central@d6bbea319540 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspavlov
bugs446090
milestone1.9.1a2pre
Bug 446090: Fix assertions in jemalloc, r=pavlov Create a custom assert() implementation in order to avoid recursive deadlock. Enable assertions on Windows (for debug builds).
memory/jemalloc/jemalloc.c
--- a/memory/jemalloc/jemalloc.c
+++ b/memory/jemalloc/jemalloc.c
@@ -124,17 +124,19 @@
     * inline functions.
     */
 #  define MALLOC_DEBUG
 
    /* Memory filling (junk/zero). */
 #  define MALLOC_FILL
 
    /* Allocation tracing. */
-#  define MALLOC_UTRACE
+#  ifndef MOZ_MEMORY_WINDOWS
+#    define MALLOC_UTRACE
+#  endif
 
    /* Support optional abort() on OOM. */
 #  define MALLOC_XMALLOC
 
    /* Support SYSV semantics. */
 #  define MALLOC_SYSV
 #endif
 
@@ -207,17 +209,16 @@
 
 #define	false FALSE
 #define	true TRUE
 #define	inline __inline
 #define	SIZE_T_MAX SIZE_MAX
 #define	STDERR_FILENO 2
 #define	PATH_MAX MAX_PATH
 #define	vsnprintf _vsnprintf
-#define	assert(f) /* we can't assert in the CRT */
 
 static unsigned long tlsIndex = 0xffffffff;
 
 #define	__thread
 #define	_pthread_self() __threadid()
 #define	issetugid() 0
 
 /* use MSVC intrinsics */
@@ -340,29 +341,16 @@ typedef long ssize_t;
 #include "jemalloc.h"
 
 #ifdef MOZ_MEMORY_DARWIN
 static const bool __isthreaded = true;
 #endif
 
 #define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
 
-#ifdef MALLOC_DEBUG
-#  ifdef NDEBUG
-#    undef NDEBUG
-#  endif
-#else
-#  ifndef NDEBUG
-#    define NDEBUG
-#  endif
-#endif
-#ifndef MOZ_MEMORY_WINDOWS
-#include <assert.h>
-#endif
-
 #include "qr.h"
 #include "ql.h"
 #ifdef MOZ_MEMORY_WINDOWS
    /* MSVC++ does not support C99 variable-length arrays. */
 #  define RB_NO_C99_VARARRAYS
 #endif
 #include "rb.h"
 
@@ -1157,28 +1145,28 @@ typedef struct {
 #define	UTRACE(a, b, c)
 #endif
 
 /******************************************************************************/
 /*
  * Begin function prototypes for non-inline static functions.
  */
 
+static char	*umax2s(uintmax_t x, char *s);
 static bool	malloc_mutex_init(malloc_mutex_t *mutex);
 static bool	malloc_spin_init(malloc_spinlock_t *lock);
 static void	wrtmessage(const char *p1, const char *p2, const char *p3,
 		const char *p4);
 #ifdef MALLOC_STATS
 #ifdef MOZ_MEMORY_DARWIN
 /* Avoid namespace collision with OS X's malloc APIs. */
 #define malloc_printf moz_malloc_printf
 #endif
 static void	malloc_printf(const char *format, ...);
 #endif
-static char	*umax2s(uintmax_t x, char *s);
 static bool	base_pages_alloc_mmap(size_t minsize);
 static bool	base_pages_alloc(size_t minsize);
 static void	*base_alloc(size_t size);
 static void	*base_calloc(size_t number, size_t size);
 static extent_node_t *base_node_alloc(void);
 static void	base_node_dealloc(extent_node_t *node);
 static reserve_reg_t *base_reserve_reg_alloc(void);
 static void	base_reserve_reg_dealloc(reserve_reg_t *reg);
@@ -1249,16 +1237,71 @@ static void	reserve_shrink(void);
 static uint64_t	reserve_notify(reserve_cnd_t cnd, size_t size, uint64_t seq);
 static uint64_t	reserve_crit(size_t size, const char *fname, uint64_t seq);
 static void	reserve_fail(size_t size, const char *fname);
 
 /*
  * End function prototypes.
  */
 /******************************************************************************/
+
+/*
+ * umax2s() provides minimal integer printing functionality, which is
+ * especially useful for situations where allocation in vsnprintf() calls would
+ * potentially cause deadlock.
+ */
+#define	UMAX2S_BUFSIZE	21
+static char *
+umax2s(uintmax_t x, char *s)
+{
+	unsigned i;
+
+	i = UMAX2S_BUFSIZE - 1;
+	s[i] = '\0';
+	do {
+		i--;
+		s[i] = "0123456789"[x % 10];
+		x /= 10;
+	} while (x > 0);
+
+	return (&s[i]);
+}
+
+static void
+wrtmessage(const char *p1, const char *p2, const char *p3, const char *p4)
+{
+#if defined(MOZ_MEMORY) && !defined(MOZ_MEMORY_WINDOWS)
+#define	_write	write
+#endif
+	_write(STDERR_FILENO, p1, (unsigned int) strlen(p1));
+	_write(STDERR_FILENO, p2, (unsigned int) strlen(p2));
+	_write(STDERR_FILENO, p3, (unsigned int) strlen(p3));
+	_write(STDERR_FILENO, p4, (unsigned int) strlen(p4));
+}
+
+#define _malloc_message malloc_message
+
+void	(*_malloc_message)(const char *p1, const char *p2, const char *p3,
+	    const char *p4) = wrtmessage;
+
+#ifdef MALLOC_DEBUG
+#  define assert(e) do {						\
+	if (!(e)) {							\
+		char line_buf[UMAX2S_BUFSIZE];				\
+		_malloc_message(__FILE__, ":", umax2s(__LINE__,		\
+		    line_buf), ": Failed assertion: ");			\
+		_malloc_message("\"", #e, "\"\n", "");			\
+		abort();						\
+	}								\
+} while (0)
+#else
+#define assert(e)
+#endif
+
+/******************************************************************************/
 /*
  * Begin mutex.  We can't use normal pthread mutexes in all places, because
  * they require malloc()ed memory, which causes bootstrapping issues in some
  * cases.
  */
 
 static bool
 malloc_mutex_init(malloc_mutex_t *mutex)
@@ -1600,33 +1643,16 @@ utrace(const void *addr, size_t len)
 
 static inline const char *
 _getprogname(void)
 {
 
 	return ("<jemalloc>");
 }
 
-static void
-wrtmessage(const char *p1, const char *p2, const char *p3, const char *p4)
-{
-#if defined(MOZ_MEMORY) && !defined(MOZ_MEMORY_WINDOWS)
-#define	_write	write
-#endif
-	_write(STDERR_FILENO, p1, (unsigned int) strlen(p1));
-	_write(STDERR_FILENO, p2, (unsigned int) strlen(p2));
-	_write(STDERR_FILENO, p3, (unsigned int) strlen(p3));
-	_write(STDERR_FILENO, p4, (unsigned int) strlen(p4));
-}
-
-#define _malloc_message malloc_message
-
-void	(*_malloc_message)(const char *p1, const char *p2, const char *p3,
-	    const char *p4) = wrtmessage;
-
 #ifdef MALLOC_STATS
 /*
  * Print to stderr in such a way as to (hopefully) avoid memory allocation.
  */
 static void
 malloc_printf(const char *format, ...)
 {
 	char buf[4096];
@@ -1634,42 +1660,16 @@ malloc_printf(const char *format, ...)
 
 	va_start(ap, format);
 	vsnprintf(buf, sizeof(buf), format, ap);
 	va_end(ap);
 	_malloc_message(buf, "", "", "");
 }
 #endif
 
-/*
- * We don't want to depend on vsnprintf() for production builds, since that can
- * cause unnecessary bloat for static binaries.  umax2s() provides minimal
- * integer printing functionality, so that malloc_printf() use can be limited to
- * MALLOC_STATS code.
- */
-#define	UMAX2S_BUFSIZE	21
-static char *
-umax2s(uintmax_t x, char *s)
-{
-	unsigned i;
-
-	/* Make sure UMAX2S_BUFSIZE is large enough. */
-	assert(sizeof(uintmax_t) <= 8);
-
-	i = UMAX2S_BUFSIZE - 1;
-	s[i] = '\0';
-	do {
-		i--;
-		s[i] = "0123456789"[x % 10];
-		x /= 10;
-	} while (x > 0);
-
-	return (&s[i]);
-}
-
 /******************************************************************************/
 
 #ifdef MALLOC_DECOMMIT
 static inline void
 pages_decommit(void *addr, size_t size)
 {
 
 #ifdef MOZ_MEMORY_WINDOWS