mirror of
https://github.com/gperftools/gperftools
synced 2025-03-10 14:57:33 +00:00
amputate maybe_threads
This facility allowed us to build tcmalloc without linking in actual -lpthread. Via weak symbols we checked at runtime if pthread functions are available and if not, special single-threaded stubs were used instead. Not always brining in pthread dependency helped performance of some programs or libraries which depended at runtime on whether threads are linked or not. Most notable of those are libstdc++ which uses non-atomic refcounting on single threaded programs. But such optional dependency on pthreads caused complications for nearly no benefit. One trouble was reported in github issue #1110. This days glibc/libstdc++ combo actually depends on sys/single_threaded.h facility. So bringing pthread at runtime is fine. Also modern glibc ships pthread symbols inside libc anyways and libpthread is empty. I also found that for whatever reason on BSDs and osx we already pulled in proper pthreads too. So we loose nothing and we get issue #1110 fixed. And we simplify everything.
This commit is contained in:
parent
3cd265b05a
commit
46d3315ad7
1
.gitignore
vendored
1
.gitignore
vendored
@ -77,7 +77,6 @@
|
||||
/malloc_hook_test.exe
|
||||
/markidle_unittest
|
||||
/markidle_unittest.exe
|
||||
/maybe_threads_unittest.sh
|
||||
/memalign_debug_unittest
|
||||
/memalign_unittest
|
||||
/missing
|
||||
|
@ -410,12 +410,6 @@ if(EXISTS /usr/sfw/lib/libstdc++.la)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
check_cxx_source_compiles(
|
||||
"#include <string>
|
||||
#include <vector>
|
||||
int main() { pthread_t th; pthread_join(th, 0); return 0; }"
|
||||
have_pthread_despite_asking_for)
|
||||
|
||||
check_variable_exists("program_invocation_name" HAVE_PROGRAM_INVOCATION_NAME)
|
||||
|
||||
if(MINGW)
|
||||
@ -572,10 +566,6 @@ if(MINGW OR MSVC)
|
||||
# (We do this via a #pragma for msvc, but need to do it here for mingw).
|
||||
target_link_libraries(sysinfo shlwapi)
|
||||
|
||||
if(have_pthread_despite_asking_for)
|
||||
add_library(maybe_threads STATIC src/maybe_threads.cc)
|
||||
set(maybe_threads_lib maybe_threads)
|
||||
endif()
|
||||
else()
|
||||
set(SPINLOCK_INCLUDES src/base/spinlock.h
|
||||
src/base/spinlock_internal.h)
|
||||
@ -588,8 +578,6 @@ else()
|
||||
set(TCMALLOC_CC "src/tcmalloc.cc")
|
||||
set(SYSTEM_ALLOC_CC "src/system-alloc.cc")
|
||||
|
||||
add_library(maybe_threads STATIC src/maybe_threads.cc)
|
||||
set(maybe_threads_lib maybe_threads)
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTING)
|
||||
@ -614,7 +602,7 @@ if(BUILD_TESTING)
|
||||
# By default, MallocHook takes stack traces for use by the heap-checker.
|
||||
# We don't need that functionality here, so we turn it off to reduce deps.
|
||||
target_compile_definitions(low_level_alloc_unittest PRIVATE NO_TCMALLOC_SAMPLES)
|
||||
target_link_libraries(low_level_alloc_unittest spinlock sysinfo logging ${maybe_threads_lib})
|
||||
target_link_libraries(low_level_alloc_unittest spinlock sysinfo logging)
|
||||
add_test(low_level_alloc_unittest low_level_alloc_unittest)
|
||||
endif()
|
||||
|
||||
@ -745,7 +733,7 @@ add_library(tcmalloc_minimal_internal_object OBJECT ${libtcmalloc_minimal_intern
|
||||
# We #define NO_TCMALLOC_SAMPLES, since sampling is turned off for _minimal.
|
||||
target_compile_definitions(tcmalloc_minimal_internal_object PRIVATE NO_TCMALLOC_SAMPLES NO_HEAP_CHECK NDEBUG)
|
||||
add_library(tcmalloc_minimal_internal INTERFACE)
|
||||
target_link_libraries(tcmalloc_minimal_internal INTERFACE ${LIBSPINLOCK} ${maybe_threads_lib})
|
||||
target_link_libraries(tcmalloc_minimal_internal INTERFACE ${LIBSPINLOCK})
|
||||
target_sources(tcmalloc_minimal_internal INTERFACE $<TARGET_OBJECTS:tcmalloc_minimal_internal_object>)
|
||||
|
||||
set(libtcmalloc_minimal_la_SOURCES ${TCMALLOC_CC} ${TCMALLOC_MINIMAL_INCLUDES})
|
||||
@ -815,13 +803,6 @@ if(BUILD_TESTING)
|
||||
tcmalloc_minimal_large_heap_fragmentation_unittest PUBLIC tcmalloc_minimal)
|
||||
add_test(tcmalloc_minimal_large_heap_fragmentation_unittest tcmalloc_minimal_large_heap_fragmentation_unittest)
|
||||
|
||||
if(BUILD_SHARED_LIBS AND NOT MINGW)
|
||||
add_custom_target(maybe_threads_unittest
|
||||
COMMAND src/tests/maybe_threads_unittest.sh
|
||||
VERBATIM)
|
||||
add_test(maybe_threads_unittest maybe_threads_unittest)
|
||||
endif()
|
||||
|
||||
if(MINGW OR MSVC)
|
||||
set(port_src src/windows/port.cc)
|
||||
endif()
|
||||
@ -1064,7 +1045,7 @@ if(GPERFTOOLS_BUILD_HEAP_CHECKER OR GPERFTOOLS_BUILD_HEAP_PROFILER)
|
||||
|
||||
set(libtcmalloc_la_SOURCES ${TCMALLOC_CC} ${TCMALLOC_INCLUDES})
|
||||
set(libtcmalloc_la_DEFINE NDEBUG ${EMERGENCY_MALLOC_DEFINE})
|
||||
set(libtcmalloc_la_LIBADD tcmalloc_internal ${maybe_threads_lib} Threads::Threads)
|
||||
set(libtcmalloc_la_LIBADD tcmalloc_internal Threads::Threads)
|
||||
if(GPERFTOOLS_BUILD_HEAP_CHECKER)
|
||||
# heap-checker-bcad is last, in hopes its global ctor will run first.
|
||||
# (Note this is added to libtcmalloc.la, not libtcmalloc_internal.la,
|
||||
@ -1282,7 +1263,7 @@ if(GPERFTOOLS_BUILD_CPU_PROFILER)
|
||||
src/profile-handler.cc
|
||||
src/profiledata.cc
|
||||
${CPU_PROFILER_INCLUDES})
|
||||
set(libprofiler_la_LIBADD stacktrace ${maybe_threads_lib} fake_stacktrace_scope)
|
||||
set(libprofiler_la_LIBADD stacktrace fake_stacktrace_scope)
|
||||
add_library(profiler SHARED ${libprofiler_la_SOURCES})
|
||||
target_link_libraries(profiler PRIVATE ${libprofiler_la_LIBADD})
|
||||
set_target_properties(profiler PROPERTIES
|
||||
|
2
INSTALL
2
INSTALL
@ -249,7 +249,7 @@ above, by linking in libtcmalloc_minimal.
|
||||
libtcmalloc.so successfully builds, and the "advanced" tcmalloc
|
||||
functionality all works except for the leak-checker, which has
|
||||
Linux-specific code:
|
||||
% make heap-profiler_unittest.sh maybe_threads_unittest.sh \
|
||||
% make heap-profiler_unittest.sh \
|
||||
tcmalloc_unittest tcmalloc_both_unittest \
|
||||
tcmalloc_large_unittest # THESE WORK
|
||||
% make -k heap-checker_unittest.sh \
|
||||
|
44
Makefile.am
44
Makefile.am
@ -168,10 +168,6 @@ libsysinfo_la_SOURCES = src/base/sysinfo.cc \
|
||||
$(SYSINFO_INCLUDES)
|
||||
libsysinfo_la_LIBADD = $(NANOSLEEP_LIBS)
|
||||
|
||||
noinst_LTLIBRARIES += libmaybe_threads.la
|
||||
# .cc is conditionally added below
|
||||
libmaybe_threads_la_SOURCES = src/maybe_threads.h
|
||||
|
||||
# For MinGW, we use also have to use libwindows Luckily, we need the
|
||||
# windows.a library in exactly the same place we need spinlock.a
|
||||
# (pretty much everywhere), so we can use the same variable name for
|
||||
@ -227,10 +223,6 @@ libsysinfo_la_LIBADD += -lshlwapi
|
||||
|
||||
# patch_functions.cc #includes tcmalloc.cc, so no need to link it in.
|
||||
TCMALLOC_CC =
|
||||
# windows has its own system for threads and system memory allocation.
|
||||
if HAVE_PTHREAD_DESPITE_ASKING_FOR
|
||||
libmaybe_threads_la_SOURCES += src/maybe_threads.cc
|
||||
endif
|
||||
SYSTEM_ALLOC_CC =
|
||||
else !MINGW
|
||||
SPINLOCK_INCLUDES = src/base/spinlock.h \
|
||||
@ -245,7 +237,6 @@ libspinlock_la_LIBADD = $(NANOSLEEP_LIBS)
|
||||
LIBSPINLOCK = libspinlock.la libsysinfo.la liblogging.la
|
||||
|
||||
TCMALLOC_CC = src/tcmalloc.cc
|
||||
libmaybe_threads_la_SOURCES += src/maybe_threads.cc
|
||||
SYSTEM_ALLOC_CC = src/system-alloc.cc
|
||||
endif !MINGW
|
||||
|
||||
@ -276,7 +267,7 @@ low_level_alloc_unittest_SOURCES = src/base/low_level_alloc.cc \
|
||||
# By default, MallocHook takes stack traces for use by the heap-checker.
|
||||
# We don't need that functionality here, so we turn it off to reduce deps.
|
||||
low_level_alloc_unittest_CXXFLAGS = -DNO_TCMALLOC_SAMPLES
|
||||
low_level_alloc_unittest_LDADD = $(LIBSPINLOCK) libmaybe_threads.la
|
||||
low_level_alloc_unittest_LDADD = $(LIBSPINLOCK)
|
||||
|
||||
|
||||
### ------- stack trace
|
||||
@ -439,7 +430,7 @@ libtcmalloc_minimal_internal_la_CXXFLAGS = -DNO_TCMALLOC_SAMPLES \
|
||||
-DNDEBUG \
|
||||
$(AM_CXXFLAGS)
|
||||
libtcmalloc_minimal_internal_la_LDFLAGS = $(AM_LDFLAGS)
|
||||
libtcmalloc_minimal_internal_la_LIBADD = $(LIBSPINLOCK) libmaybe_threads.la
|
||||
libtcmalloc_minimal_internal_la_LIBADD = $(LIBSPINLOCK)
|
||||
|
||||
lib_LTLIBRARIES += libtcmalloc_minimal.la
|
||||
WINDOWS_PROJECTS += vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcxproj
|
||||
@ -474,11 +465,9 @@ LIBS_TO_WEAKEN += libtcmalloc_minimal.la
|
||||
## src/malloc_hook_mmap_linux.h \
|
||||
## src/malloc_hook_mmap_freebsd.h \
|
||||
## src/base/basictypes.h \
|
||||
## src/maybe_threads.h
|
||||
## malloc_unittest_SOURCES = src/tests/tcmalloc_unittest.cc \
|
||||
## src/malloc_hook.cc \
|
||||
## src/malloc_extension.cc \
|
||||
## $(MAYBE_THREADS_CC) \
|
||||
## $(MALLOC_UNITTEST_INCLUDES)
|
||||
## malloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
|
||||
## malloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
|
||||
@ -512,7 +501,7 @@ tcm_min_asserts_unittest_SOURCES = src/tests/tcmalloc_unittest.cc \
|
||||
tcm_min_asserts_unittest_CXXFLAGS = -DNO_TCMALLOC_SAMPLES -DNO_HEAP_CHECK \
|
||||
$(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
|
||||
tcm_min_asserts_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS)
|
||||
tcm_min_asserts_unittest_LDADD = $(LIBSPINLOCK) libmaybe_threads.la \
|
||||
tcm_min_asserts_unittest_LDADD = $(LIBSPINLOCK) \
|
||||
liblogging.la $(PTHREAD_LIBS)
|
||||
|
||||
TESTS += tcmalloc_minimal_large_unittest
|
||||
@ -528,27 +517,6 @@ tcmalloc_minimal_large_heap_fragmentation_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
|
||||
tcmalloc_minimal_large_heap_fragmentation_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS)
|
||||
tcmalloc_minimal_large_heap_fragmentation_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
|
||||
|
||||
# This tests it works to LD_PRELOAD libtcmalloc (tests maybe_threads.cc)
|
||||
# In theory this should work under mingw, but mingw has trouble running
|
||||
# shell scripts that end in .exe. And it doesn't seem to build shared
|
||||
# libraries anyway (so can't be LD_PRELOADed) -- in fact, anybody who
|
||||
# chooses not to build shared libraries won't be able to run this test.
|
||||
# TODO(csilvers): figure out how to nix ".exe" or otherwise work under mingw
|
||||
if !MINGW
|
||||
if !ENABLE_STATIC
|
||||
TESTS += maybe_threads_unittest.sh$(EXEEXT)
|
||||
maybe_threads_unittest_sh_SOURCES = src/tests/maybe_threads_unittest.sh
|
||||
noinst_SCRIPTS += $(maybe_threads_unittest_sh_SOURCES)
|
||||
# This script preloads libtcmalloc, and calls two other binaries as well
|
||||
# TODO(csilvers): replace by 'if ! cmp $^ $@ >/dev/null 2>&; then ...; fi'
|
||||
maybe_threads_unittest.sh$(EXEEXT): $(top_srcdir)/$(maybe_threads_unittest_sh_SOURCES) \
|
||||
$(LIBTCMALLOC_MINIMAL) \
|
||||
low_level_alloc_unittest
|
||||
rm -f $@
|
||||
cp -p $(top_srcdir)/$(maybe_threads_unittest_sh_SOURCES) $@
|
||||
endif !ENABLE_STATIC
|
||||
endif !MINGW
|
||||
|
||||
# These all tests components of tcmalloc_minimal
|
||||
|
||||
TESTS += addressmap_unittest
|
||||
@ -934,7 +902,7 @@ libtcmalloc_la_SOURCES = $(TCMALLOC_CC) $(TCMALLOC_INCLUDES) \
|
||||
libtcmalloc_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG $(AM_CXXFLAGS) \
|
||||
$(MAYBE_NO_HEAP_CHECK) $(EMERGENCY_MALLOC_DEFINE)
|
||||
libtcmalloc_la_LDFLAGS = $(PTHREAD_CFLAGS) -version-info @TCMALLOC_SO_VERSION@
|
||||
libtcmalloc_la_LIBADD = libtcmalloc_internal.la libmaybe_threads.la $(PTHREAD_LIBS)
|
||||
libtcmalloc_la_LIBADD = libtcmalloc_internal.la $(PTHREAD_LIBS)
|
||||
|
||||
# same as above with without -DNDEBUG
|
||||
noinst_LTLIBRARIES += libtcmalloc_internal_with_asserts.la
|
||||
@ -950,7 +918,7 @@ libtcmalloc_with_asserts_la_SOURCES = $(libtcmalloc_la_SOURCES)
|
||||
libtcmalloc_with_asserts_la_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) \
|
||||
$(MAYBE_NO_HEAP_CHECK) $(EMERGENCY_MALLOC_DEFINE)
|
||||
libtcmalloc_with_asserts_la_LDFLAGS = $(PTHREAD_CFLAGS)
|
||||
libtcmalloc_with_asserts_la_LIBADD = libtcmalloc_internal_with_asserts.la libmaybe_threads.la $(PTHREAD_LIBS)
|
||||
libtcmalloc_with_asserts_la_LIBADD = libtcmalloc_internal_with_asserts.la $(PTHREAD_LIBS)
|
||||
|
||||
LIBTCMALLOC = libtcmalloc.la
|
||||
|
||||
@ -1270,7 +1238,7 @@ libprofiler_la_SOURCES = src/profiler.cc \
|
||||
src/profile-handler.cc \
|
||||
src/profiledata.cc \
|
||||
$(CPU_PROFILER_INCLUDES)
|
||||
libprofiler_la_LIBADD = libstacktrace.la libmaybe_threads.la libfake_stacktrace_scope.la
|
||||
libprofiler_la_LIBADD = libstacktrace.la libfake_stacktrace_scope.la
|
||||
# We have to include ProfileData for profiledata_unittest
|
||||
CPU_PROFILER_SYMBOLS = '(ProfilerStart|ProfilerStartWithOptions|ProfilerStop|ProfilerFlush|ProfilerEnable|ProfilerDisable|ProfilingIsEnabledForAllThreads|ProfilerRegisterThread|ProfilerGetCurrentState|ProfilerState|ProfileData|ProfileHandler|ProfilerGetStackTrace)'
|
||||
libprofiler_la_LDFLAGS = -export-symbols-regex $(CPU_PROFILER_SYMBOLS) \
|
||||
|
17
configure.ac
17
configure.ac
@ -518,23 +518,6 @@ AC_SUBST(LIBSTDCXX_LA_LINKER_FLAG)
|
||||
# In fact, a lot of the code in this directory depends on pthreads
|
||||
AX_PTHREAD
|
||||
|
||||
AC_MSG_CHECKING([whether pthread symbols are available in C++ without including pthread.h])
|
||||
acx_pthread_despite_asking_for=no
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM([
|
||||
#include <string>
|
||||
#include <vector>
|
||||
],[
|
||||
pthread_t th; pthread_join(th, 0);
|
||||
])],[
|
||||
acx_pthread_despite_asking_for=yes
|
||||
AC_DEFINE(HAVE_PTHREAD_DESPITE_ASKING_FOR, 1, [defined to 1 if pthread symbols are exposed even without include pthread.h])
|
||||
AC_DEFINE(HAVE_PTHREAD, 1, [])
|
||||
])
|
||||
AC_MSG_RESULT([$acx_pthread_despite_asking_for])
|
||||
|
||||
AM_CONDITIONAL(HAVE_PTHREAD_DESPITE_ASKING_FOR, test x"$acx_pthread_despite_asking_for" = xyes)
|
||||
|
||||
# Figure out where libc has program_invocation_name
|
||||
AC_PROGRAM_INVOCATION_NAME
|
||||
|
||||
|
@ -84,7 +84,6 @@
|
||||
#include "base/sysinfo.h"
|
||||
#include "heap-profile-table.h"
|
||||
#include "malloc_hook-inl.h"
|
||||
#include "maybe_threads.h"
|
||||
#include "memory_region_map.h"
|
||||
#include "safe_strerror.h"
|
||||
|
||||
@ -555,7 +554,7 @@ inline void set_thread_disable_counter(int value) {
|
||||
class InitThreadDisableCounter {
|
||||
public:
|
||||
InitThreadDisableCounter() {
|
||||
perftools_pthread_key_create(&thread_disable_counter_key, NULL);
|
||||
pthread_key_create(&thread_disable_counter_key, NULL);
|
||||
// Set up the main thread's value, which we have a special variable for.
|
||||
void* p = (void*)(intptr_t)main_thread_counter; // store the counter directly
|
||||
perftools_pthread_setspecific(thread_disable_counter_key, p);
|
||||
|
@ -50,7 +50,6 @@
|
||||
#endif
|
||||
#include "gperftools/malloc_extension.h"
|
||||
#include "gperftools/malloc_extension_c.h"
|
||||
#include "maybe_threads.h"
|
||||
#include "base/googleinit.h"
|
||||
|
||||
using std::string;
|
||||
|
@ -50,7 +50,6 @@
|
||||
#include "base/logging.h"
|
||||
#include "base/spinlock.h"
|
||||
#include "maybe_emergency_malloc.h"
|
||||
#include "maybe_threads.h"
|
||||
#include "malloc_hook-inl.h"
|
||||
#include <gperftools/malloc_hook.h>
|
||||
|
||||
|
@ -1,144 +0,0 @@
|
||||
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
|
||||
// Copyright (c) 2005, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// ---
|
||||
// Author: Paul Menage <opensource@google.com>
|
||||
//
|
||||
// Some wrappers for pthread functions so that we can be LD_PRELOADed
|
||||
// against non-pthreads apps.
|
||||
//
|
||||
// This module will behave very strangely if some pthreads functions
|
||||
// exist and others don't.
|
||||
|
||||
#include "config.h"
|
||||
#include <assert.h>
|
||||
#include <string.h> // for memcmp
|
||||
#include <stdio.h> // for __isthreaded on FreeBSD
|
||||
// We don't actually need strings. But including this header seems to
|
||||
// stop the compiler trying to short-circuit our pthreads existence
|
||||
// tests and claiming that the address of a function is always
|
||||
// non-zero. I have no idea why ...
|
||||
#include <string>
|
||||
#include "maybe_threads.h"
|
||||
#include "base/basictypes.h"
|
||||
#include "base/logging.h"
|
||||
|
||||
// __THROW is defined in glibc systems. It means, counter-intuitively,
|
||||
// "This function will never throw an exception." It's an optional
|
||||
// optimization tool, but we may need to use it to match glibc prototypes.
|
||||
#ifndef __THROW // I guess we're not on a glibc system
|
||||
# define __THROW // __THROW is just an optimization, so ok to make it ""
|
||||
#endif
|
||||
|
||||
// These are the methods we're going to conditionally include.
|
||||
extern "C" {
|
||||
int pthread_key_create (pthread_key_t*, void (*)(void*))
|
||||
__THROW ATTRIBUTE_WEAK;
|
||||
int pthread_key_delete (pthread_key_t)
|
||||
__THROW ATTRIBUTE_WEAK;
|
||||
void *pthread_getspecific(pthread_key_t)
|
||||
__THROW ATTRIBUTE_WEAK;
|
||||
int pthread_setspecific(pthread_key_t, const void*)
|
||||
__THROW ATTRIBUTE_WEAK;
|
||||
int pthread_once(pthread_once_t *, void (*)(void))
|
||||
ATTRIBUTE_WEAK;
|
||||
#ifdef HAVE_FORK
|
||||
int pthread_atfork(void (*__prepare) (void),
|
||||
void (*__parent) (void),
|
||||
void (*__child) (void))
|
||||
__THROW ATTRIBUTE_WEAK;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define MAX_PERTHREAD_VALS 16
|
||||
static void *perftools_pthread_specific_vals[MAX_PERTHREAD_VALS];
|
||||
static int next_key;
|
||||
|
||||
// NOTE: it's similar to bitcast defined in basic_types.h with
|
||||
// exception of ignoring sizes mismatch
|
||||
template <typename T1, typename T2>
|
||||
static T2 memcpy_cast(const T1 &input) {
|
||||
T2 output;
|
||||
size_t s = sizeof(input);
|
||||
if (sizeof(output) < s) {
|
||||
s = sizeof(output);
|
||||
}
|
||||
memcpy(&output, &input, s);
|
||||
return output;
|
||||
}
|
||||
|
||||
int perftools_pthread_key_create(pthread_key_t *key,
|
||||
void (*destr_function) (void *)) {
|
||||
if (pthread_key_create) {
|
||||
return pthread_key_create(key, destr_function);
|
||||
} else {
|
||||
assert(next_key < MAX_PERTHREAD_VALS);
|
||||
*key = memcpy_cast<int, pthread_key_t>(next_key++);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int perftools_pthread_key_delete(pthread_key_t key) {
|
||||
if (pthread_key_delete) {
|
||||
return pthread_key_delete(key);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void *perftools_pthread_getspecific(pthread_key_t key) {
|
||||
if (pthread_getspecific) {
|
||||
return pthread_getspecific(key);
|
||||
} else {
|
||||
return perftools_pthread_specific_vals[memcpy_cast<pthread_key_t, int>(key)];
|
||||
}
|
||||
}
|
||||
|
||||
int perftools_pthread_setspecific(pthread_key_t key, void *val) {
|
||||
if (pthread_setspecific) {
|
||||
return pthread_setspecific(key, val);
|
||||
} else {
|
||||
perftools_pthread_specific_vals[memcpy_cast<pthread_key_t, int>(key)] = val;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_FORK
|
||||
|
||||
void perftools_pthread_atfork(void (*before)(),
|
||||
void (*parent_after)(),
|
||||
void (*child_after)()) {
|
||||
if (pthread_atfork) {
|
||||
int rv = pthread_atfork(before, parent_after, child_after);
|
||||
CHECK(rv == 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -1,59 +0,0 @@
|
||||
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
|
||||
// Copyright (c) 2005, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// ---
|
||||
// Author: Paul Menage <opensource@google.com>
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Some wrappers for pthread functions so that we can be LD_PRELOADed
|
||||
// against non-pthreads apps.
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
#ifndef GOOGLE_MAYBE_THREADS_H_
|
||||
#define GOOGLE_MAYBE_THREADS_H_
|
||||
|
||||
#ifdef HAVE_PTHREAD
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
int perftools_pthread_key_create(pthread_key_t *key,
|
||||
void (*destr_function) (void *));
|
||||
int perftools_pthread_key_delete(pthread_key_t key);
|
||||
void *perftools_pthread_getspecific(pthread_key_t key);
|
||||
int perftools_pthread_setspecific(pthread_key_t key, void *val);
|
||||
|
||||
// Our wrapper for pthread_atfork. Does _nothing_ when there are no
|
||||
// threads. See static_vars.cc:SetupAtForkLocksHandler for only user
|
||||
// of this.
|
||||
void perftools_pthread_atfork(void (*before)(),
|
||||
void (*parent_after)(),
|
||||
void (*child_after)());
|
||||
|
||||
#endif /* GOOGLE_MAYBE_THREADS_H_ */
|
@ -47,22 +47,19 @@
|
||||
#include <string>
|
||||
|
||||
#if HAVE_LINUX_SIGEV_THREAD_ID
|
||||
#include <pthread.h>
|
||||
// for timer_{create,settime} and associated typedefs & constants
|
||||
#include <time.h>
|
||||
// for sigevent
|
||||
#include <signal.h>
|
||||
// for SYS_gettid
|
||||
#include <sys/syscall.h>
|
||||
|
||||
// for perftools_pthread_key_create
|
||||
#include "maybe_threads.h"
|
||||
#endif
|
||||
|
||||
#include "base/dynamic_annotations.h"
|
||||
#include "base/googleinit.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/spinlock.h"
|
||||
#include "maybe_threads.h"
|
||||
|
||||
// Some Linux systems don't have sigev_notify_thread_id defined in
|
||||
// signal.h (despite having SIGEV_THREAD_ID defined) and also lack
|
||||
@ -268,7 +265,7 @@ extern "C" {
|
||||
}
|
||||
|
||||
static void CreateThreadTimerKey(pthread_key_t *pkey) {
|
||||
int rv = perftools_pthread_key_create(pkey, ThreadTimerDestructor);
|
||||
int rv = pthread_key_create(pkey, ThreadTimerDestructor);
|
||||
if (rv) {
|
||||
RAW_LOG(FATAL, "aborting due to pthread_key_create error: %s", strerror(rv));
|
||||
}
|
||||
@ -294,7 +291,7 @@ static void StartLinuxThreadTimer(int timer_type, int signal_number,
|
||||
}
|
||||
|
||||
timer_id_holder *holder = new timer_id_holder(timerid);
|
||||
rv = perftools_pthread_setspecific(timer_key, holder);
|
||||
rv = pthread_setspecific(timer_key, holder);
|
||||
if (rv) {
|
||||
RAW_LOG(FATAL, "aborting due to pthread_setspecific error: %s", strerror(rv));
|
||||
}
|
||||
@ -393,7 +390,7 @@ ProfileHandler::~ProfileHandler() {
|
||||
Reset();
|
||||
#ifdef HAVE_LINUX_SIGEV_THREAD_ID
|
||||
if (per_thread_timer_enabled_) {
|
||||
perftools_pthread_key_delete(thread_timer_key);
|
||||
pthread_key_delete(thread_timer_key);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -43,7 +43,6 @@
|
||||
#include "sampler.h" // for Sampler
|
||||
#include "getenv_safe.h" // TCMallocGetenvSafe
|
||||
#include "base/googleinit.h"
|
||||
#include "maybe_threads.h"
|
||||
|
||||
namespace tcmalloc {
|
||||
|
||||
@ -137,7 +136,7 @@ void Static::InitLateMaybeRecursive() {
|
||||
// be less fortunate and allow some early app constructors to run
|
||||
// before malloc is ever called.
|
||||
|
||||
perftools_pthread_atfork(
|
||||
pthread_atfork(
|
||||
CentralCacheLockAll, // parent calls before fork
|
||||
CentralCacheUnlockAll, // parent calls after fork
|
||||
CentralCacheUnlockAll); // child calls after fork
|
||||
|
@ -163,8 +163,6 @@ static void FreeHook(const void *p) {
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// This is needed by maybe_threads_unittest.sh, which parses argv[0]
|
||||
// to figure out what directory low_level_alloc_unittest is in.
|
||||
if (argc != 1) {
|
||||
fprintf(stderr, "USAGE: %s\n", argv[0]);
|
||||
return 1;
|
||||
|
@ -1,79 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (c) 2007, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# ---
|
||||
# Author: Craig Silverstein
|
||||
#
|
||||
# maybe_threads.cc was written to allow LD_PRELOAD=libtcmalloc.so to
|
||||
# work even on binaries that were not linked with pthreads. This
|
||||
# unittest tests that, by running low_level_alloc_unittest with an
|
||||
# LD_PRELOAD. (low_level_alloc_unittest was chosen because it doesn't
|
||||
# link in tcmalloc.)
|
||||
#
|
||||
# We assume all the .so files are in the same directory as both
|
||||
# addressmap_unittest and profiler1_unittest. The reason we need
|
||||
# profiler1_unittest is because it's instrumented to show the directory
|
||||
# it's "really" in when run without any args. In practice this will either
|
||||
# be BINDIR, or, when using libtool, BINDIR/.lib.
|
||||
|
||||
# We expect BINDIR to be set in the environment.
|
||||
# If not, we set them to some reasonable values.
|
||||
BINDIR="${BINDIR:-.}"
|
||||
|
||||
if [ "x$1" = "x-h" -o "x$1" = "x--help" ]; then
|
||||
echo "USAGE: $0 [unittest dir]"
|
||||
echo " By default, unittest_dir=$BINDIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
UNITTEST_DIR=${1:-$BINDIR}
|
||||
|
||||
# Figure out the "real" unittest directory. Also holds the .so files.
|
||||
UNITTEST_DIR=`$UNITTEST_DIR/low_level_alloc_unittest --help 2>&1 \
|
||||
| awk '{print $2; exit;}' \
|
||||
| xargs dirname`
|
||||
|
||||
# Figure out where libtcmalloc lives. It should be in UNITTEST_DIR,
|
||||
# but with libtool it might be in a subdir.
|
||||
if [ -r "$UNITTEST_DIR/libtcmalloc_minimal.so" ]; then
|
||||
LIB_PATH="$UNITTEST_DIR/libtcmalloc_minimal.so"
|
||||
elif [ -r "$UNITTEST_DIR/.libs/libtcmalloc_minimal.so" ]; then
|
||||
LIB_PATH="$UNITTEST_DIR/.libs/libtcmalloc_minimal.so"
|
||||
elif [ -r "$UNITTEST_DIR/libtcmalloc_minimal.dylib" ]; then # for os x
|
||||
LIB_PATH="$UNITTEST_DIR/libtcmalloc_minimal.dylib"
|
||||
elif [ -r "$UNITTEST_DIR/.libs/libtcmalloc_minimal.dylib" ]; then
|
||||
LIB_PATH="$UNITTEST_DIR/.libs/libtcmalloc_minimal.dylib"
|
||||
else
|
||||
echo "Cannot run $0: cannot find libtcmalloc_minimal.so"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
LD_PRELOAD="$LIB_PATH" $UNITTEST_DIR/low_level_alloc_unittest
|
@ -40,7 +40,6 @@
|
||||
#include "base/spinlock.h" // for SpinLockHolder
|
||||
#include "getenv_safe.h" // for TCMallocGetenvSafe
|
||||
#include "central_freelist.h" // for CentralFreeListPadded
|
||||
#include "maybe_threads.h"
|
||||
|
||||
using std::min;
|
||||
using std::max;
|
||||
|
@ -46,7 +46,6 @@
|
||||
#include "base/commandlineflags.h"
|
||||
#include "common.h"
|
||||
#include "linked_list.h"
|
||||
#include "maybe_threads.h"
|
||||
#include "page_heap_allocator.h"
|
||||
#include "sampler.h"
|
||||
#include "static_vars.h"
|
||||
@ -60,6 +59,12 @@
|
||||
|
||||
DECLARE_int64(tcmalloc_sample_parameter);
|
||||
|
||||
#ifndef HAVE_PERFTOOLS_PTHREAD_KEYS
|
||||
#define perftools_pthread_getspecific pthread_getspecific
|
||||
#define perftools_pthread_setspecific pthread_setspecific
|
||||
#define perftools_pthread_key_create pthread_key_create
|
||||
#endif
|
||||
|
||||
namespace tcmalloc {
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
@ -130,8 +130,7 @@ inline bool pthread_equal(pthread_t left, pthread_t right) {
|
||||
* we therefore shouldn't be #including directly. This hack keeps us from
|
||||
* doing so. TODO(csilvers): do something more principled.
|
||||
*/
|
||||
#define GOOGLE_MAYBE_THREADS_H_ 1
|
||||
/* This replaces maybe_threads.{h,cc} */
|
||||
#define HAVE_PERFTOOLS_PTHREAD_KEYS
|
||||
|
||||
EXTERN_C pthread_key_t PthreadKeyCreate(void (*destr_fn)(void*)); /* port.cc */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user