commit 3713cee3624bdfbca808847b7199fa7efd948f99 Author: overweight <5324761+overweight@user.noreply.gitee.com> Date: Mon Sep 30 10:51:34 2019 -0400 Package init diff --git a/Avoid-static-initialization-of-pprof-path-for-symbol.patch b/Avoid-static-initialization-of-pprof-path-for-symbol.patch new file mode 100644 index 0000000..5b1c261 --- /dev/null +++ b/Avoid-static-initialization-of-pprof-path-for-symbol.patch @@ -0,0 +1,64 @@ +From 893bff51bcf220b724a812d340d878b5fb8ce911 Mon Sep 17 00:00:00 2001 +From: Aliaksey Kandratsenka +Date: Sun, 26 Aug 2018 11:35:44 -0700 +Subject: [PATCH 23/39] Avoid static initialization of pprof path for + symbolization. + +This is one of the things that chrome's fork fixes, but with c++11 we +can do it even nicer. Proposed fix is to use c++11 local static +variable to ensure that pprof path is initialized once on as-needed +basis. +--- + src/symbolize.cc | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +diff --git a/src/symbolize.cc b/src/symbolize.cc +index 88609ff..4c71010 100755 +--- a/src/symbolize.cc ++++ b/src/symbolize.cc +@@ -67,15 +67,17 @@ + using std::string; + using tcmalloc::DumpProcSelfMaps; // from sysinfo.h + +- +-DEFINE_string(symbolize_pprof, +- EnvToString("PPROF_PATH", "pprof"), +- "Path to pprof to call for reporting function names."); +- +-// heap_profile_table_pprof may be referenced after destructors are ++// pprof may be used after destructors are + // called (since that's when leak-checking is done), so we make + // a more-permanent copy that won't ever get destroyed. +-static string* g_pprof_path = new string(FLAGS_symbolize_pprof); ++static char* get_pprof_path() { ++ static char* result = ([] () { ++ string pprof_string = EnvToString("PPROF_PATH", "pprof"); ++ return strdup(pprof_string.c_str()); ++ })(); ++ ++ return result; ++} + + // Returns NULL if we're on an OS where we can't get the invocation name. + // Using a static var is ok because we're not called from a thread. +@@ -144,7 +146,7 @@ int SymbolTable::Symbolize() { + PrintError("Cannot figure out the name of this executable (argv0)"); + return 0; + } +- if (access(g_pprof_path->c_str(), R_OK) != 0) { ++ if (access(get_pprof_path(), R_OK) != 0) { + PrintError("Cannot find 'pprof' (is PPROF_PATH set correctly?)"); + return 0; + } +@@ -206,7 +208,7 @@ int SymbolTable::Symbolize() { + unsetenv("HEAPPROFILE"); + unsetenv("HEAPCHECK"); + unsetenv("PERFTOOLS_VERBOSE"); +- execlp(g_pprof_path->c_str(), g_pprof_path->c_str(), ++ execlp(get_pprof_path(), get_pprof_path(), + "--symbols", argv0, NULL); + _exit(3); // if execvp fails, it's bad news for us + } +-- +1.8.3.1 + diff --git a/Disable-large-allocation-report-by-default.patch b/Disable-large-allocation-report-by-default.patch new file mode 100644 index 0000000..7463b39 --- /dev/null +++ b/Disable-large-allocation-report-by-default.patch @@ -0,0 +1,70 @@ +From 99d4b81d3fcedb7c912acbd813573a89d32ade22 Mon Sep 17 00:00:00 2001 +From: Junhao Li +Date: Sun, 20 May 2018 13:45:32 -0400 +Subject: [PATCH] Disable large allocation report by default + +Fixes issue #360. + +[alkondratenko@gmail.com: adjusted commit message a bit] +[alkondratenko@gmail.com: adjusted configure help message] +Signed-off-by: Aliaksey Kandratsenka +--- + configure.ac | 9 +++++++++ + src/tcmalloc.cc | 4 ++++ + 2 files changed, 13 insertions(+) + +diff --git a/configure.ac b/configure.ac +index fa03f1a..f874e19 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -663,6 +663,15 @@ AS_IF([test "x$enable_generic_dynamic_tls" = xyes], + [AC_DEFINE([ENABLE_GENERIC_DYNAMIC_TLS], 1, + [Use the generic dynamic TLS model])]) + ++# Disable large allocation report by default. ++AC_ARG_ENABLE([large-alloc-report], ++ [AS_HELP_STRING([--enable-large-alloc-report], ++ [report very large allocations to stderr])], ++ [enable_large_alloc_report="$enableval"], ++ [enable_large_alloc_report=no]) ++AS_IF([test "x$enable_large_alloc_report" = xyes], ++ [AC_DEFINE([ENABLE_LARGE_ALLOC_REPORT], 1, [report large allocation])]) ++ + # Write generated configuration file + AC_CONFIG_FILES([Makefile + src/gperftools/tcmalloc.h src/windows/gperftools/tcmalloc.h]) +diff --git a/src/tcmalloc.cc b/src/tcmalloc.cc +index 7b18ddb..48d4530 100644 +--- a/src/tcmalloc.cc ++++ b/src/tcmalloc.cc +@@ -1272,9 +1272,11 @@ void* handle_oom(malloc_fn retry_fn, + + // Copy of FLAGS_tcmalloc_large_alloc_report_threshold with + // automatic increases factored in. ++#ifdef ENABLE_LARGE_ALLOC_REPORT + static int64_t large_alloc_threshold = + (kPageSize > FLAGS_tcmalloc_large_alloc_report_threshold + ? kPageSize : FLAGS_tcmalloc_large_alloc_report_threshold); ++#endif + + static void ReportLargeAlloc(Length num_pages, void* result) { + StackTrace stack; +@@ -1295,6 +1297,7 @@ static void ReportLargeAlloc(Length num_pages, void* result) { + + // Must be called with the page lock held. + inline bool should_report_large(Length num_pages) { ++#ifdef ENABLE_LARGE_ALLOC_REPORT + const int64 threshold = large_alloc_threshold; + if (threshold > 0 && num_pages >= (threshold >> kPageShift)) { + // Increase the threshold by 1/8 every time we generate a report. +@@ -1303,6 +1306,7 @@ inline bool should_report_large(Length num_pages) { + ? threshold + threshold/8 : 8ll<<30); + return true; + } ++#endif + return false; + } + +-- +1.8.3.1 + diff --git a/Drop-not-very-portable-and-not-very-useful-unwind-be.patch b/Drop-not-very-portable-and-not-very-useful-unwind-be.patch new file mode 100644 index 0000000..ab4c484 --- /dev/null +++ b/Drop-not-very-portable-and-not-very-useful-unwind-be.patch @@ -0,0 +1,196 @@ +From 630c9ce77822212a4ce3ee92afabbec0eea0f94b Mon Sep 17 00:00:00 2001 +From: Aliaksey Kandratsenka +Date: Sun, 7 Oct 2018 08:17:04 -0700 +Subject: [PATCH] Drop not very portable and not very useful unwind benchmark. + +--- + Makefile.am | 8 ---- + benchmark/getcontext_light.cc | 60 ----------------------------- + benchmark/unwind_bench.cc | 89 ------------------------------------------- + 3 files changed, 157 deletions(-) + delete mode 100644 benchmark/getcontext_light.cc + delete mode 100644 benchmark/unwind_bench.cc + +diff --git a/Makefile.am b/Makefile.am +index c79227a..1f52d3d 100755 +--- a/Makefile.am ++++ b/Makefile.am +@@ -881,14 +881,6 @@ malloc_bench_shared_full_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTI + malloc_bench_shared_full_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) + malloc_bench_shared_full_LDADD = librun_benchmark.la libtcmalloc.la $(PTHREAD_LIBS) + +-if !OSX +-noinst_PROGRAMS += unwind_bench +-unwind_bench_SOURCES = benchmark/unwind_bench.cc benchmark/getcontext_light.cc +-unwind_bench_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) +-unwind_bench_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +-unwind_bench_LDADD = librun_benchmark.la libtcmalloc.la $(PTHREAD_LIBS) +-endif !OSX +- + endif WITH_HEAP_PROFILER_OR_CHECKER + + binary_trees_SOURCES = benchmark/binary_trees.cc +diff --git a/benchmark/getcontext_light.cc b/benchmark/getcontext_light.cc +deleted file mode 100644 +index e8ff8b3..0000000 +--- a/benchmark/getcontext_light.cc ++++ /dev/null +@@ -1,60 +0,0 @@ +-#include +-#include +- +-extern "C" void getcontext_light(ucontext_t *ctx); +- +-// clang's built-in asm cannot handle .set directives +-#if defined(__GNUC__) && !defined(__llvm__) && defined(__x86_64) && defined(_LP64) +- +-#define R(r) offsetof(ucontext_t, uc_mcontext.gregs[r]) +- +-static __attribute__((used)) +-void getcontext_tramp(ucontext_t *ctx) { +- __asm__ __volatile__(".set oRBX, %c0\n" +- ".set oRBP, %c1\n" +- ".set oR12, %c2\n" +- ".set oR13, %c3\n" +- ".set oR14, %c4\n" +- ".set oR15, %c5\n" +- ".set oRIP, %c6\n" +- ".set oRSP, %c7\n" +- : : +- "p" (R(REG_RBX)), +- "p" (R(REG_RBP)), +- "p" (R(REG_R12)), +- "p" (R(REG_R13)), +- "p" (R(REG_R14)), +- "p" (R(REG_R15)), +- "p" (R(REG_RIP)), +- "p" (R(REG_RSP))); +- getcontext_light(ctx); +-} +- +-__asm__(".pushsection .text; .globl getcontext_light\n" +- ".type getcontext_light, @function\n" +-"getcontext_light:\n" +- "\t.cfi_startproc\n" +- "\tmovq %rbx, oRBX(%rdi)\n" +- "\tmovq %rbp, oRBP(%rdi)\n" +- "\tmovq %r12, oR12(%rdi)\n" +- "\tmovq %r13, oR13(%rdi)\n" +- "\tmovq %r14, oR14(%rdi)\n" +- "\tmovq %r15, oR14(%rdi)\n" +- +- "\tmovq (%rsp), %rcx\n" +- "\tmovq %rcx, oRIP(%rdi)\n" +- "\tleaq 8(%rsp), %rcx\n" /* Exclude the return address. */ +- "\tmovq %rcx, oRSP(%rdi)\n" +- "\tret\n" +- ".cfi_endproc\n" +- ".size getcontext_light, .-getcontext_light\n" +- ".popsection\n" +- ); +- +-#else +- +-extern "C" void getcontext_light(ucontext_t *ctx) { +- getcontext(ctx); +-} +- +-#endif +diff --git a/benchmark/unwind_bench.cc b/benchmark/unwind_bench.cc +deleted file mode 100644 +index 9c4e2f8..0000000 +--- a/benchmark/unwind_bench.cc ++++ /dev/null +@@ -1,89 +0,0 @@ +-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +-#include "config.h" +- +-#include "base/basictypes.h" +-#include "gperftools/stacktrace.h" +- +-#include +-#include +-#include +-#include +-#if HAVE_LIBUNWIND_H +-#include +-#endif +- +-#include "run_benchmark.h" +- +-extern "C" void getcontext_light(ucontext_t *ctx); +- +-#define MAX_FRAMES 1024 +-static void *frames[MAX_FRAMES]; +- +-enum measure_mode { +- MODE_NOOP, +- MODE_WITH_CONTEXT, +- MODE_WITHOUT_CONTEXT +-}; +- +-static int ATTRIBUTE_NOINLINE measure_unwind(int maxlevel, int mode) { +- int n; +- +- if (mode == MODE_NOOP) +- return 0; +- +- if (mode == MODE_WITH_CONTEXT) { +- ucontext_t uc; +- getcontext_light(&uc); +- n = GetStackTraceWithContext(frames, MAX_FRAMES, 0, &uc); +- } else { +- n = GetStackTrace(frames, MAX_FRAMES, 0); +- } +- if (n < maxlevel) { +- fprintf(stderr, "Expected at least %d frames, got %d\n", maxlevel, n); +- abort(); +- } +- return 0; +-} +- +-static int ATTRIBUTE_NOINLINE frame_forcer(int rv) { +- return rv; +-} +- +-static int ATTRIBUTE_NOINLINE f1(int level, int maxlevel, int mode) { +- if (level == maxlevel) +- return frame_forcer(measure_unwind(maxlevel, mode)); +- return frame_forcer(f1(level + 1, maxlevel, mode)); +-} +- +-static void bench_unwind_no_op(long iterations, uintptr_t param) { +- do { +- f1(0, param, MODE_NOOP); +- iterations -= param; +- } while (iterations > 0); +-} +- +-static void bench_unwind_context(long iterations, uintptr_t param) { +- do { +- f1(0, param, MODE_WITH_CONTEXT); +- iterations -= param; +- } while (iterations > 0); +-} +- +-static void bench_unwind_no_context(long iterations, uintptr_t param) { +- do { +- f1(0, param, MODE_WITHOUT_CONTEXT); +- iterations -= param; +- } while (iterations > 0); +-} +- +-int main(void) { +- report_benchmark("unwind_no_op", bench_unwind_no_op, 100); +- report_benchmark("unwind_context", bench_unwind_context, 100); +- report_benchmark("unwind_no_context", bench_unwind_no_context, 100); +- +-//// TODO: somehow this fails at linking step. Figure out why this is missing +-// #if HAVE_LIBUNWIND_H +-// unw_set_caching_policy(unw_local_addr_space, UNW_CACHE_PER_THREAD); +-// #endif +- return 0; +-} +-- +1.8.3.1 + diff --git a/Fix-incompatible-aliasing-warnings.patch b/Fix-incompatible-aliasing-warnings.patch new file mode 100644 index 0000000..2c912fe --- /dev/null +++ b/Fix-incompatible-aliasing-warnings.patch @@ -0,0 +1,101 @@ +From 71c8cedacafe700e662c008b65f5064b23426070 Mon Sep 17 00:00:00 2001 +From: Aliaksey Kandratsenka +Date: Sun, 5 Aug 2018 18:54:01 -0700 +Subject: [PATCH 19/39] Fix incompatible aliasing warnings + +We aliased functions with different signatures and gcc now correctly +gives warning for that. Originally gcc 5 same code merging feature +caused us to alias more than necessary, but I am not able to reproduce +this problem anymore. So we're now aliasing only compatible functions. +--- + src/libc_override_gcc_and_weak.h | 8 ++++---- + src/tcmalloc.cc | 16 ---------------- + 2 files changed, 4 insertions(+), 20 deletions(-) + +diff --git a/src/libc_override_gcc_and_weak.h b/src/libc_override_gcc_and_weak.h +index 6875164..bb99b69 100644 +--- a/src/libc_override_gcc_and_weak.h ++++ b/src/libc_override_gcc_and_weak.h +@@ -126,9 +126,9 @@ void operator delete[](void *p, size_t size) CPP_NOTHROW + #else /* !ENABLE_SIZED_DELETE && !ENABLE_DYN_SIZED_DELETE */ + + void operator delete(void *p, size_t size) CPP_NOTHROW +- ALIAS(tc_delete); ++ ALIAS(tc_delete_sized); + void operator delete[](void *p, size_t size) CPP_NOTHROW +- ALIAS(tc_deletearray); ++ ALIAS(tc_deletearray_sized); + + #endif /* !ENABLE_SIZED_DELETE && !ENABLE_DYN_SIZED_DELETE */ + +@@ -197,9 +197,9 @@ void operator delete[](void *p, size_t size, std::align_val_t al) CPP_NOTHROW + #else /* defined(ENABLE_DYN_SIZED_DELETE) */ + + void operator delete(void *p, size_t size, std::align_val_t al) CPP_NOTHROW +- ALIAS(tc_delete); ++ ALIAS(tc_delete_sized_aligned); + void operator delete[](void *p, size_t size, std::align_val_t al) CPP_NOTHROW +- ALIAS(tc_deletearray); ++ ALIAS(tc_deletearray_sized_aligned); + + #endif /* defined(ENABLE_DYN_SIZED_DELETE) */ + +diff --git a/src/tcmalloc.cc b/src/tcmalloc.cc +index 37c1440..b320b30 100644 +--- a/src/tcmalloc.cc ++++ b/src/tcmalloc.cc +@@ -1998,9 +1998,6 @@ TC_ALIAS(tc_free); + // (via ::operator delete(ptr, nothrow)). + // But it's really the same as normal delete, so we just do the same thing. + extern "C" PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p, const std::nothrow_t&) PERFTOOLS_NOTHROW +-#ifdef TC_ALIAS +-TC_ALIAS(tc_free); +-#else + { + if (PREDICT_FALSE(!base::internal::delete_hooks_.empty())) { + tcmalloc::invoke_hooks_and_free(p); +@@ -2008,7 +2005,6 @@ TC_ALIAS(tc_free); + } + do_free(p); + } +-#endif + + extern "C" PERFTOOLS_DLL_DECL void* tc_newarray(size_t size) + #ifdef TC_ALIAS +@@ -2080,33 +2076,21 @@ extern "C" PERFTOOLS_DLL_DECL void* tc_new_aligned_nothrow(size_t size, std::ali + } + + extern "C" PERFTOOLS_DLL_DECL void tc_delete_aligned(void* p, std::align_val_t) PERFTOOLS_NOTHROW +-#ifdef TC_ALIAS +-TC_ALIAS(tc_delete); +-#else + { + free_fast_path(p); + } +-#endif + + // There is no easy way to obtain the actual size used by do_memalign to allocate aligned storage, so for now + // just ignore the size. It might get useful in the future. + extern "C" PERFTOOLS_DLL_DECL void tc_delete_sized_aligned(void* p, size_t size, std::align_val_t align) PERFTOOLS_NOTHROW +-#ifdef TC_ALIAS +-TC_ALIAS(tc_delete); +-#else + { + free_fast_path(p); + } +-#endif + + extern "C" PERFTOOLS_DLL_DECL void tc_delete_aligned_nothrow(void* p, std::align_val_t, const std::nothrow_t&) PERFTOOLS_NOTHROW +-#ifdef TC_ALIAS +-TC_ALIAS(tc_delete); +-#else + { + free_fast_path(p); + } +-#endif + + extern "C" PERFTOOLS_DLL_DECL void* tc_newarray_aligned(size_t size, std::align_val_t align) + #ifdef TC_ALIAS +-- +1.8.3.1 + diff --git a/Fix-mmap-region-iteration-while-no-regions-are-recor.patch b/Fix-mmap-region-iteration-while-no-regions-are-recor.patch new file mode 100644 index 0000000..87897b3 --- /dev/null +++ b/Fix-mmap-region-iteration-while-no-regions-are-recor.patch @@ -0,0 +1,81 @@ +From 1de76671d478e848f0dd210e00df43bfa463ca9f Mon Sep 17 00:00:00 2001 +From: Gabriel Marin +Date: Thu, 4 Oct 2018 22:52:35 +0000 +Subject: [PATCH 31/39] Fix mmap region iteration while no regions are + recorded. + +If no mmap regions are recorded, iteration failed since the RegionSet +(std::set) object is not initialized. + +Original CL https://codereview.chromium.org/14769008 + +Reviewed-on: https://chromium-review.googlesource.com/c/1130807 +--- + src/memory_region_map.cc | 19 +++++++++++++------ + src/memory_region_map.h | 3 +++ + 2 files changed, 16 insertions(+), 6 deletions(-) + mode change 100755 => 100644 src/memory_region_map.cc + +diff --git a/src/memory_region_map.cc b/src/memory_region_map.cc +old mode 100755 +new mode 100644 +index 841d6f3..06b6fb0 +--- a/src/memory_region_map.cc ++++ b/src/memory_region_map.cc +@@ -234,6 +234,9 @@ void MemoryRegionMap::Init(int max_stack_depth, bool use_buckets) { + memset(bucket_table_, 0, table_bytes); + num_buckets_ = 0; + } ++ if (regions_ == NULL) { // init regions_ ++ InitRegionSetLocked(); ++ } + Unlock(); + RAW_VLOG(10, "MemoryRegionMap Init done"); + } +@@ -536,6 +539,15 @@ void MemoryRegionMap::RestoreSavedBucketsLocked() { + } + } + ++inline void MemoryRegionMap::InitRegionSetLocked() { ++ RAW_VLOG(12, "Initializing region set"); ++ regions_ = regions_rep.region_set(); ++ recursive_insert = true; ++ new (regions_) RegionSet(); ++ HandleSavedRegionsLocked(&DoInsertRegionLocked); ++ recursive_insert = false; ++} ++ + inline void MemoryRegionMap::InsertRegionLocked(const Region& region) { + RAW_CHECK(LockIsHeld(), "should be held (by this thread)"); + // We can be called recursively, because RegionSet constructor +@@ -556,12 +568,7 @@ inline void MemoryRegionMap::InsertRegionLocked(const Region& region) { + saved_regions[saved_regions_count++] = region; + } else { // not a recusrive call + if (regions_ == NULL) { // init regions_ +- RAW_VLOG(12, "Initializing region set"); +- regions_ = regions_rep.region_set(); +- recursive_insert = true; +- new(regions_) RegionSet(); +- HandleSavedRegionsLocked(&DoInsertRegionLocked); +- recursive_insert = false; ++ InitRegionSetLocked(); + } + recursive_insert = true; + // Do the actual insertion work to put new regions into regions_: +diff --git a/src/memory_region_map.h b/src/memory_region_map.h +index ec388e1..f774994 100644 +--- a/src/memory_region_map.h ++++ b/src/memory_region_map.h +@@ -362,6 +362,9 @@ class MemoryRegionMap { + // table where all buckets eventually should be. + static void RestoreSavedBucketsLocked(); + ++ // Initialize RegionSet regions_. ++ inline static void InitRegionSetLocked(); ++ + // Wrapper around DoInsertRegionLocked + // that handles the case of recursive allocator calls. + inline static void InsertRegionLocked(const Region& region); +-- +1.8.3.1 + diff --git a/Fix-page_heap_test-flakiness.patch b/Fix-page_heap_test-flakiness.patch new file mode 100644 index 0000000..c3c97a4 --- /dev/null +++ b/Fix-page_heap_test-flakiness.patch @@ -0,0 +1,194 @@ +From f2bca77aed83107197abadee0652c39e2c4c73d3 Mon Sep 17 00:00:00 2001 +From: Brian Silverman +Date: Thu, 9 Aug 2018 16:33:39 -0700 +Subject: [PATCH 21/39] Fix page_heap_test flakiness + +After 71fa9f87 (use 2-level page map for 48-bit addresses), there is a +potential for allocs of additional leaves in the middle of the test. +With ASLR enabled on amd64 (without TCMALLOC_SMALL_BUT_SLOW), this +results in the test failing sometimes (< 1% of the time). Instead, make +sure all those leaves are allocated before deciding on the baseline heap +usage in the test. +--- + src/tests/page_heap_test.cc | 79 ++++++++++++++++++++++++++++++++------------- + 1 file changed, 56 insertions(+), 23 deletions(-) + +diff --git a/src/tests/page_heap_test.cc b/src/tests/page_heap_test.cc +index e82a1da..3caacc0 100644 +--- a/src/tests/page_heap_test.cc ++++ b/src/tests/page_heap_test.cc +@@ -6,9 +6,13 @@ + // be found in the LICENSE file. + + #include "config_for_unittests.h" ++ ++#include ++ ++#include ++ + #include "page_heap.h" + #include "system-alloc.h" +-#include + #include "base/logging.h" + #include "common.h" + +@@ -39,33 +43,63 @@ static void CheckStats(const tcmalloc::PageHeap* ph, + } + + static void TestPageHeap_Stats() { +- tcmalloc::PageHeap* ph = new tcmalloc::PageHeap(); ++ std::unique_ptr ph(new tcmalloc::PageHeap()); + + // Empty page heap +- CheckStats(ph, 0, 0, 0); ++ CheckStats(ph.get(), 0, 0, 0); + + // Allocate a span 's1' + tcmalloc::Span* s1 = ph->New(256); +- CheckStats(ph, 256, 0, 0); ++ CheckStats(ph.get(), 256, 0, 0); + + // Split span 's1' into 's1', 's2'. Delete 's2' + tcmalloc::Span* s2 = ph->Split(s1, 128); + ph->Delete(s2); +- CheckStats(ph, 256, 128, 0); ++ CheckStats(ph.get(), 256, 128, 0); + + // Unmap deleted span 's2' + ph->ReleaseAtLeastNPages(1); +- CheckStats(ph, 256, 0, 128); ++ CheckStats(ph.get(), 256, 0, 128); + + // Delete span 's1' + ph->Delete(s1); +- CheckStats(ph, 256, 128, 128); ++ CheckStats(ph.get(), 256, 128, 128); ++} + +- delete ph; ++// The number of kMaxPages-sized Spans we will allocate and free during the ++// tests. ++// We will also do twice this many kMaxPages/2-sized ones. ++static constexpr int kNumberMaxPagesSpans = 10; ++ ++// Allocates all the last-level page tables we will need. Doing this before ++// calculating the base heap usage is necessary, because otherwise if any of ++// these are allocated during the main test it will throw the heap usage ++// calculations off and cause the test to fail. ++static void AllocateAllPageTables() { ++ // Make a separate PageHeap from the main test so the test can start without ++ // any pages in the lists. ++ std::unique_ptr ph(new tcmalloc::PageHeap()); ++ tcmalloc::Span *spans[kNumberMaxPagesSpans * 2]; ++ for (int i = 0; i < kNumberMaxPagesSpans; ++i) { ++ spans[i] = ph->New(kMaxPages); ++ EXPECT_NE(spans[i], NULL); ++ } ++ for (int i = 0; i < kNumberMaxPagesSpans; ++i) { ++ ph->Delete(spans[i]); ++ } ++ for (int i = 0; i < kNumberMaxPagesSpans * 2; ++i) { ++ spans[i] = ph->New(kMaxPages >> 1); ++ EXPECT_NE(spans[i], NULL); ++ } ++ for (int i = 0; i < kNumberMaxPagesSpans * 2; ++i) { ++ ph->Delete(spans[i]); ++ } + } + + static void TestPageHeap_Limit() { +- tcmalloc::PageHeap* ph = new tcmalloc::PageHeap(); ++ AllocateAllPageTables(); ++ ++ std::unique_ptr ph(new tcmalloc::PageHeap()); + + CHECK_EQ(kMaxPages, 1 << (20 - kPageShift)); + +@@ -77,25 +111,26 @@ static void TestPageHeap_Limit() { + while((s = ph->New(kMaxPages)) == NULL) { + FLAGS_tcmalloc_heap_limit_mb++; + } +- FLAGS_tcmalloc_heap_limit_mb += 9; ++ FLAGS_tcmalloc_heap_limit_mb += kNumberMaxPagesSpans - 1; + ph->Delete(s); + // We are [10, 11) mb from the limit now. + } + + // Test AllocLarge and GrowHeap first: + { +- tcmalloc::Span * spans[10]; +- for (int i=0; i<10; ++i) { ++ tcmalloc::Span * spans[kNumberMaxPagesSpans]; ++ for (int i=0; iNew(kMaxPages); + EXPECT_NE(spans[i], NULL); + } + EXPECT_EQ(ph->New(kMaxPages), NULL); + +- for (int i=0; i<10; i += 2) { ++ for (int i=0; iDelete(spans[i]); + } + +- tcmalloc::Span *defragmented = ph->New(5 * kMaxPages); ++ tcmalloc::Span *defragmented = ++ ph->New(kNumberMaxPagesSpans / 2 * kMaxPages); + + if (HaveSystemRelease) { + // EnsureLimit should release deleted normal spans +@@ -109,15 +144,15 @@ static void TestPageHeap_Limit() { + EXPECT_TRUE(ph->CheckExpensive()); + } + +- for (int i=1; i<10; i += 2) { ++ for (int i=1; iDelete(spans[i]); + } + } + + // Once again, testing small lists this time (twice smaller spans): + { +- tcmalloc::Span * spans[20]; +- for (int i=0; i<20; ++i) { ++ tcmalloc::Span * spans[kNumberMaxPagesSpans * 2]; ++ for (int i=0; iNew(kMaxPages >> 1); + EXPECT_NE(spans[i], NULL); + } +@@ -125,12 +160,12 @@ static void TestPageHeap_Limit() { + tcmalloc::Span * lastHalf = ph->New(kMaxPages >> 1); + EXPECT_EQ(ph->New(kMaxPages >> 1), NULL); + +- for (int i=0; i<20; i += 2) { ++ for (int i=0; iDelete(spans[i]); + } + +- for(Length len = kMaxPages >> 2; len < 5 * kMaxPages; len = len << 1) +- { ++ for (Length len = kMaxPages >> 2; ++ len < kNumberMaxPagesSpans / 2 * kMaxPages; len = len << 1) { + if(len <= kMaxPages >> 1 || HaveSystemRelease) { + tcmalloc::Span *s = ph->New(len); + EXPECT_NE(s, NULL); +@@ -140,7 +175,7 @@ static void TestPageHeap_Limit() { + + EXPECT_TRUE(ph->CheckExpensive()); + +- for (int i=1; i<20; i += 2) { ++ for (int i=1; iDelete(spans[i]); + } + +@@ -148,8 +183,6 @@ static void TestPageHeap_Limit() { + ph->Delete(lastHalf); + } + } +- +- delete ph; + } + + } // namespace +-- +1.8.3.1 + diff --git a/Fix-uninitialized-memory-use-in-sampler_test.patch b/Fix-uninitialized-memory-use-in-sampler_test.patch new file mode 100644 index 0000000..f3237c2 --- /dev/null +++ b/Fix-uninitialized-memory-use-in-sampler_test.patch @@ -0,0 +1,31 @@ +From 0b588e7490eac4ef37b59c9265f1f3f05f4bb27c Mon Sep 17 00:00:00 2001 +From: Brian Silverman +Date: Tue, 31 Jul 2018 15:53:47 -0700 +Subject: [PATCH 05/39] Fix uninitialized memory use in sampler_test + +Sampler's documentation states the following: + C++03 requires that types stored in TLS be POD. As a result, you must + initialize these members to {0, 0, false} before using this class! + +However, the test code wasn't doing that. MemorySanitizer and +UndefinedBehaviorSanitizer both failed because of it. +--- + src/tests/sampler_test.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/tests/sampler_test.cc b/src/tests/sampler_test.cc +index e0d24d4..9a55b70 100755 +--- a/src/tests/sampler_test.cc ++++ b/src/tests/sampler_test.cc +@@ -361,7 +361,7 @@ double StandardDeviationsErrorInSample( + } + + TEST(Sampler, LargeAndSmallAllocs_CombinedTest) { +- tcmalloc::Sampler sampler; ++ tcmalloc::Sampler sampler{0, 0, false}; + sampler.Init(1); + int counter_big = 0; + int counter_small = 0; +-- +1.8.3.1 + diff --git a/Format-and-fix-out-of-bound-access-in-CpuProfilerSwi.patch b/Format-and-fix-out-of-bound-access-in-CpuProfilerSwi.patch new file mode 100644 index 0000000..d2f8c43 --- /dev/null +++ b/Format-and-fix-out-of-bound-access-in-CpuProfilerSwi.patch @@ -0,0 +1,79 @@ +From 8dd304035848e780372a5a4bb1afac2b2d20bc43 Mon Sep 17 00:00:00 2001 +From: Aliaksey Kandratsenka +Date: Sun, 5 Aug 2018 19:52:11 -0700 +Subject: [PATCH 18/39] Format and fix out of bound access in CpuProfilerSwitch + +GCC was giving warning on snprintf and it hinted at base_profile_name +and full_profile_name not being long enough. + +Fix is to ensure base_profile_name is long enough for PATH_MAX and +that full_profile_name is enough longer to fit extra chars. +--- + src/profiler.cc | 49 +++++++++++++++++++++++-------------------------- + 1 file changed, 23 insertions(+), 26 deletions(-) + +diff --git a/src/profiler.cc b/src/profiler.cc +index f4f5990..3bd0ed9 100644 +--- a/src/profiler.cc ++++ b/src/profiler.cc +@@ -144,34 +144,31 @@ class CpuProfiler { + // number is defined in the environment variable CPUPROFILESIGNAL. + static void CpuProfilerSwitch(int signal_number) + { +- bool static started = false; +- static unsigned profile_count = 0; +- static char base_profile_name[1024] = "\0"; +- +- if (base_profile_name[0] == '\0') { +- if (!GetUniquePathFromEnv("CPUPROFILE", base_profile_name)) { +- RAW_LOG(FATAL,"Cpu profiler switch is registered but no CPUPROFILE is defined"); +- return; +- } +- } +- if (!started) +- { +- char full_profile_name[1024]; +- +- snprintf(full_profile_name, sizeof(full_profile_name), "%s.%u", +- base_profile_name, profile_count++); +- +- if(!ProfilerStart(full_profile_name)) +- { +- RAW_LOG(FATAL, "Can't turn on cpu profiling for '%s': %s\n", +- full_profile_name, strerror(errno)); +- } ++ static unsigned profile_count; ++ static char base_profile_name[PATH_MAX]; ++ static bool started = false; ++ ++ if (base_profile_name[0] == '\0') { ++ if (!GetUniquePathFromEnv("CPUPROFILE", base_profile_name)) { ++ RAW_LOG(FATAL,"Cpu profiler switch is registered but no CPUPROFILE is defined"); ++ return; + } +- else +- { +- ProfilerStop(); ++ } ++ ++ if (!started) { ++ char full_profile_name[PATH_MAX + 16]; ++ ++ snprintf(full_profile_name, sizeof(full_profile_name), "%s.%u", ++ base_profile_name, profile_count++); ++ ++ if(!ProfilerStart(full_profile_name)) { ++ RAW_LOG(FATAL, "Can't turn on cpu profiling for '%s': %s\n", ++ full_profile_name, strerror(errno)); + } +- started = !started; ++ } else { ++ ProfilerStop(); ++ } ++ started = !started; + } + + // Profile data structure singleton: Constructor will check to see if +-- +1.8.3.1 + diff --git a/Use-initial-exec-TLS-model-for-all-thread-local-vari.patch b/Use-initial-exec-TLS-model-for-all-thread-local-vari.patch new file mode 100644 index 0000000..90a8dd7 --- /dev/null +++ b/Use-initial-exec-TLS-model-for-all-thread-local-vari.patch @@ -0,0 +1,71 @@ +From 1e36ed705548ae2a5170bb00dfee0954b8ef76de Mon Sep 17 00:00:00 2001 +From: Romain Geissler +Date: Tue, 29 Jan 2019 18:31:19 +0000 +Subject: [PATCH 38/39] Use initial exec TLS model for all thread local + variables from thread_cache.cc + +This avoids a deadlock when a library which is being dlopen'ed creates +as part of its static constructors a thread which quickly need to call +malloc. We are still in the dlopen call (so with some internal glibc +mutex taken) when the thread executes code and later needs to call +malloc which in term calls tls_get_addr_tail, which wait for the dlopen +mutex to be unlocked. If later the dlopen'ing thread also calls malloc +as part of its constructors, we are in a deadlock. + +Fix is similar to +https://github.com/gperftools/gperftools/commit/7852eeb75b9375cf52a7da01be044da6e915dd08 + +Stack of the dlopening thread: + #0 0x00007fd5406ca93c in __lll_lock_wait () from /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/libpthread.so.0 + #1 0x00007fd5406c45a5 in pthread_mutex_lock () from /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/libpthread.so.0 + ... proprietary code in the stack + #9 0x00007fd5074f0367 in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at src/ClientImpl.cpp:15 + #10 0x00007fd5074f06d7 in _GLOBAL__sub_I_ClientImpl.cpp(void) () at src/ClientImpl.cpp:85 + #11 0x00007fd50757aa46 in __do_global_ctors_aux () + #12 0x00007fd5073e985f in _init () from ... + #13 0x00007fd53bf9dec8 in ?? () from ... + #14 0x00007fd54d637a5d in call_init.part () from /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/ld-linux-x86-64.so.2 + #15 0x00007fd54d637bab in _dl_init () from /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/ld-linux-x86-64.so.2 + #16 0x00007fd54d63c160 in dl_open_worker () from /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/ld-linux-x86-64.so.2 + #17 0x00007fd54d637944 in _dl_catch_error () from /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/ld-linux-x86-64.so.2 + #18 0x00007fd54d63b7d9 in _dl_open () from /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/ld-linux-x86-64.so.2 + #19 0x00007fd54d61f2b9 in dlopen_doit () from /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/libdl.so.2 + #20 0x00007fd54d637944 in _dl_catch_error () from /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/ld-linux-x86-64.so.2 + #21 0x00007fd54d61f889 in _dlerror_run () from /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/libdl.so.2 + #22 0x00007fd54d61f351 in dlopen@@GLIBC_2.2.5 () from /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/libdl.so.2 + +Stack of the newly created thread calling tls_get_addr_tail: + #0 0x00007fd5406ca93c in __lll_lock_wait () from /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/libpthread.so.0 + #1 0x00007fd5406c4622 in pthread_mutex_lock () from /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/libpthread.so.0 + #2 0x00007fd54d63a2ed in tls_get_addr_tail () from /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/ld-linux-x86-64.so.2 + #3 0x00007fd53fee877d in tcmalloc::ThreadCache::CreateCacheIfNecessary () at src/thread_cache.cc:344 + #4 0x00007fd53fecb4ab in tcmalloc::ThreadCache::GetCache () at src/thread_cache.h:437 + #5 0x00007fd53fefeccb in (anonymous namespace)::do_malloc (size=56) at src/tcmalloc.cc:1354 + #6 tcmalloc::do_allocate_full (size=56) at src/tcmalloc.cc:1762 + #7 tcmalloc::allocate_full_cpp_throw_oom (size=56) at src/tcmalloc.cc:1776 + #8 0x00007fd53ff01b80 in tcmalloc::dispatch_allocate_full (size=56) at src/tcmalloc.cc:1785 + #9 malloc_fast_path (size=56) at src/tcmalloc.cc:1845 + #10 tc_new (size=56) at src/tcmalloc.cc:1980 + ... proprietary code in the stack + #26 0x00007fd5406c1ef4 in start_thread () from /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/libpthread.so.0 + #27 0x00007fd5403ba01d in clone () from /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/libc.so.6 +--- + src/thread_cache.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/thread_cache.cc b/src/thread_cache.cc +index 6d2f832..97f3ffe 100644 +--- a/src/thread_cache.cc ++++ b/src/thread_cache.cc +@@ -334,7 +334,7 @@ ThreadCache* ThreadCache::CreateCacheIfNecessary() { + + bool seach_condition = true; + #ifdef HAVE_TLS +- static __thread ThreadCache** current_heap_ptr; ++ static __thread ThreadCache** current_heap_ptr ATTR_INITIAL_EXEC; + if (tsd_inited_) { + // In most common case we're avoiding expensive linear search + // through all heaps (see below). Working TLS enables faster +-- +1.8.3.1 + diff --git a/Use-standard-conforming-alignof-in-debugallocation.c.patch b/Use-standard-conforming-alignof-in-debugallocation.c.patch new file mode 100644 index 0000000..2bd431a --- /dev/null +++ b/Use-standard-conforming-alignof-in-debugallocation.c.patch @@ -0,0 +1,29 @@ +From c41688bf20186723367b560ceb539b2330951ddb Mon Sep 17 00:00:00 2001 +From: Aliaksey Kandratsenka +Date: Sun, 5 Aug 2018 20:39:07 -0700 +Subject: [PATCH 20/39] Use standard-conforming alignof in debugallocation.cc + +Clang was giving warning that alignof() is extension. So +we're now doing alignof of decltype. +--- + src/debugallocation.cc | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/debugallocation.cc b/src/debugallocation.cc +index 7c438f2..39dea5a 100644 +--- a/src/debugallocation.cc ++++ b/src/debugallocation.cc +@@ -1152,8 +1152,8 @@ static union { + + REGISTER_MODULE_INITIALIZER(debugallocation, { + #if (__cplusplus >= 201103L) +- COMPILE_ASSERT(alignof(debug_malloc_implementation_space) >= alignof(DebugMallocImplementation), +- debug_malloc_implementation_space_is_not_properly_aligned); ++ static_assert(alignof(decltype(debug_malloc_implementation_space)) >= alignof(DebugMallocImplementation), ++ "DebugMallocImplementation is expected to need just word alignment"); + #endif + // Either we or valgrind will control memory management. We + // register our extension if we're the winner. Otherwise let +-- +1.8.3.1 + diff --git a/benchmark-use-angle-brackets-to-include-ucontext.h.patch b/benchmark-use-angle-brackets-to-include-ucontext.h.patch new file mode 100644 index 0000000..27ac302 --- /dev/null +++ b/benchmark-use-angle-brackets-to-include-ucontext.h.patch @@ -0,0 +1,26 @@ +From 3af509d4f91aa1fae3f8caeb17b158f20e9b5e59 Mon Sep 17 00:00:00 2001 +From: Gabriel Marin +Date: Tue, 17 Jul 2018 18:28:01 -0700 +Subject: [PATCH 13/39] benchmark: use angle brackets to include ucontext.h + +Using quotes for a system header file fails a presubmit check in Chromium. +--- + benchmark/unwind_bench.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/benchmark/unwind_bench.cc b/benchmark/unwind_bench.cc +index f919fc0..9c4e2f8 100644 +--- a/benchmark/unwind_bench.cc ++++ b/benchmark/unwind_bench.cc +@@ -7,7 +7,7 @@ + #include + #include + #include +-#include "sys/ucontext.h" ++#include + #if HAVE_LIBUNWIND_H + #include + #endif +-- +1.8.3.1 + diff --git a/don-t-try-to-mark-rsp-as-clobbered-in-linux-syscall-.patch b/don-t-try-to-mark-rsp-as-clobbered-in-linux-syscall-.patch new file mode 100644 index 0000000..170567f --- /dev/null +++ b/don-t-try-to-mark-rsp-as-clobbered-in-linux-syscall-.patch @@ -0,0 +1,30 @@ +From 9e5b1628737c67b4587f937164572774592978c4 Mon Sep 17 00:00:00 2001 +From: Aliaksey Kandratsenka +Date: Sun, 10 Feb 2019 12:46:18 -0800 +Subject: [PATCH 39/39] don't try to mark rsp as clobbered in linux syscall + support + +rsp is not actually clobbered by that code and later gccs actually (correctly) bark +at it. + +Fixed issue #1076. +--- + src/base/linux_syscall_support.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/base/linux_syscall_support.h b/src/base/linux_syscall_support.h +index 13aa415..199061a 100644 +--- a/src/base/linux_syscall_support.h ++++ b/src/base/linux_syscall_support.h +@@ -1485,7 +1485,7 @@ struct kernel_stat { + "d"(LSS_SYSCALL_ARG(parent_tidptr)), + "r"(LSS_SYSCALL_ARG(newtls)), + "r"(LSS_SYSCALL_ARG(child_tidptr)) +- : "rsp", "memory", "r8", "r10", "r11", "rcx"); ++ : "memory", "r8", "r10", "r11", "rcx"); + } + LSS_RETURN(int, __res); + } +-- +1.8.3.1 + diff --git a/gperftools-2.6.1-disable-generic-dynamic-tls.patch b/gperftools-2.6.1-disable-generic-dynamic-tls.patch new file mode 100644 index 0000000..ae87e5d --- /dev/null +++ b/gperftools-2.6.1-disable-generic-dynamic-tls.patch @@ -0,0 +1,32 @@ +diff -up ./configure.ac.dynload ./configure.ac +--- ./configure.ac.dynload 2017-08-24 15:23:01.126622099 -0400 ++++ ./configure.ac 2017-08-24 15:29:46.332132222 -0400 +@@ -614,6 +614,16 @@ AC_COMPILE_IFELSE( + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])]) + ++default_enable_generic_dynamic_tls=yes ++AC_ARG_ENABLE([general-dynamic-tls], ++ [AS_HELP_STRING([--disable-general-dynamic-tls], ++ [Do not use the general dynamic TLS model])], ++ [], ++ [enable_generic_dynamic_tls="$default_enable_generic_dynamic_tls"]) ++AS_IF([test "x$enable_generic_dynamic_tls" = xyes], ++ [AC_DEFINE([ENABLE_GENERIC_DYNAMIC_TLS], 1, ++ [Use the generic dynamic TLS model])]) ++ + # Write generated configuration file + AC_CONFIG_FILES([Makefile + src/gperftools/tcmalloc.h src/windows/gperftools/tcmalloc.h]) +diff -up ./src/base/basictypes.h.dynload ./src/base/basictypes.h +--- ./src/base/basictypes.h.dynload 2017-08-24 15:30:30.210996293 -0400 ++++ ./src/base/basictypes.h 2017-08-24 15:31:01.889176214 -0400 +@@ -200,7 +200,7 @@ struct CompileAssert { + # define ATTRIBUTE_UNUSED + #endif + +-#if defined(HAVE___ATTRIBUTE__) && defined(HAVE_TLS) ++#if defined(HAVE___ATTRIBUTE__) && defined(HAVE_TLS) && defined(ENABLE_GENERIC_DYNAMIC_TLS) + #define ATTR_INITIAL_EXEC __attribute__ ((tls_model ("initial-exec"))) + #else + #define ATTR_INITIAL_EXEC diff --git a/gperftools-2.7.tar.gz b/gperftools-2.7.tar.gz new file mode 100644 index 0000000..e0a82a2 Binary files /dev/null and b/gperftools-2.7.tar.gz differ diff --git a/gperftools.spec b/gperftools.spec new file mode 100644 index 0000000..c5bff35 --- /dev/null +++ b/gperftools.spec @@ -0,0 +1,131 @@ +Name: gperftools +Version: 2.7 +Release: 5 +Summary: high-performance malloc and performance analysis tools + +License: BSD +URL: https://github.com/gperftools/gperftools +Source0: https://github.com/gperftools/gperftools/releases/download/%{name}-%{version}/%{name}-%{version}.tar.gz +Patch1: gperftools-2.6.1-disable-generic-dynamic-tls.patch +Patch2: Disable-large-allocation-report-by-default.patch +Patch3: Fix-uninitialized-memory-use-in-sampler_test.patch +Patch4: benchmark-use-angle-brackets-to-include-ucontext.h.patch +Patch5: Format-and-fix-out-of-bound-access-in-CpuProfilerSwi.patch +Patch6: Fix-incompatible-aliasing-warnings.patch +Patch7: Use-standard-conforming-alignof-in-debugallocation.c.patch +Patch8: Fix-page_heap_test-flakiness.patch +Patch9: Avoid-static-initialization-of-pprof-path-for-symbol.patch +Patch10: Fix-mmap-region-iteration-while-no-regions-are-recor.patch +Patch11: Drop-not-very-portable-and-not-very-useful-unwind-be.patch +Patch12: undef-mmap64-function.patch +Patch13: Use-initial-exec-TLS-model-for-all-thread-local-vari.patch +Patch14: don-t-try-to-mark-rsp-as-clobbered-in-linux-syscall-.patch + +Patch9000: issue-1122-fix-bus-error-on-aarch64.patch + +BuildRequires: autoconf automake gcc-c++ libtool libunwind-devel perl-generators +Requires: %{name}-devel = %{version}-%{release} +Requires: pprof = %{version}-%{release} + +ExcludeArch: s390 + +%description +gperftools is a collection of a high-performance multi-threaded \ +malloc() implementation, plus some pretty nifty performance analysis \ +tools. + +%package libs +Summary: Libraries for CPU profiler and tcmalloc +Provides: google-perftools-libs = %{version}-%{release} +Obsoletes: google-perftools-libs < 2.0 + +%description libs +This package contains libraries with CPU or heap profiling and thread-caching +malloc(). + +%package devel +Summary: Development header files +Requires: pkg-config +Requires: %{name}-libs = %{version}-%{release} +Provides: google-perftools-devel = %{version}-%{release} +Provides: pkg-config(gperftools-devel) = %{version}-%{release} +Obsoletes: google-perftools-devel < 2.0 + +%description devel +This package contains Development header files with CPU or heap profiling and +thread-caching malloc() which provides by google and gperftools. + +%package -n pprof +Summary: Analyzes CPU and heap profiles tools +Requires: gv graphviz perl +BuildArch: noarch +Provides: pprof = %{version}-%{release} +Provides: google-perftools = %{version}-%{release} +Obsoletes: google-perftools < 2.0 + +%description -n pprof +pprof is an facility that analyzes CPU and heap profiles. + +%prep +%autosetup -n %{name}-%{version} -p1 + +%build +autoreconf -vif + +CFLAGS=`echo $RPM_OPT_FLAGS -fno-strict-aliasing -Wno-unused-local-typedefs -DTCMALLOC_LARGE_PAGES | sed -e 's|-fexceptions||g'` +CXXFLAGS=`echo $RPM_OPT_FLAGS -fno-strict-aliasing -Wno-unused-local-typedefs -DTCMALLOC_LARGE_PAGES | sed -e 's|-fexceptions||g'` + +%configure \ +%ifarch s390x aarch64 + --disable-general-dynamic-tls \ +%endif + --disable-dynamic-sized-delete-support \ + +%disable_rpath + +make + +%install +%make_install + +%ldconfig_scriptlets libs + +%files +#nothing to do + +%files libs +%{_libdir}/libprofiler.so.* +%{_libdir}/libtcmalloc*.so.* + +%files devel +%{_includedir}/google/*.h +%{_includedir}/gperftools/*.h +%{_libdir}/libprofiler.so +%{_libdir}/libtcmalloc*.so +%{_libdir}/pkgconfig/*.pc +%{_docdir}/%{name}/* +%{_libdir}/libprofiler.*a +%{_libdir}/libtcmalloc*.*a + +%files -n pprof +%{_bindir}/* +%{_mandir}/man1/*.1.gz + +%changelog +* Thu Aug 29 2019 luochunsheng - 2.7-5 +- fix spelling errors + +* Mon Jun 17 2019 Zhipeng Xie - 2.7-4 +- Type:bugfix +- ID:NA +- SUG: NA +- DESC: issue-1122: fix bus error on aarch64 + +* Mon Apr 15 2019 lvying - 2.7-3 +- Type:enhancement +- ID:NA +- SUG: NA +- DESC: peripheral package quality reinforcement: backport bugfix patches from community + +* Tue Mar 5 2019 openEuler Buildteam - 2.7-2 +- Package init diff --git a/issue-1122-fix-bus-error-on-aarch64.patch b/issue-1122-fix-bus-error-on-aarch64.patch new file mode 100644 index 0000000..3ba360d --- /dev/null +++ b/issue-1122-fix-bus-error-on-aarch64.patch @@ -0,0 +1,42 @@ +From 42dbe9e2ced74ae7f0f3b70daabf634edf44d3d3 Mon Sep 17 00:00:00 2001 +From: Zhipeng Xie +Date: Thu, 13 Jun 2019 23:16:43 +0800 +Subject: [PATCH] issue-1122: fix bus error on aarch64 + +According to the ARMv8 Instruction Set Overview, among other documents, +"... if SP is used as the base register then the value of the stack +pointer prior to adding any offset must be quadword (16 byte) aligned, +or else a stack alignment exception will be generated.". So, we pass +the child_stack 16 byte aligned to sys_clone. + +Signed-off-by: Zhipeng Xie +--- + src/base/linuxthreads.cc | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/base/linuxthreads.cc b/src/base/linuxthreads.cc +index 891e70c..00b1ea3 100644 +--- a/src/base/linuxthreads.cc ++++ b/src/base/linuxthreads.cc +@@ -105,6 +105,7 @@ static int local_clone (int (*fn)(void *), void *arg, ...) + #define CLONE_STACK_SIZE 4096 + #endif + ++#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) + static int local_clone (int (*fn)(void *), void *arg, ...) { + /* Leave 4kB of gap between the callers stack and the new clone. This + * should be more than sufficient for the caller to call waitpid() until +@@ -120,7 +121,9 @@ static int local_clone (int (*fn)(void *), void *arg, ...) { + * is being debugged. This is OK and the error code will be reported + * correctly. + */ +- return sys_clone(fn, (char *)&arg - CLONE_STACK_SIZE, ++ void *child_stack = (void *)ALIGN(((unsigned long)&arg - CLONE_STACK_SIZE), ++ 16); ++ return sys_clone(fn, child_stack, + CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_UNTRACED, arg, 0, 0, 0); + } + +-- +1.7.12.4 + diff --git a/undef-mmap64-function.patch b/undef-mmap64-function.patch new file mode 100644 index 0000000..7296652 --- /dev/null +++ b/undef-mmap64-function.patch @@ -0,0 +1,44 @@ +From e9ab4c53041ac62feefbbb076d326e9a77dd1567 Mon Sep 17 00:00:00 2001 +From: Fabrice Fontaine +Date: Sun, 7 Oct 2018 18:12:03 +0200 +Subject: [PATCH 34/39] undef mmap64 function +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +mmap64 can already been defined and as a result the following error is +raised: + +In file included from src/malloc_hook.cc:686:0: +src/malloc_hook_mmap_linux.h: In function ‘void* mmap(void*, size_t, int, int, int, off_t)’: +src/malloc_hook_mmap_linux.h:173:18: error: redefinition of ‘void* mmap(void*, size_t, int, int, int, off_t)’ + extern "C" void* mmap(void *start, size_t length, int prot, int flags, + ^~~~ +In file included from src/malloc_hook.cc:41:0: +src/malloc_hook_mmap_linux.h:159:18: note: ‘void* mmap(void*, size_t, int, int, int, off_t)’ previously defined here + extern "C" void* mmap64(void *start, size_t length, int prot, int flags, + ^ +Makefile:4874: recipe for target 'src/libtcmalloc_minimal_internal_la-malloc_hook.lo' failed + +Signed-off-by: Fabrice Fontaine +--- + src/malloc_hook_mmap_linux.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/malloc_hook_mmap_linux.h b/src/malloc_hook_mmap_linux.h +index 0eec895..34de715 100644 +--- a/src/malloc_hook_mmap_linux.h ++++ b/src/malloc_hook_mmap_linux.h +@@ -137,7 +137,8 @@ static inline void* do_mmap64(void *start, size_t length, + // malloc_hook section, + // so that MallocHook::GetCallerStackTrace can function accurately: + +-// Make sure mmap doesn't get #define'd away by ++// Make sure mmap64 and mmap doesn't get #define'd away by ++# undef mmap64 + # undef mmap + + extern "C" { +-- +1.8.3.1 +