From 9e20df163c0c608026498b8fb5beab35e8a049c6 Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Wed, 26 Feb 2014 10:19:18 -0800 Subject: [PATCH 01/17] Remove duplicate 'static' keyword. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported by İsmail Dönmez. --- test/include/test/SFMT-alti.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/include/test/SFMT-alti.h b/test/include/test/SFMT-alti.h index 2f86f67d..0005df6b 100644 --- a/test/include/test/SFMT-alti.h +++ b/test/include/test/SFMT-alti.h @@ -61,7 +61,7 @@ * @return output */ JEMALLOC_ALWAYS_INLINE -static vector unsigned int vec_recursion(vector unsigned int a, +vector unsigned int vec_recursion(vector unsigned int a, vector unsigned int b, vector unsigned int c, vector unsigned int d) { From bf543df20ccd9e2c422751908cabf073bc7f5d4b Mon Sep 17 00:00:00 2001 From: Harald Weppner Date: Mon, 17 Mar 2014 23:53:00 -0700 Subject: [PATCH 02/17] Enable profiling / leak detection in FreeBSD * Assumes procfs is mounted at /proc, cf. --- bin/pprof | 22 ++++++++++++++++++++-- src/prof.c | 8 +++++++- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/bin/pprof b/bin/pprof index 727eb437..08c9ea31 100755 --- a/bin/pprof +++ b/bin/pprof @@ -4197,8 +4197,12 @@ sub FindLibrary { # For libc libraries, the copy in /usr/lib/debug contains debugging symbols sub DebuggingLibrary { my $file = shift; - if ($file =~ m|^/| && -f "/usr/lib/debug$file") { - return "/usr/lib/debug$file"; + if ($file =~ m|^/|) { + if (-f "/usr/lib/debug$file") { + return "/usr/lib/debug$file"; + } elsif (-f "/usr/lib/debug$file.debug") { + return "/usr/lib/debug$file.debug"; + } } return undef; } @@ -4360,6 +4364,19 @@ sub ParseLibraries { $finish = HexExtend($2); $offset = $zero_offset; $lib = $3; + } + # FreeBSD 10.0 virtual memory map /proc/curproc/map as defined in + # function procfs_doprocmap (sys/fs/procfs/procfs_map.c) + # + # Example: + # 0x800600000 0x80061a000 26 0 0xfffff800035a0000 r-x 75 33 0x1004 COW NC vnode /libexec/ld-elf.s + # o.1 NCH -1 + elsif ($l =~ /^(0x$h)\s(0x$h)\s\d+\s\d+\s0x$h\sr-x\s\d+\s\d+\s0x\d+\s(COW|NCO)\s(NC|NNC)\svnode\s(\S+\.so(\.\d+)*)/) { + $start = HexExtend($1); + $finish = HexExtend($2); + $offset = $zero_offset; + $lib = FindLibrary($5); + } else { next; } @@ -4382,6 +4399,7 @@ sub ParseLibraries { } } + if($main::opt_debug) { printf STDERR "$start:$finish ($offset) $lib\n"; } push(@{$result}, [$lib, $start, $finish, $offset]); } diff --git a/src/prof.c b/src/prof.c index 1d8ccbd6..ede89a7a 100644 --- a/src/prof.c +++ b/src/prof.c @@ -11,6 +11,12 @@ #include #endif +#ifdef __FreeBSD__ +#define PROCESS_VMEM_MAP "/proc/curproc/map" +#else +#define PROCESS_VMEM_MAP "/proc/%d/maps" +#endif + /******************************************************************************/ /* Data. */ @@ -936,7 +942,7 @@ prof_dump_maps(bool propagate_err) cassert(config_prof); - malloc_snprintf(filename, sizeof(filename), "/proc/%d/maps", + malloc_snprintf(filename, sizeof(filename), PROCESS_VMEM_MAP, (int)getpid()); mfd = open(filename, O_RDONLY); if (mfd != -1) { From 4bbf8181f384d6bd8a634b22543f83e5b949b609 Mon Sep 17 00:00:00 2001 From: Harald Weppner Date: Tue, 18 Mar 2014 00:00:14 -0700 Subject: [PATCH 03/17] Consistently use debug lib(s) if present Fixes a situation where nm uses the debug lib but addr2line does not, which completely messes up the symbol lookup. --- bin/pprof | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/bin/pprof b/bin/pprof index 08c9ea31..a309943c 100755 --- a/bin/pprof +++ b/bin/pprof @@ -4607,6 +4607,12 @@ sub ExtractSymbols { my $finish = $lib->[2]; my $offset = $lib->[3]; + # Use debug library if it exists + my $debug_libname = DebuggingLibrary($libname); + if ($debug_libname) { + $libname = $debug_libname; + } + # Get list of pcs that belong in this library. my $contained = []; my ($start_pc_index, $finish_pc_index); @@ -5037,7 +5043,7 @@ sub GetProcedureBoundariesViaNm { # Tag this routine with the starting address in case the image # has multiple occurrences of this routine. We use a syntax - # that resembles template paramters that are automatically + # that resembles template parameters that are automatically # stripped out by ShortFunctionName() $this_routine .= "<$start_val>"; From 20a8c78bfe3310e0f0f72b596d4e10ca7336063b Mon Sep 17 00:00:00 2001 From: Chris Pride Date: Tue, 25 Mar 2014 22:36:05 -0700 Subject: [PATCH 04/17] Fix a crashing case where arena_chunk_init_hard returns NULL. This happens when it fails to allocate a new chunk. Which arena_chunk_alloc then passes into arena_avail_insert without any checks. This then causes a crash when arena_avail_insert tries to check chunk->ndirty. This was introduced by the refactoring of arena_chunk_alloc which previously would have returned NULL immediately after calling chunk_alloc. This is now the return from arena_chunk_init_hard so we need to check that return, and not continue if it was NULL. --- src/arena.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/arena.c b/src/arena.c index 390ab0f8..dad707b6 100644 --- a/src/arena.c +++ b/src/arena.c @@ -614,8 +614,11 @@ arena_chunk_alloc(arena_t *arena) if (arena->spare != NULL) chunk = arena_chunk_init_spare(arena); - else + else { chunk = arena_chunk_init_hard(arena); + if (chunk == NULL) + return (NULL); + } /* Insert the run into the runs_avail tree. */ arena_avail_insert(arena, chunk, map_bias, chunk_npages-map_bias, From c2dcfd8ded8162cddb143836c12d003840fdeaeb Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Fri, 28 Mar 2014 10:40:03 -0700 Subject: [PATCH 05/17] Convert ALLOCM_ARENA() test to MALLOCX_ARENA() test. --- Makefile.in | 2 +- test/integration/{ALLOCM_ARENA.c => MALLOCX_ARENA.c} | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) rename test/integration/{ALLOCM_ARENA.c => MALLOCX_ARENA.c} (88%) diff --git a/Makefile.in b/Makefile.in index 7399f277..d6b7d6ea 100644 --- a/Makefile.in +++ b/Makefile.in @@ -141,7 +141,7 @@ TESTS_INTEGRATION := $(srcroot)test/integration/aligned_alloc.c \ $(srcroot)test/integration/xallocx.c ifeq ($(enable_experimental), 1) TESTS_INTEGRATION += $(srcroot)test/integration/allocm.c \ - $(srcroot)test/integration/ALLOCM_ARENA.c \ + $(srcroot)test/integration/MALLOCX_ARENA.c \ $(srcroot)test/integration/rallocm.c endif TESTS_STRESS := diff --git a/test/integration/ALLOCM_ARENA.c b/test/integration/MALLOCX_ARENA.c similarity index 88% rename from test/integration/ALLOCM_ARENA.c rename to test/integration/MALLOCX_ARENA.c index 5bf3c4ab..71cf6f25 100644 --- a/test/integration/ALLOCM_ARENA.c +++ b/test/integration/MALLOCX_ARENA.c @@ -8,7 +8,7 @@ thd_start(void *arg) unsigned thread_ind = (unsigned)(uintptr_t)arg; unsigned arena_ind; void *p; - size_t rsz, sz; + size_t sz; sz = sizeof(arena_ind); assert_d_eq(mallctl("arenas.extend", &arena_ind, &sz, NULL, 0), 0, @@ -27,9 +27,9 @@ thd_start(void *arg) sizeof(const char *)), 0, "Error in mallctlbymib()"); } - assert_d_eq(allocm(&p, &rsz, 1, ALLOCM_ARENA(arena_ind)), - ALLOCM_SUCCESS, "Unexpected allocm() error"); - dallocm(p, 0); + p = mallocx(1, MALLOCX_ARENA(arena_ind)); + assert_ptr_not_null(p, "Unexpected mallocx() error"); + dallocx(p, 0); return (NULL); } From fbb31029a5c2f556f39e04a8781340d4ee4cf16c Mon Sep 17 00:00:00 2001 From: Max Wang Date: Thu, 27 Mar 2014 14:46:00 -0700 Subject: [PATCH 06/17] Use arena dss prec instead of default for huge allocs. Pass a dss_prec_t parameter to huge_{m,p,r}alloc instead of defaulting to the chunk dss prec. --- include/jemalloc/internal/huge.h | 8 +++--- .../jemalloc/internal/jemalloc_internal.h.in | 10 +++---- src/huge.c | 26 ++++++++++++------- src/jemalloc.c | 2 +- 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/include/jemalloc/internal/huge.h b/include/jemalloc/internal/huge.h index ddf13138..a2b9c779 100644 --- a/include/jemalloc/internal/huge.h +++ b/include/jemalloc/internal/huge.h @@ -17,18 +17,20 @@ extern size_t huge_allocated; /* Protects chunk-related data structures. */ extern malloc_mutex_t huge_mtx; -void *huge_malloc(size_t size, bool zero); -void *huge_palloc(size_t size, size_t alignment, bool zero); +void *huge_malloc(size_t size, bool zero, dss_prec_t dss_prec); +void *huge_palloc(size_t size, size_t alignment, bool zero, + dss_prec_t dss_prec); bool huge_ralloc_no_move(void *ptr, size_t oldsize, size_t size, size_t extra); void *huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra, - size_t alignment, bool zero, bool try_tcache_dalloc); + size_t alignment, bool zero, bool try_tcache_dalloc, dss_prec_t dss_prec); #ifdef JEMALLOC_JET typedef void (huge_dalloc_junk_t)(void *, size_t); extern huge_dalloc_junk_t *huge_dalloc_junk; #endif void huge_dalloc(void *ptr, bool unmap); size_t huge_salloc(const void *ptr); +dss_prec_t huge_dss_prec_get(arena_t *arena); prof_ctx_t *huge_prof_ctx_get(const void *ptr); void huge_prof_ctx_set(const void *ptr, prof_ctx_t *ctx); bool huge_boot(void); diff --git a/include/jemalloc/internal/jemalloc_internal.h.in b/include/jemalloc/internal/jemalloc_internal.h.in index d24a1fe6..574bbb14 100644 --- a/include/jemalloc/internal/jemalloc_internal.h.in +++ b/include/jemalloc/internal/jemalloc_internal.h.in @@ -770,7 +770,7 @@ imalloct(size_t size, bool try_tcache, arena_t *arena) if (size <= arena_maxclass) return (arena_malloc(arena, size, false, try_tcache)); else - return (huge_malloc(size, false)); + return (huge_malloc(size, false, huge_dss_prec_get(arena))); } JEMALLOC_ALWAYS_INLINE void * @@ -787,7 +787,7 @@ icalloct(size_t size, bool try_tcache, arena_t *arena) if (size <= arena_maxclass) return (arena_malloc(arena, size, true, try_tcache)); else - return (huge_malloc(size, true)); + return (huge_malloc(size, true, huge_dss_prec_get(arena))); } JEMALLOC_ALWAYS_INLINE void * @@ -813,9 +813,9 @@ ipalloct(size_t usize, size_t alignment, bool zero, bool try_tcache, ret = arena_palloc(choose_arena(arena), usize, alignment, zero); } else if (alignment <= chunksize) - ret = huge_malloc(usize, zero); + ret = huge_malloc(usize, zero, huge_dss_prec_get(arena)); else - ret = huge_palloc(usize, alignment, zero); + ret = huge_palloc(usize, alignment, zero, huge_dss_prec_get(arena)); } assert(ALIGNMENT_ADDR2BASE(ret, alignment) == ret); @@ -984,7 +984,7 @@ iralloct(void *ptr, size_t size, size_t extra, size_t alignment, bool zero, try_tcache_dalloc)); } else { return (huge_ralloc(ptr, oldsize, size, extra, - alignment, zero, try_tcache_dalloc)); + alignment, zero, try_tcache_dalloc, huge_dss_prec_get(arena))); } } diff --git a/src/huge.c b/src/huge.c index 6d86aed8..d72f2135 100644 --- a/src/huge.c +++ b/src/huge.c @@ -16,14 +16,14 @@ malloc_mutex_t huge_mtx; static extent_tree_t huge; void * -huge_malloc(size_t size, bool zero) +huge_malloc(size_t size, bool zero, dss_prec_t dss_prec) { - return (huge_palloc(size, chunksize, zero)); + return (huge_palloc(size, chunksize, zero, dss_prec)); } void * -huge_palloc(size_t size, size_t alignment, bool zero) +huge_palloc(size_t size, size_t alignment, bool zero, dss_prec_t dss_prec) { void *ret; size_t csize; @@ -48,8 +48,7 @@ huge_palloc(size_t size, size_t alignment, bool zero) * it is possible to make correct junk/zero fill decisions below. */ is_zeroed = zero; - ret = chunk_alloc(csize, alignment, false, &is_zeroed, - chunk_dss_prec_get()); + ret = chunk_alloc(csize, alignment, false, &is_zeroed, dss_prec); if (ret == NULL) { base_node_dealloc(node); return (NULL); @@ -98,7 +97,7 @@ huge_ralloc_no_move(void *ptr, size_t oldsize, size_t size, size_t extra) void * huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra, - size_t alignment, bool zero, bool try_tcache_dalloc) + size_t alignment, bool zero, bool try_tcache_dalloc, dss_prec_t dss_prec) { void *ret; size_t copysize; @@ -113,18 +112,18 @@ huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra, * space and copying. */ if (alignment > chunksize) - ret = huge_palloc(size + extra, alignment, zero); + ret = huge_palloc(size + extra, alignment, zero, dss_prec); else - ret = huge_malloc(size + extra, zero); + ret = huge_malloc(size + extra, zero, dss_prec); if (ret == NULL) { if (extra == 0) return (NULL); /* Try again, this time without extra. */ if (alignment > chunksize) - ret = huge_palloc(size, alignment, zero); + ret = huge_palloc(size, alignment, zero, dss_prec); else - ret = huge_malloc(size, zero); + ret = huge_malloc(size, zero, dss_prec); if (ret == NULL) return (NULL); @@ -264,6 +263,13 @@ huge_salloc(const void *ptr) return (ret); } +dss_prec_t +huge_dss_prec_get(arena_t *arena) +{ + + return (arena_dss_prec_get(choose_arena(arena))); +} + prof_ctx_t * huge_prof_ctx_get(const void *ptr) { diff --git a/src/jemalloc.c b/src/jemalloc.c index 563d99f8..204778bc 100644 --- a/src/jemalloc.c +++ b/src/jemalloc.c @@ -2076,7 +2076,7 @@ a0alloc(size_t size, bool zero) if (size <= arena_maxclass) return (arena_malloc(arenas[0], size, zero, false)); else - return (huge_malloc(size, zero)); + return (huge_malloc(size, zero, huge_dss_prec_get(arenas[0]))); } void * From c2da2591befa5574cf8c930a5a2cd7f56138658e Mon Sep 17 00:00:00 2001 From: Harald Weppner Date: Tue, 18 Mar 2014 00:00:14 -0700 Subject: [PATCH 07/17] Consistently use debug lib(s) if present Fixes a situation where nm uses the debug lib but addr2line does not, which completely messes up the symbol lookup. --- src/prof.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/prof.c b/src/prof.c index ede89a7a..7722b7b4 100644 --- a/src/prof.c +++ b/src/prof.c @@ -11,12 +11,6 @@ #include #endif -#ifdef __FreeBSD__ -#define PROCESS_VMEM_MAP "/proc/curproc/map" -#else -#define PROCESS_VMEM_MAP "/proc/%d/maps" -#endif - /******************************************************************************/ /* Data. */ @@ -941,9 +935,12 @@ prof_dump_maps(bool propagate_err) char filename[PATH_MAX + 1]; cassert(config_prof); - - malloc_snprintf(filename, sizeof(filename), PROCESS_VMEM_MAP, +#ifdef __FreeBSD__ + malloc_snprintf(filename, sizeof(filename), "/proc/curproc/map"); +#else + malloc_snprintf(filename, sizeof(filename), "/proc/%d/maps", (int)getpid()); +#endif mfd = open(filename, O_RDONLY); if (mfd != -1) { ssize_t nread; From e3f27cfced57ac9c3b5306947d37411479a68c2e Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Sat, 29 Mar 2014 23:14:32 -0700 Subject: [PATCH 08/17] Fix p_test_fail()'s va_list abuse. p_test_fail() was passing a va_list to two separate functions with the expectation that no reset would occur. Refactor p_test_fail()'s callers to instead format two strings and pass them to p_test_fail(). Add a missing parameter to an assert_u64_eq() call, which the compiler warned about after the assertion macro refactoring. --- test/include/test/test.h | 53 ++++++++++++++++++++++++++++++---------- test/src/test.c | 10 ++------ test/unit/SFMT.c | 2 +- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/test/include/test/test.h b/test/include/test/test.h index 8cc97af5..a32ec07c 100644 --- a/test/include/test/test.h +++ b/test/include/test/test.h @@ -1,13 +1,19 @@ +#define ASSERT_BUFSIZE 256 + #define assert_cmp(t, a, b, cmp, neg_cmp, pri, fmt...) do { \ t a_ = (a); \ t b_ = (b); \ if (!(a_ cmp b_)) { \ - p_test_fail( \ + char prefix[ASSERT_BUFSIZE]; \ + char message[ASSERT_BUFSIZE]; \ + malloc_snprintf(prefix, sizeof(prefix), \ "%s:%s:%d: Failed assertion: " \ "(%s) "#cmp" (%s) --> " \ "%"pri" "#neg_cmp" %"pri": ", \ __func__, __FILE__, __LINE__, \ - #a, #b, a_, b_, fmt); \ + #a, #b, a_, b_); \ + malloc_snprintf(message, sizeof(message), fmt); \ + p_test_fail(prefix, message); \ } \ } while (0) @@ -208,24 +214,32 @@ bool a_ = (a); \ bool b_ = (b); \ if (!(a_ == b_)) { \ - p_test_fail( \ + char prefix[ASSERT_BUFSIZE]; \ + char message[ASSERT_BUFSIZE]; \ + malloc_snprintf(prefix, sizeof(prefix), \ "%s:%s:%d: Failed assertion: " \ "(%s) == (%s) --> %s != %s: ", \ __func__, __FILE__, __LINE__, \ #a, #b, a_ ? "true" : "false", \ - b_ ? "true" : "false", fmt); \ + b_ ? "true" : "false"); \ + malloc_snprintf(message, sizeof(message), fmt); \ + p_test_fail(prefix, message); \ } \ } while (0) #define assert_b_ne(a, b, fmt...) do { \ bool a_ = (a); \ bool b_ = (b); \ if (!(a_ != b_)) { \ - p_test_fail( \ + char prefix[ASSERT_BUFSIZE]; \ + char message[ASSERT_BUFSIZE]; \ + malloc_snprintf(prefix, sizeof(prefix), \ "%s:%s:%d: Failed assertion: " \ "(%s) != (%s) --> %s == %s: ", \ __func__, __FILE__, __LINE__, \ #a, #b, a_ ? "true" : "false", \ - b_ ? "true" : "false", fmt); \ + b_ ? "true" : "false"); \ + malloc_snprintf(message, sizeof(message), fmt); \ + p_test_fail(prefix, message); \ } \ } while (0) #define assert_true(a, fmt...) assert_b_eq(a, true, fmt) @@ -233,26 +247,39 @@ #define assert_str_eq(a, b, fmt...) do { \ if (strcmp((a), (b))) { \ - p_test_fail( \ + char prefix[ASSERT_BUFSIZE]; \ + char message[ASSERT_BUFSIZE]; \ + malloc_snprintf(prefix, sizeof(prefix), \ "%s:%s:%d: Failed assertion: " \ "(%s) same as (%s) --> " \ "\"%s\" differs from \"%s\": ", \ - __func__, __FILE__, __LINE__, #a, #b, a, b, fmt); \ + __func__, __FILE__, __LINE__, #a, #b, a, b); \ + malloc_snprintf(message, sizeof(message), fmt); \ + p_test_fail(prefix, message); \ } \ } while (0) #define assert_str_ne(a, b, fmt...) do { \ if (!strcmp((a), (b))) { \ - p_test_fail( \ + char prefix[ASSERT_BUFSIZE]; \ + char message[ASSERT_BUFSIZE]; \ + malloc_snprintf(prefix, sizeof(prefix), \ "%s:%s:%d: Failed assertion: " \ "(%s) differs from (%s) --> " \ "\"%s\" same as \"%s\": ", \ - __func__, __FILE__, __LINE__, #a, #b, a, b, fmt); \ + __func__, __FILE__, __LINE__, #a, #b, a, b); \ + malloc_snprintf(message, sizeof(message), fmt); \ + p_test_fail(prefix, message); \ } \ } while (0) #define assert_not_reached(fmt...) do { \ - p_test_fail("%s:%s:%d: Unreachable code reached: ", \ - __func__, __FILE__, __LINE__, fmt); \ + char prefix[ASSERT_BUFSIZE]; \ + char message[ASSERT_BUFSIZE]; \ + malloc_snprintf(prefix, sizeof(prefix), \ + "%s:%s:%d: Unreachable code reached: ", \ + __func__, __FILE__, __LINE__); \ + malloc_snprintf(message, sizeof(message), fmt); \ + p_test_fail(prefix, message); \ } while (0) /* @@ -299,4 +326,4 @@ void test_fail(const char *format, ...) JEMALLOC_ATTR(format(printf, 1, 2)); test_status_t p_test(test_t* t, ...); void p_test_init(const char *name); void p_test_fini(void); -void p_test_fail(const char *format, ...); +void p_test_fail(const char *prefix, const char *message); diff --git a/test/src/test.c b/test/src/test.c index 6552e377..528d8583 100644 --- a/test/src/test.c +++ b/test/src/test.c @@ -86,15 +86,9 @@ p_test(test_t* t, ...) } void -p_test_fail(const char *format, ...) +p_test_fail(const char *prefix, const char *message) { - va_list ap; - va_start(ap, format); - malloc_vcprintf(NULL, NULL, format, ap); - format = va_arg(ap, const char *); - malloc_vcprintf(NULL, NULL, format, ap); - va_end(ap); - malloc_printf("\n"); + malloc_cprintf(NULL, NULL, "%s%s\n", prefix, message); test_status = test_status_fail; } diff --git a/test/unit/SFMT.c b/test/unit/SFMT.c index 4805f8e4..c57bd68d 100644 --- a/test/unit/SFMT.c +++ b/test/unit/SFMT.c @@ -1576,7 +1576,7 @@ TEST_BEGIN(test_by_array_64) for (i = 0; i < BLOCK_SIZE64; i++) { if (i < COUNT_1) { assert_u64_eq(array64[i], init_by_array_64_expected[i], - "Output mismatch for i=%d"); + "Output mismatch for i=%d", i); } r = gen_rand64(ctx); assert_u64_eq(r, array64[i], From ab8c79fdafd6d1ee722c1277ef32c14c6e0c9dd3 Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Sun, 30 Mar 2014 11:21:09 -0700 Subject: [PATCH 09/17] Fix message formatting errors uncovered by p_test_fail() refactoring. --- test/unit/ckh.c | 12 ++++++------ test/unit/junk.c | 2 +- test/unit/quarantine.c | 2 +- test/unit/rtree.c | 5 +++-- test/unit/zero.c | 2 +- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/test/unit/ckh.c b/test/unit/ckh.c index 69fd7f52..b214c279 100644 --- a/test/unit/ckh.c +++ b/test/unit/ckh.c @@ -29,7 +29,7 @@ TEST_BEGIN(test_count_insert_search_remove) assert_false(ckh_new(&ckh, 2, ckh_string_hash, ckh_string_keycomp), "Unexpected ckh_new() error"); assert_zu_eq(ckh_count(&ckh), 0, - "ckh_count() should return %zu, but it returned %zu", 0, + "ckh_count() should return %zu, but it returned %zu", ZU(0), ckh_count(&ckh)); /* Insert. */ @@ -101,11 +101,11 @@ TEST_END TEST_BEGIN(test_insert_iter_remove) { -#define NITEMS 1000 +#define NITEMS ZU(1000) ckh_t ckh; void **p[NITEMS]; void *q, *r; - unsigned i; + size_t i; assert_false(ckh_new(&ckh, 2, ckh_pointer_hash, ckh_pointer_keycomp), "Unexpected ckh_new() error"); @@ -116,7 +116,7 @@ TEST_BEGIN(test_insert_iter_remove) } for (i = 0; i < NITEMS; i++) { - unsigned j; + size_t j; for (j = i; j < NITEMS; j++) { assert_false(ckh_insert(&ckh, p[j], p[j]), @@ -152,7 +152,7 @@ TEST_BEGIN(test_insert_iter_remove) for (tabind = 0; ckh_iter(&ckh, &tabind, &q, &r) == false;) { - unsigned k; + size_t k; assert_ptr_eq(q, r, "Key and val not equal"); @@ -188,7 +188,7 @@ TEST_BEGIN(test_insert_iter_remove) } assert_zu_eq(ckh_count(&ckh), 0, - "ckh_count() should return %zu, but it returned %zu", 0, + "ckh_count() should return %zu, but it returned %zu", ZU(0), ckh_count(&ckh)); ckh_delete(&ckh); #undef NITEMS diff --git a/test/unit/junk.c b/test/unit/junk.c index ef8f9c16..85bbf9e2 100644 --- a/test/unit/junk.c +++ b/test/unit/junk.c @@ -73,7 +73,7 @@ test_junk(size_t sz_min, size_t sz_max) if (sz_prev > 0) { assert_c_eq(s[0], 'a', "Previously allocated byte %zu/%zu is corrupted", - 0, sz_prev); + ZU(0), sz_prev); assert_c_eq(s[sz_prev-1], 'a', "Previously allocated byte %zu/%zu is corrupted", sz_prev-1, sz_prev); diff --git a/test/unit/quarantine.c b/test/unit/quarantine.c index 45349237..bbd48a51 100644 --- a/test/unit/quarantine.c +++ b/test/unit/quarantine.c @@ -21,7 +21,7 @@ quarantine_clear(void) TEST_BEGIN(test_quarantine) { -#define SZ 256 +#define SZ ZU(256) #define NQUARANTINED (QUARANTINE_SIZE/SZ) void *quarantined[NQUARANTINED+1]; size_t i, j; diff --git a/test/unit/rtree.c b/test/unit/rtree.c index 5e7a4113..5463055f 100644 --- a/test/unit/rtree.c +++ b/test/unit/rtree.c @@ -48,8 +48,9 @@ TEST_BEGIN(test_rtree_bits) assert_u_eq(rtree_get(rtree, keys[k]), 1, "rtree_get() should return previously set " "value and ignore insignificant key bits; " - "i=%u, j=%u, k=%u, set key=%#x, " - "get key=%#x", i, j, k, keys[j], keys[k]); + "i=%u, j=%u, k=%u, set key=%#"PRIxPTR", " + "get key=%#"PRIxPTR, i, j, k, keys[j], + keys[k]); } assert_u_eq(rtree_get(rtree, (((uintptr_t)1) << (sizeof(uintptr_t)*8-i))), 0, diff --git a/test/unit/zero.c b/test/unit/zero.c index 2fdae2fd..65a8f0c9 100644 --- a/test/unit/zero.c +++ b/test/unit/zero.c @@ -20,7 +20,7 @@ test_zero(size_t sz_min, size_t sz_max) if (sz_prev > 0) { assert_c_eq(s[0], 'a', "Previously allocated byte %zu/%zu is corrupted", - 0, sz_prev); + ZU(0), sz_prev); assert_c_eq(s[sz_prev-1], 'a', "Previously allocated byte %zu/%zu is corrupted", sz_prev-1, sz_prev); From ada8447cf6fb2c1f976b6311dade2e91026b3d83 Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Sun, 30 Mar 2014 11:22:23 -0700 Subject: [PATCH 10/17] Reduce maximum tested alignment. Reduce maximum tested alignment from 2^29 to 2^25. Some systems may not have enough contiguous virtual memory to satisfy the larger alignment, but the smaller alignment is still adequate to test multi-chunk alignment. --- test/integration/allocm.c | 3 +-- test/integration/mallocx.c | 3 +-- test/integration/rallocx.c | 4 ++-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/test/integration/allocm.c b/test/integration/allocm.c index 66ecf869..7b4ea0c2 100644 --- a/test/integration/allocm.c +++ b/test/integration/allocm.c @@ -1,8 +1,7 @@ #include "test/jemalloc_test.h" #define CHUNK 0x400000 -/* #define MAXALIGN ((size_t)UINT64_C(0x80000000000)) */ -#define MAXALIGN ((size_t)0x2000000LU) +#define MAXALIGN (((size_t)1) << 25) #define NITER 4 TEST_BEGIN(test_basic) diff --git a/test/integration/mallocx.c b/test/integration/mallocx.c index f37a74bc..123e041f 100644 --- a/test/integration/mallocx.c +++ b/test/integration/mallocx.c @@ -1,8 +1,7 @@ #include "test/jemalloc_test.h" #define CHUNK 0x400000 -/* #define MAXALIGN ((size_t)UINT64_C(0x80000000000)) */ -#define MAXALIGN ((size_t)0x2000000LU) +#define MAXALIGN (((size_t)1) << 25) #define NITER 4 TEST_BEGIN(test_basic) diff --git a/test/integration/rallocx.c b/test/integration/rallocx.c index b4b67802..ee21aedf 100644 --- a/test/integration/rallocx.c +++ b/test/integration/rallocx.c @@ -112,7 +112,7 @@ TEST_BEGIN(test_align) { void *p, *q; size_t align; -#define MAX_ALIGN (ZU(1) << 29) +#define MAX_ALIGN (ZU(1) << 25) align = ZU(1); p = mallocx(1, MALLOCX_ALIGN(align)); @@ -137,7 +137,7 @@ TEST_BEGIN(test_lg_align_and_zero) { void *p, *q; size_t lg_align, sz; -#define MAX_LG_ALIGN 29 +#define MAX_LG_ALIGN 25 #define MAX_VALIDATE (ZU(1) << 22) lg_align = ZU(0); From df3f27024f193b7baeedcd9f3799b4774dd20bbf Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Sun, 30 Mar 2014 16:27:08 -0700 Subject: [PATCH 11/17] Adapt hash tests to big-endian systems. The hash code, which has MurmurHash3 at its core, generates different output depending on system endianness, so adapt the expected output on big-endian systems. MurmurHash3 code also makes the assumption that unaligned access is okay (not true on all systems), but jemalloc only hashes data structures that have sufficient alignment to dodge this limitation. --- configure.ac | 5 +++++ include/jemalloc/internal/hash.h | 2 +- include/jemalloc/internal/jemalloc_internal_defs.h.in | 3 +++ test/unit/hash.c | 6 ++++++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 3837a786..d5c663eb 100644 --- a/configure.ac +++ b/configure.ac @@ -150,6 +150,11 @@ if test "x$EXTRA_CFLAGS" != "x" ; then fi AC_PROG_CPP +AC_C_BIGENDIAN([ac_cv_big_endian=1], [ac_cv_big_endian=0]) +if test "x${ac_cv_big_endian}" = "x1" ; then + AC_DEFINE_UNQUOTED([JEMALLOC_BIG_ENDIAN], [ ]) +fi + AC_CHECK_SIZEOF([void *]) if test "x${ac_cv_sizeof_void_p}" = "x8" ; then LG_SIZEOF_PTR=3 diff --git a/include/jemalloc/internal/hash.h b/include/jemalloc/internal/hash.h index 09b69df5..c7183ede 100644 --- a/include/jemalloc/internal/hash.h +++ b/include/jemalloc/internal/hash.h @@ -320,7 +320,7 @@ hash_x64_128(const void *key, const int len, const uint32_t seed, JEMALLOC_INLINE void hash(const void *key, size_t len, const uint32_t seed, size_t r_hash[2]) { -#if (LG_SIZEOF_PTR == 3) +#if (LG_SIZEOF_PTR == 3 && !defined(JEMALLOC_BIG_ENDIAN)) hash_x64_128(key, len, seed, (uint64_t *)r_hash); #else uint64_t hashes[2]; diff --git a/include/jemalloc/internal/jemalloc_internal_defs.h.in b/include/jemalloc/internal/jemalloc_internal_defs.h.in index e3758e47..c166fbd9 100644 --- a/include/jemalloc/internal/jemalloc_internal_defs.h.in +++ b/include/jemalloc/internal/jemalloc_internal_defs.h.in @@ -190,6 +190,9 @@ /* C99 restrict keyword supported. */ #undef JEMALLOC_HAS_RESTRICT +/* For use by hash code. */ +#undef JEMALLOC_BIG_ENDIAN + /* sizeof(int) == 2^LG_SIZEOF_INT. */ #undef LG_SIZEOF_INT diff --git a/test/unit/hash.c b/test/unit/hash.c index 0446e524..abb394ac 100644 --- a/test/unit/hash.c +++ b/test/unit/hash.c @@ -122,9 +122,15 @@ hash_variant_verify(hash_variant_t variant) (final[3] << 24); switch (variant) { +#ifdef JEMALLOC_BIG_ENDIAN + case hash_variant_x86_32: expected = 0x6213303eU; break; + case hash_variant_x86_128: expected = 0x266820caU; break; + case hash_variant_x64_128: expected = 0xcc622b6fU; break; +#else case hash_variant_x86_32: expected = 0xb0f57ee3U; break; case hash_variant_x86_128: expected = 0xb3ece62aU; break; case hash_variant_x64_128: expected = 0x6384ba69U; break; +#endif default: not_reached(); } From e64b1b7be9319b187360306ceff17ce6cb2d530c Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Sun, 30 Mar 2014 17:24:24 -0700 Subject: [PATCH 12/17] Enable big-endian mode for SFMT. Add cpp logic to enable big-endian mode in SFMT. This should fix SFMT tests on e.g. MIPS and SPARC. --- test/src/SFMT.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/src/SFMT.c b/test/src/SFMT.c index 433d7f6e..e6f8deec 100644 --- a/test/src/SFMT.c +++ b/test/src/SFMT.c @@ -49,6 +49,9 @@ #include "test/jemalloc_test.h" #include "test/SFMT-params.h" +#if defined(JEMALLOC_BIG_ENDIAN) && !defined(BIG_ENDIAN64) +#define BIG_ENDIAN64 1 +#endif #if defined(__BIG_ENDIAN__) && !defined(__amd64) && !defined(BIG_ENDIAN64) #define BIG_ENDIAN64 1 #endif From e181f5aa76d3a9d59a4e0ce46867349334f286d1 Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Sun, 30 Mar 2014 18:58:32 -0700 Subject: [PATCH 13/17] Keep frame pointers if using gcc frame intrinsics. Specify -fno-omit-frame-pointer when using __builtin_frame_address() and __builtin_return_address() for backtracing. This fixes backtracing failures on e.g. i686 for optimized builds. --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index d5c663eb..3521a704 100644 --- a/configure.ac +++ b/configure.ac @@ -784,6 +784,7 @@ fi ) if test "x$backtrace_method" = "x" -a "x$enable_prof_gcc" = "x1" \ -a "x$GCC" = "xyes" ; then + JE_CFLAGS_APPEND([-fno-omit-frame-pointer]) backtrace_method="gcc intrinsics" AC_DEFINE([JEMALLOC_PROF_GCC], [ ]) else From 82abf6fe6913a0f8bccc5ad8aeab081a8d9a5ed8 Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Sun, 30 Mar 2014 20:35:50 -0700 Subject: [PATCH 14/17] Allow libgcc-based backtracing on x86. Remove autoconf code that explicitly disabled libgcc-based backtracing on i[3456]86. There is no mention of which platforms/compilers exhibited problems when this code was added, and chances are good that any gcc toolchain issues have long since been fixed. --- configure.ac | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/configure.ac b/configure.ac index 3521a704..4de81dc1 100644 --- a/configure.ac +++ b/configure.ac @@ -747,22 +747,6 @@ if test "x$backtrace_method" = "x" -a "x$enable_prof_libgcc" = "x1" \ -a "x$GCC" = "xyes" ; then AC_CHECK_HEADERS([unwind.h], , [enable_prof_libgcc="0"]) AC_CHECK_LIB([gcc], [_Unwind_Backtrace], [LIBS="$LIBS -lgcc"], [enable_prof_libgcc="0"]) - dnl The following is conservative, in that it only has entries for CPUs on - dnl which jemalloc has been tested. - AC_MSG_CHECKING([libgcc-based backtracing reliability on ${host_cpu}]) - case "${host_cpu}" in - i[[3456]]86) - AC_MSG_RESULT([unreliable]) - enable_prof_libgcc="0"; - ;; - x86_64) - AC_MSG_RESULT([reliable]) - ;; - *) - AC_MSG_RESULT([unreliable]) - enable_prof_libgcc="0"; - ;; - esac if test "x${enable_prof_libgcc}" = "x1" ; then backtrace_method="libgcc" AC_DEFINE([JEMALLOC_PROF_LIBGCC], [ ]) From 9c62ed44b04610bd5465c8aaeec5623280015d41 Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Mon, 31 Mar 2014 09:16:59 -0700 Subject: [PATCH 15/17] Document how dss precedence affects huge allocation. --- doc/jemalloc.xml.in | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/jemalloc.xml.in b/doc/jemalloc.xml.in index c7e2e872..d8e2e711 100644 --- a/doc/jemalloc.xml.in +++ b/doc/jemalloc.xml.in @@ -1439,8 +1439,12 @@ malloc_conf = "xmalloc:true";]]> Set the precedence of dss allocation as related to mmap allocation for arena <i>, or for all arenas if <i> equals arenas.narenas. See - opt.dss for supported + linkend="arenas.narenas">arenas.narenas. Note + that even during huge allocation this setting is read from the arena + that would be chosen for small or large allocation so that applications + can depend on consistent dss versus mmap allocation regardless of + allocation size. See opt.dss for supported settings. From ff53631535707c79bbd7e0fd255f954aaf2b5268 Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Mon, 31 Mar 2014 09:23:10 -0700 Subject: [PATCH 16/17] Update ChangeLog for 3.6.0. --- ChangeLog | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/ChangeLog b/ChangeLog index c0ca338b..d56ee999 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,30 @@ found in the git revision history: https://github.com/jemalloc/jemalloc +* 3.6.0 (March 31, 2014) + + This version contains a critical bug fix for a regression present in 3.5.0 and + 3.5.1. + + Bug fixes: + - Fix a regression in arena_chunk_alloc() that caused crashes during + small/large allocation if chunk allocation failed. In the absence of this + bug, chunk allocation failure would result in allocation failure, e.g. NULL + return from malloc(). This regression was introduced in 3.5.0. + - Fix backtracing for gcc intrinsics-based backtracing by specifying + -fno-omit-frame-pointer to gcc. Note that the application (and all the + libraries it links to) must also be compiled with this option for + backtracing to be reliable. + - Use dss allocation precedence for huge allocations as well as small/large + allocations. + - Fix test assertion failure message formatting. This bug did not manifect on + x86_64 systems because of implementation subtleties in va_list. + - Fix inconsequential test failures for hash and SFMT code. + + New features: + - Support heap profiling on FreeBSD. This feature depends on the proc + filesystem being mounted during heap profile dumping. + * 3.5.1 (February 25, 2014) This version primarily addresses minor bugs in test code. From 8a26eaca7f4c95771ecbf096caeeba14fbe1122f Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Mon, 31 Mar 2014 09:31:38 -0700 Subject: [PATCH 17/17] Add private namespace mangling for huge_dss_prec_get(). --- include/jemalloc/internal/private_symbols.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/include/jemalloc/internal/private_symbols.txt b/include/jemalloc/internal/private_symbols.txt index 1e64ed57..93516d24 100644 --- a/include/jemalloc/internal/private_symbols.txt +++ b/include/jemalloc/internal/private_symbols.txt @@ -197,6 +197,7 @@ huge_allocated huge_boot huge_dalloc huge_dalloc_junk +huge_dss_prec_get huge_malloc huge_mtx huge_ndalloc