Squashed 'third_party/gperftools/' changes from 54505f1d50..c25941200e
c25941200e fix cmake gperftools_enable_libunwind invalid
43504ab709 tcmalloc page fences: add TCMALLOC_PAGE_FENCE_READABLE option
d57a9ea8bc README: replace "golang" moniker with "Go"
f7c6fb6c8e bump version to 2.9.1
c2f60400a8 prefer backtrace() on OSX
a015377a54 Set tcmalloc heap limit prior to testing oom
c939dd5531 correctly check sized delete hint when asserts are on
47b5b59ca9 bump version to 2.9
d7cbc8c2ff unbreak cmake build
be0bbdb340 amputate various unused bits from elfcore.h
42bab59f25 liberate profile handler from linux_syscall_support
4629511e99 liberate spinlock futex waits from linux_syscall_support includes
2e7094a862 liberate malloc_hook_mmap_linux.h from linux_syscall_support
35301e2e59 add missing noopt wrappings around more operator new calls
fa412adfe3 Fix thread-safety (annotalysis) annotations
cc496aecb8 tcmalloc: Switch thread-safety annotations to support clang
96ba58e19b bump version to 2.9rc
9ce32aefa9 upgrade test bot to xenial (ubuntu 16.04 LTS)
91ff311449 don't default to generic_fp without frame pointers
4cf7dd0a75 enable emergency_malloc on all architectures with mmap
37087ec536 prefer libunwind on x86-64 even with -fno-omit-frame-pointer
f4aa2a435e implement generic frame pointer backtracer
17bab484ae always respect --enable-frame-pointers
22c0eceddc add emacs mode line annotations to remaining files
b12139ddba delete-trailing-whitespace on all files
419c85814d amputate unused dynamic annotations support
73a72cdb61 don't check for snprintf
95b52b0504 don't check for unused uname symbol
01c2697fac amputate unused SleepForMilliseconds from sysinfo.{h,cc}
ac68c97187 don't check for useless __builtin_stack_pointer
7271bb72be unbreak cmake check for TLS support
7c106ca241 don't bother checking for stl namespace and use std
0d6f32b9ce use standard way to print size_t-sized ints
0c11d35f4a amputate checking for __int64
92718aaaeb amputate checking for conflict-signal.h
9bb2937261 amputate checking for inline keyword support
d9c4c3b481 profile-handler: use documented sigev_notify_thread_id in sigevent
43459feb33 configure.ac: check for features.h once
290b123c01 atomicops: Remove Acquire_Store / Release_Load
3b1c60cc4e Add support for Elbrus 2000 (e2k)
c5747615da syscall: Mark x8 as clobbered
d8eb315fb1 bump version to 2.8.1
6ed61f8e91 add note that cmake build is preliminary
6bbf2ed150 Update cmake
913d3eb7d7 Fix a few macros for Apple
64a73b1cb8 Work on fixing linking errors in stacktrace
b788d51eb4 Fix conditional definitions
495229b625 Make internal tcmalloc libs
cca7f6f669 More unit tests and libraries
11dc65c3c4 Fix config headers, add more unit tests
6078fe40d9 Finish configure.ac conversion to CMake, start on Makefile.am
515fb22196 Generate config header
4adb5ff74d Add architecture checks
fa9bedc82c Add most of CMake build
9e4f72fd1f Define options, start system checks
a6ce98174b Add CMakeLists.txt
3134955875 Additional porting for riscv64.
f0e289bdbb Enable build on riscv64.
6c715b4fa1 docs: fix simple typo, defininitions -> definitions
02d5264018 Revert "drop page heap lock when returning memory back to kernel"
151cbf5146 Add OS X arm64 program counter
140e3481d0 Merge pull request #1231 from PatriosTheGreat/master
0fc5cabdfc Fix implicit-int-float-conversion warning.
bda3c82e11 Increase kMaxStackDepth to 254
1d9b8bb59d don't test sbrk hook if we're on linux and don't have __sbrk
180bfa10d7 bumped version to 2.8
c1bcc412ba Don't try to mark esp as clobbered in linux syscall support.
50f89afaed liberate gperftools tests from relying on -fno-builtin-XXX flags
98ccd0f102 prevent inlining in heap-checker unittest
e521472f1a fix linking of page_heap_test on windows
e5f77d6485 chmod -x Makefile.am gperftools.sln
6b92e00cec don't assume HAVE_MMAP on mingw builds
4cddede399 New ProfilerGetStackTrace()
db7aa547ab bumped version to 2.8rc
be3da70298 drop page heap lock when returning memory back to kernel
87acc2782f amputate span events history
e40c7f231a Fix mmap syscall on s390
b7607ee7d4 tcmalloc: ability to disable fallback allocator in memfs
1bfcb5bc3a tcmalloc: fragmentation overhead instrumentation
36bf1309de Fix a clang-tidy readability warning for static member access
2b2a962c2b Remove executable flag for c++ files
8f308afbfe Increase kClassSizesMax to 128 to allow for page size of 4K
d3fefdb694 Allow configuring page size to 4K, 8K, 16K, 32K, 64K, 128K and 256K
cf2df3b000 Fix the removed std::allocator::pointer member type removed in C++20
31024506c5 Add mips64* support
fe62a0baab Update config.h in Windows
8272631b5a Fix a long time typo
c1d546d7b2 never test and always default HAVE_MMAP to on
fba6ce0e7a Fix build on FreeBSD
98ac4ee9bc Fix typos
9e5b162873 don't try to mark rsp as clobbered in linux syscall support
1e36ed7055 Use initial exec TLS model for all thread local variables from thread_cache.cc
8f9a873fce Fix accessing PC on FreeBSD/powerpc and powerpc64
fc00474ddc Include asm/ptrace.h when accessing ucontext_t
5574c87e39 Compile time aggressive decommit option
e9ab4c5304 undef mmap64 function
5eec9d0ae3 Drop not very portable and not very useful unwind benchmark.
1561f0946f check for __sbrk
1de76671d4 Fix mmap region iteration while no regions are recorded.
acdcacc28f Use off64_t instead of __off64_t
0177a2420a Return early in WriteProfile to reduce indentation
b85652bf26 Add generic.total_physical_bytes property to MallocExtension
90df23c81f Make some tcmalloc constants truly const
49dbe4362b Add comment about gperftools 2.8 not deduplicating heapz samples.
63a12a5ed3 Drop de-duplication of heap sample (aka heapz) entries.
954f9dc0e3 Add flag to disable installing unmaintained & deprecated pprof.
893bff51bc Avoid static initialization of pprof path for symbolization.
69867c523b Clean up MSVC projects
f2bca77aed Fix page_heap_test flakiness
c41688bf20 Use standard-conforming alignof in debugallocation.cc
71c8cedaca Fix incompatible aliasing warnings
8dd3040358 Format and fix out of bound access in CpuProfilerSwitch
467502e70a provide constexpr constructor for Sampler
1fb543cc70 Patch _free_dbg to make Debug mode in MSVC works
267f431d80 Use indirect system calls in the linux spinlock implementation
73ee9b1544 Use indirect system calls in the mmap malloc hooks.
3af509d4f9 benchmark: use angle brackets to include ucontext.h
0cdda6d7cc use utf-8 for special symbols
c7a0cfda88 Fix potential missing nul character on resolved symbol names
e42bfc8c06 tcmalloc: use relative addresses with the windows addr2line wrapper
d8f8d1cced tcmalloc: add long form flag '--exe' to specify the binary
25c53aca12 tcmalloc: fixes for the windows addr2line wrapper
f02e28f348 Replace builtin_expect configure test with a direct GCC compiler check
62c4eca6e7 Under x64, the PE loader looks for callbacks in constant sections
0b588e7490 Fix uninitialized memory use in sampler_test
51a5613f21 Upgrade MSVC projects to MSVC2015
44da4ce539 build with c++11 or later
f47a52ce85 Make _recalloc adhere to MS's definition
fe87ffb7ea Disable large allocation report by default
9608fa3bcf bumped version to 2.7
db890ccfad Clean up src/windows/config.h
497ea33165 Fix WIN32_OVERRIDE_ALLOCATORS for VS2017
ebc85cca90 Enable aligned new/delete declarations on Windows when applicable
a3badd6d21 Really fix CheckAddressBits compilation warning
7c718fe176 Add tests for sized deallocation
30e5e614a8 Fix build without static libraries
836c4f29a5 Update documentation for heap_checker.html
e47d0d1c51 powerpc: Re-enable VDSO support
0a66dd3a6a linux: add aarch64_ilp32 support.
05dff09663 Fix signature of sbrk.
33ae0ed2ae unbreak compilation on GNU/Linux i386
977e0d4500 Remove not needed header in vdso_support.cc.
36bfa9a404 Enable tcmalloc VDSO support only on x86 to reduce static initializers
1cb5de6db9 Explicitly prevent int overflow
8f63f2bb98 Correctly detect presence of various functions in tcmalloc.h
736648887b Don't test OOM handling of debugallocator
c4a8e00da4 Fix warning about one of CheckAddressBits functions unused
47c99cf492 unbreak printing large span stats
34f78a2dcd bumped version to 2.7rc
db98aac55a Add a central free list for kMaxPages-sized spans
d7be938560 implement more robust detection of sized delete support
f1d3fe4a21 refactored handling of reverse span set iterator for correctness
59c77be0fa Update docs for central page heap to reflect tree
06c9414ec4 Implemented O(log n) searching among large spans
a42e44738a typo in docs/tcmalloc.html
71bf09aabe bumped version to 2.6.3
0bccb5e658 fix malloc fast path for patched windows functions
8b1d13c631 configure.ac: use link check for std::align_val_t
36ab068baa configure.ac: better test for -faligned-new
6a4b079997 bumped version to 2.6.2
2291714518 implement fast-path for memalign/aligned_alloc/tc_new_aligned
8b9728b023 add memalign benchmark to malloc_bench
79c91a9810 always define empty PERFTOOLS_NOTHROW
03da6afff5 unbreak throw declarations on operators new/delete
89fe59c831 Fix OOM handling in fast-path
a29a0cf348 delete-trailing-whitespace on thread_cache.*
e6cd69bdec reintroduce aliasing for aligned delete
fb30c3d435 fully disable aligned new on windows for now
7efb3ecf37 Add support for C++17 operator new/delete for overaligned types.
7a6e25f3b1 Add new statistics for the PageHeap
6e3a702fb9 Fix data race setting size_left_ in ThreadCache::SetMaxSize
235471f965 fix memory leak in Symbolize function
47efdd60f5 Added mising va_end() in TracePrintf function
497b60ef0f Implemented GetProgramInvocationName on FreeBSD
ac072a3fc7 Revert "Ignore current_instance heap allocation when leak sanitizer is enabled"
fb5987d579 Revert "Ensure that lsan flags are appended on all necessary targets"
5815f02105 Use safe getenv for setting up backtrace capturing method
aab4277311 Fixed LTO warning about the mismatch between return values for ProfilingIsEnabledForAllThreads()
d406f22853 implement support for C11 aligned_alloc
92a27e41a1 Fix build on macOS.
e033431e5a include fcntl.h for loff_t definition
e41bc41404 Use ucontext_t instead of struct ucontext
bf840dec04 bumped version to 2.6.1
2d220c7e26 Replace "throw()" by "PERFTOOLS_NOTHROW"
c4de73c0e6 Add PERFTOOLS_THROW where necessary (as detected by GCC).
e5fbd0e24e Rename PERFTOOLS_THROW into PERFTOOLS_NOTHROW.
eeb7b84c20 Register tcmalloc atfork handler as early as possible
208c26caef Add initial syscall support for mips64 32-bit ABI
a3bf61ca81 Ensure that lsan flags are appended on all necessary targets
97646a1932 Add missing NEWS entry for recent 2.6 release
4be05e43a1 bumped version up to 2.6
70a35422b5 Ignore current_instance heap allocation when leak sanitizer is enabled
6eca6c64fa Revert "issue-654: [pprof] handle split text segments"
a495969cb6 update the prev_class_size in each loop, or the min_object_size of tcmalloc.thread will always be 1 when calling GetFreeListSizes
163224d8af Document HEAPPROFILESIGNAL environment variable
5ac82ec5b9 added stacktrace capturing benchmark
c571ae2fc9 2.6rc4
f2bae51e7e Revert "Revert "disable dynamic sized delete support by default""
6426c0cc80 2.6rc3
0c0e2fe43b enable 48-bit page map on msvc as well
83d6818295 speed up 3-level page map access
f7ff175b92 add configure-time warning on unsupported backtrace capturing
cef582350c align fast-path functions only if compiler supports that
bddf862b18 actually support very early freeing of NULL
07a124d8c1 don't use arg-ful constructor attribute for early nallocx test
5346b8a4de don't depend on SIZE_MAX definition in sampler.cc
50125d8f70 2.6rc2
a5e8e42a47 don't link-in libunwind if libunwind.h is missing
e92acdf98d Fix compilation error for powerpc32
b48403a4b0 2.6rc
53f15325d9 fix compilation of tcmalloc_unittest.cc on older llvm-gcc
b1d88662cb change size class to be represented by 32 bit int
991f47a159 change default transfer batch back to 32
7bc34ad1f6 support different number of size classes at runtime
4585b78c8d massage allocation and deallocation fast-path for performance
5964a1d9c9 always inline a number of hot functions
e419b7b9a6 introduce ATTRIBUTE_ALWAYS_INLINE
7d588da7ec synchronized Sampler implementation with Google-internal version
27da4ade70 reduce size of class_to_size_ array
335f09d4e4 use static location for pageheap
6ff332fb51 move size classes map earlier in SizeMap
121b1cb32e slightly faster size class cache
b57c0bad41 init tcmalloc prior to replacing system alloc
71fa9f8730 use 2-level page map for 48-bit addresses
bad70249dd use 48-bit addresses on 64-bit arms too
5f12147c6d use hidden visibility for some key global variables
dfd53da578 set ENOMEM in handle_oom
14fd551072 avoid O(N²) in thread cache creation code
507a105e84 pass original size to DoSampledAllocation
bb77979dea don't declare throw() on malloc funtions since it is faster
89c74cb79c handle duplicate google_malloc frames in malloc hook stack trace
0feb1109ac fix stack trace capturing in debug malloc
0506e965ee replace LIKELY/UNLIKELY with PREDICT_{TRUE,FALSE}
59a4987054 prevent inlining ATTRIBUTE_SECTION functions
ebb575b8a0 Revert "enabled aggressive decommit by default"
b82d89cb7c Revert "disable dynamic sized delete support by default"
fac0bb44d5 Do not depend on memchr in commandlineflags::StringToBool
7d49f015a0 Make GetenvBeforeMain work inside ifunc handler
a2550b6309 turn bench_fastpath_throughput into actual throughput benchmark
b762b1a492 added sized free benchmarks to malloc_bench
71ffc1cd6b added free lists randomization step to malloc_bench
732dfeb83d Run StartStopNoOptionsEmpty profiledata unittest
cbb312fbe8 aggressive decommit: only free necessary regions and fix O(N²)
6d98223a90 don't build with -fno-exceptions
d6a1931cce fixed warning in casting heap of checker's main_thread_counter
5c778701d9 added tcmalloc minimal unittest with ASSERTs checked
a9167617ab drop unused g_load_map variable in patch_functionc.cc
d52e56dcb5 don't compare integer to NULL
bae00c0341 add fake_stacktrace_scope to few msvc projects
79aab4fed4 correctly dllexport nallocx on windows
b010895a08 don't undef PERFTOOLS_DLL_DECL
491b1aca7e don't try to use pthread_atfork on windows
691045b957 suppress warnings from legacy headers while building legacy headers test
22f7ceb97a use unsigned for few flags in mini_disassembler_types.h
9b17a8a5ba remove superfluous size_t value >= 0 check
86ce69d77f Update binary_trees.cc
cd8586ed6c Fix path names in README
98753aa737 test that sized deallocation really works before enabling it
5618ef7850 Don't assume memalign exists in memalign vs nallocx test
bf640cd740 rename sys allocator's sys_alloc symbol to tcmalloc_sys_alloc
069e3b1655 build malloc_bench_shared_full only when full tcmalloc is built
b8f9d0d44f ported nallocx support from Google-internal tcmalloc
b0abefd938 Fix a typo in the page fence flag declaration
855b380006 replace docs by doc
664210ead8 doc -> docs, with symlink
75dc9a6e14 Fix Post(s)cript tyos
dde32f8bbc Fix unaligned memory accesses in debug allocator
02eeed29df Fix redefinition of mmap on aarch64.
c07a15cff4 [windows] patch _free_base as well
acac6af26b Fix finding default zone on macOS sierra
7822b5b0b9 Stop using glibc malloc hooks
c92f0ed089 Remove references to __malloc_initialize_hook
9709eef361 Merge pull request #821 from jtmcdole/patch-1
44f276e132 Rename TCMALLOC_DEBUG to PERFTOOLS_VERBOSE
eb474c995e Summary: support gcc atomic ops on clang too
7f86eab1f3 Recognize .node files as shared libraries
bf8eacce69 Add support for 31-bit s390; merge linux_syscall_support.h changes from upstream.
c54218069b Update README
06f4ce65c2 Small performance tweak: avoid calling time() if we don't need it
db8d483609 Autogenerate ChangeLog from git on make dist
4a13598319 renamed ChangeLog to ChangeLog.old
7852eeb75b Use initial-exec tls for libunwind's recursion flag
a07f9fe75a gerftools -> gperftools in readme
9fd6d26879 added define to enable MADV_FREE usage on Linux
6f7a14f45e Don't use MADV_FREE on Linux
55cf6e6281 Fix symbol resolution on OSX
8e85843622 added simple .travis.yml config
05e40d29c0 Recognize modern Linux ARM
632de2975e bumped version up to 2.5
6682016092 Unbreak profiling with CPUPROFILE_FREQUENCY=1
6ff86ff6a7 bumped version to 2.4.91 for 2.5rc2
782165fa7f build sized delete aliases even when sized-delete is disabled
06811b3ae4 disable dynamic sized delete support by default
d4d99eb608 unbreak compilation with visual studio
126d4582c1 Call function pointers with the right type
e0fa28ef7d Don't shift a type by more than its width
a1c764d263 Initialize counters in test
22123a37c2 Don't overflow a signed integer
66e1e94f38 added minimal "header section" to README
2804b7cfee bumped version to 2.5rc
f47fefbfc1 updated NEWS for 2.5rc
cef6036174 alias same malloc/free variants to their canonical versions
ea8d242061 Re-enable MultipleIdleNonIdlePhases test
c9962f698b added maybe_emergency_malloc.h to Makefile.am
7dd4af6536 don't round up sizes for large allocation when sampling
4f3410e759 enable emergency malloc by default on arm when using libunwind
7f12051dbe implemented emergency malloc
3ee2360250 replaced invalid uses of __THROW
013b82abcf unbreak <malloc.h> inclusion in gperftools/tcmalloc.h
19903e6f15 drop detection of sys/malloc.h and malloc/malloc.h
cdff090ebd Fix several harmless clang warnings
9095ed0840 implemented stacktrace capturing via libgcc's C++ ABI function
728cbe1021 force profiler_unittest to do 'real' work
fff6b4fb88 Extend low-level allocator to support custom pages allocator
32d9926795 added malloc_bench_shared_full
00d8fa1ef8 always use real throw() on operators new/delete
08e034ad59 Detect working ifunc before enabling dynamic sized delete support
a788f354a0 include unistd.h for getpid in thread_lister.c
644a6bdbdb Add support for Linux s390x
bab7753aad Fix typo in heap-checker-death_unittest.sh
17182e1d3c Fix include of malloc_hook_c.h in malloc_hook.h
c69721b2b2 Add support for obtaining cache size of the current thread and softer idling
5ce42e535d Don't always arm the profiling timer.
7f801ea091 Make sure the alias is not removed by link-time optimization when it can prove that it isn't used by the program, as it might still be needed to override the corresponding symbol in shared libraries (or inline assembler for that matter). For example, suppose the program uses malloc and free but not calloc and is statically linked against tcmalloc (built with -flto) and LTO is done. Then before this patch the calloc alias would be deleted by LTO due to not being used, but the malloc/free aliases would be kept because they are used by the program. Suppose the program is dynamically linked with a shared library that allocates memory using calloc and later frees it by calling free. Then calloc will use the libc memory allocator, because the calloc alias was deleted, but free will call into tcmalloc, resulting in a crash.
6b3e6ef5e0 don't retain compatibility with old docdir behavior
ccffcbd9e9 support use of configure --docdir argument
050f2d28be use alias attribute only for elf platforms
07b0b21ddd fix compilation error in spinlock
e14450366a Added better description for GetStats API
64892ae730 lower default transfer batch size down to 512
6fdfc5a7f4 implemented enabling sized-delete support at runtime
c2a79d063c use x86 pause in spin loop
0fb6dd8aa3 added binary_trees benchmark
a8852489e5 drop unsupported allocation sampling code in tcmalloc_minimal
a9db0ae516 implemented (disabled by default) sized delete support
88686972b9 pass -fsized-deallocation to gcc 5
0a18fab3af implemented sized free support via tc_free_sized
464688ab6d speedup free code path by dropping "fast path allowed check"
10f7e20716 added SizeMap::MaybeSizeClass
436e1dea43 slightly faster GetCacheIfPresent
04df911915 tell compiler that non-empty hooks are unlikely
8cc75acd1f correctly test for -Wno-unused-result support
7753d8239b fixed clang warning about shifting negative values
ae09ebb383 Fix tmpdir usage in heap-profiler_unittest.sh
df34e71b57 use $0 when referring to pprof
7773ea64ee Alignment fix to static variables for system allocators
c46eb1f3d2 Fixed printf misuse in pprof - printed string was passed as format. Better use print instead
9bbed8b1a8 Fixed assembler argument passing inside _syscall6 on MIPS - it was causing 'Expression too complex' compilation errors in spinlock
962aa53c55 added more fastpath microbenchmarks
347a830689 Ensure that PPROF_PATH is set for debugallocation_test
a9059b7c30 prevent clang from inlining Mallocer in heap checker unittest
6627f9217d drop cycleclock
f985abc296 amputate unportable and unused stuff from sysinfo
16408eb4d7 amputated wait_cycles accounting in spinlocks
fedceef40c drop cycleclock reference in ThreadCache
d7fdc3fc9d dropped unused and unsupported synchronization profiling facility
3a054d37c1 dropped unused SpinLockWait function
5b62d38329 avoid checking for dup. entries on empty backtrace
7b9ded722e fixed compiler warning in memory_region_map.cc
4194e485cb Don't link libtcmalloc_minimal.so to libpthread.so
121038308d Check if _MSC_VER is defined to avoid warnings
7367322995 Make default config.h work with VS2015
ae0a444db0 Ensure ThreadCache objects are CACHELINE_ALIGNED.
ea0b1d3154 unbreak TestErrno again
e53aef24ad don't try to test memalign on windows
7707582448 Merge pull request #717 from myrsloik/master
9eb63bddfb Use correct mangled new and delete symbols on windows x64
5078abdb33 Don't discard curl options if timeout is not defined.
Change-Id: If80121a97ff4c18289c6ebff7ccea1d1b355ec89
git-subtree-dir: third_party/gperftools
git-subtree-split: c25941200ef4ce39d0774c1332ff7abfbeab7035
Signed-off-by: Brian Silverman <bsilver16834@gmail.com>
diff --git a/src/base/arm_instruction_set_select.h b/src/base/arm_instruction_set_select.h
index 6fde685..77ff670 100644
--- a/src/base/arm_instruction_set_select.h
+++ b/src/base/arm_instruction_set_select.h
@@ -1,3 +1,4 @@
+// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
// Copyright (c) 2011, Google Inc.
// All rights reserved.
//
diff --git a/src/base/atomicops-internals-arm-generic.h b/src/base/atomicops-internals-arm-generic.h
index d0f9413..cfa6143 100644
--- a/src/base/atomicops-internals-arm-generic.h
+++ b/src/base/atomicops-internals-arm-generic.h
@@ -122,11 +122,6 @@
pLinuxKernelMemoryBarrier();
}
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
- *ptr = value;
- MemoryBarrier();
-}
-
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
MemoryBarrier();
*ptr = value;
@@ -142,11 +137,6 @@
return value;
}
-inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
- MemoryBarrier();
- return *ptr;
-}
-
// 64-bit versions are not implemented yet.
@@ -185,10 +175,6 @@
NotImplementedFatalError("NoBarrier_Store");
}
-inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
- NotImplementedFatalError("Acquire_Store64");
-}
-
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
NotImplementedFatalError("Release_Store");
}
@@ -203,11 +189,6 @@
return 0;
}
-inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
- NotImplementedFatalError("Atomic64 Release_Load");
- return 0;
-}
-
inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
diff --git a/src/base/atomicops-internals-arm-v6plus.h b/src/base/atomicops-internals-arm-v6plus.h
index 35f1048..af2920a 100644
--- a/src/base/atomicops-internals-arm-v6plus.h
+++ b/src/base/atomicops-internals-arm-v6plus.h
@@ -136,11 +136,6 @@
*ptr = value;
}
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
- *ptr = value;
- MemoryBarrier();
-}
-
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
MemoryBarrier();
*ptr = value;
@@ -156,11 +151,6 @@
return value;
}
-inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
- MemoryBarrier();
- return *ptr;
-}
-
// 64-bit versions are only available if LDREXD and STREXD instructions
// are available.
#ifdef BASE_ATOMICOPS_HAS_LDREXD_AND_STREXD
@@ -288,11 +278,6 @@
#endif // BASE_ATOMICOPS_HAS_LDREXD_AND_STREXD
-inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
- NoBarrier_Store(ptr, value);
- MemoryBarrier();
-}
-
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
MemoryBarrier();
NoBarrier_Store(ptr, value);
@@ -304,11 +289,6 @@
return value;
}
-inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
- MemoryBarrier();
- return NoBarrier_Load(ptr);
-}
-
inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
diff --git a/src/base/atomicops-internals-gcc.h b/src/base/atomicops-internals-gcc.h
index f8d2786..4f81ce3 100644
--- a/src/base/atomicops-internals-gcc.h
+++ b/src/base/atomicops-internals-gcc.h
@@ -57,7 +57,7 @@
Atomic32 old_value,
Atomic32 new_value) {
Atomic32 prev_value = old_value;
- __atomic_compare_exchange_n(ptr, &prev_value, new_value,
+ __atomic_compare_exchange_n(ptr, &prev_value, new_value,
0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
return prev_value;
}
@@ -81,7 +81,7 @@
Atomic32 old_value,
Atomic32 new_value) {
Atomic32 prev_value = old_value;
- __atomic_compare_exchange_n(ptr, &prev_value, new_value,
+ __atomic_compare_exchange_n(ptr, &prev_value, new_value,
0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
return prev_value;
}
@@ -90,7 +90,7 @@
Atomic32 old_value,
Atomic32 new_value) {
Atomic32 prev_value = old_value;
- __atomic_compare_exchange_n(ptr, &prev_value, new_value,
+ __atomic_compare_exchange_n(ptr, &prev_value, new_value,
0, __ATOMIC_RELEASE, __ATOMIC_RELAXED);
return prev_value;
}
@@ -99,11 +99,6 @@
*ptr = value;
}
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
- *ptr = value;
- MemoryBarrier();
-}
-
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
MemoryBarrier();
*ptr = value;
@@ -119,18 +114,13 @@
return value;
}
-inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
- MemoryBarrier();
- return *ptr;
-}
-
// 64-bit versions
inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
Atomic64 prev_value = old_value;
- __atomic_compare_exchange_n(ptr, &prev_value, new_value,
+ __atomic_compare_exchange_n(ptr, &prev_value, new_value,
0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
return prev_value;
}
@@ -154,7 +144,7 @@
Atomic64 old_value,
Atomic64 new_value) {
Atomic64 prev_value = old_value;
- __atomic_compare_exchange_n(ptr, &prev_value, new_value,
+ __atomic_compare_exchange_n(ptr, &prev_value, new_value,
0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
return prev_value;
}
@@ -163,7 +153,7 @@
Atomic64 old_value,
Atomic64 new_value) {
Atomic64 prev_value = old_value;
- __atomic_compare_exchange_n(ptr, &prev_value, new_value,
+ __atomic_compare_exchange_n(ptr, &prev_value, new_value,
0, __ATOMIC_RELEASE, __ATOMIC_RELAXED);
return prev_value;
}
@@ -172,11 +162,6 @@
*ptr = value;
}
-inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
- *ptr = value;
- MemoryBarrier();
-}
-
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
MemoryBarrier();
*ptr = value;
@@ -192,11 +177,6 @@
return value;
}
-inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
- MemoryBarrier();
- return *ptr;
-}
-
} // namespace base::subtle
} // namespace base
diff --git a/src/base/atomicops-internals-linuxppc.h b/src/base/atomicops-internals-linuxppc.h
index b52fdf0..5c4d03c 100644
--- a/src/base/atomicops-internals-linuxppc.h
+++ b/src/base/atomicops-internals-linuxppc.h
@@ -1,11 +1,11 @@
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
/* Copyright (c) 2008, 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
@@ -15,7 +15,7 @@
* * 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
@@ -359,14 +359,6 @@
*ptr = value;
}
-inline void Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) {
- *ptr = value;
- // This can't be _lwsync(); we need to order the immediately
- // preceding stores against any load that may follow, but lwsync
- // doesn't guarantee that.
- _sync();
-}
-
inline void Release_Store(volatile Atomic32 *ptr, Atomic32 value) {
_lwsync();
*ptr = value;
@@ -382,14 +374,6 @@
return value;
}
-inline Atomic32 Release_Load(volatile const Atomic32 *ptr) {
- // This can't be _lwsync(); we need to order the immediately
- // preceding stores against any load that may follow, but lwsync
- // doesn't guarantee that.
- _sync();
- return *ptr;
-}
-
#ifdef __PPC64__
// 64-bit Versions.
@@ -398,14 +382,6 @@
*ptr = value;
}
-inline void Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) {
- *ptr = value;
- // This can't be _lwsync(); we need to order the immediately
- // preceding stores against any load that may follow, but lwsync
- // doesn't guarantee that.
- _sync();
-}
-
inline void Release_Store(volatile Atomic64 *ptr, Atomic64 value) {
_lwsync();
*ptr = value;
@@ -421,14 +397,6 @@
return value;
}
-inline Atomic64 Release_Load(volatile const Atomic64 *ptr) {
- // This can't be _lwsync(); we need to order the immediately
- // preceding stores against any load that may follow, but lwsync
- // doesn't guarantee that.
- _sync();
- return *ptr;
-}
-
#endif
} // namespace base::subtle
diff --git a/src/base/atomicops-internals-macosx.h b/src/base/atomicops-internals-macosx.h
index b5130d4..9a0c00a 100644
--- a/src/base/atomicops-internals-macosx.h
+++ b/src/base/atomicops-internals-macosx.h
@@ -1,11 +1,11 @@
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
/* Copyright (c) 2006, 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
@@ -15,7 +15,7 @@
* * 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
@@ -172,11 +172,6 @@
*ptr = value;
}
-inline void Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) {
- *ptr = value;
- MemoryBarrier();
-}
-
inline void Release_Store(volatile Atomic32 *ptr, Atomic32 value) {
MemoryBarrier();
*ptr = value;
@@ -192,11 +187,6 @@
return value;
}
-inline Atomic32 Release_Load(volatile const Atomic32 *ptr) {
- MemoryBarrier();
- return *ptr;
-}
-
// 64-bit version
inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64 *ptr,
@@ -268,11 +258,6 @@
*ptr = value;
}
-inline void Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) {
- *ptr = value;
- MemoryBarrier();
-}
-
inline void Release_Store(volatile Atomic64 *ptr, Atomic64 value) {
MemoryBarrier();
*ptr = value;
@@ -288,11 +273,6 @@
return value;
}
-inline Atomic64 Release_Load(volatile const Atomic64 *ptr) {
- MemoryBarrier();
- return *ptr;
-}
-
#else
// 64-bit implementation on 32-bit platform
@@ -342,11 +322,6 @@
#endif
-inline void Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) {
- NoBarrier_Store(ptr, value);
- MemoryBarrier();
-}
-
inline void Release_Store(volatile Atomic64 *ptr, Atomic64 value) {
MemoryBarrier();
NoBarrier_Store(ptr, value);
@@ -358,10 +333,6 @@
return value;
}
-inline Atomic64 Release_Load(volatile const Atomic64 *ptr) {
- MemoryBarrier();
- return NoBarrier_Load(ptr);
-}
#endif // __LP64__
} // namespace base::subtle
diff --git a/src/base/atomicops-internals-mips.h b/src/base/atomicops-internals-mips.h
index 4bfd7f6..58e0f14 100644
--- a/src/base/atomicops-internals-mips.h
+++ b/src/base/atomicops-internals-mips.h
@@ -161,12 +161,6 @@
return NoBarrier_AtomicExchange(ptr, new_value);
}
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value)
-{
- *ptr = value;
- MemoryBarrier();
-}
-
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value)
{
MemoryBarrier();
@@ -185,12 +179,6 @@
return value;
}
-inline Atomic32 Release_Load(volatile const Atomic32* ptr)
-{
- MemoryBarrier();
- return *ptr;
-}
-
#if (_MIPS_ISA == _MIPS_ISA_MIPS64) || (_MIPS_SIM == _MIPS_SIM_ABI64)
typedef int64_t Atomic64;
@@ -285,12 +273,6 @@
return NoBarrier_AtomicExchange(ptr, new_value);
}
-inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value)
-{
- *ptr = value;
- MemoryBarrier();
-}
-
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value)
{
MemoryBarrier();
@@ -309,12 +291,6 @@
return value;
}
-inline Atomic64 Release_Load(volatile const Atomic64* ptr)
-{
- MemoryBarrier();
- return *ptr;
-}
-
#endif
} // namespace base::subtle
diff --git a/src/base/atomicops-internals-windows.h b/src/base/atomicops-internals-windows.h
index 93ced87..f7c2907 100644
--- a/src/base/atomicops-internals-windows.h
+++ b/src/base/atomicops-internals-windows.h
@@ -1,11 +1,11 @@
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
/* Copyright (c) 2006, 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
@@ -15,7 +15,7 @@
* * 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
@@ -188,10 +188,6 @@
*ptr = value;
}
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
- Acquire_AtomicExchange(ptr, value);
-}
-
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
*ptr = value; // works w/o barrier for current Intel chips as of June 2005
// See comments in Atomic64 version of Release_Store() below.
@@ -206,11 +202,6 @@
return value;
}
-inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
- MemoryBarrier();
- return *ptr;
-}
-
// 64-bit operations
#if defined(_WIN64) || defined(__MINGW64__)
@@ -298,11 +289,6 @@
*ptr = value;
}
-inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
- NoBarrier_AtomicExchange(ptr, value);
- // acts as a barrier in this implementation
-}
-
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
*ptr = value; // works w/o barrier for current Intel chips as of June 2005
@@ -323,11 +309,6 @@
return value;
}
-inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
- MemoryBarrier();
- return *ptr;
-}
-
#else // defined(_WIN64) || defined(__MINGW64__)
// 64-bit low-level operations on 32-bit platform
@@ -393,11 +374,6 @@
}
}
-inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
- NoBarrier_AtomicExchange(ptr, value);
- // acts as a barrier in this implementation
-}
-
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
NoBarrier_Store(ptr, value);
}
@@ -419,11 +395,6 @@
return value;
}
-inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
- MemoryBarrier();
- return NoBarrier_Load(ptr);
-}
-
#endif // defined(_WIN64) || defined(__MINGW64__)
diff --git a/src/base/atomicops-internals-x86.cc b/src/base/atomicops-internals-x86.cc
index c3391e7..20073c2 100644
--- a/src/base/atomicops-internals-x86.cc
+++ b/src/base/atomicops-internals-x86.cc
@@ -1,11 +1,11 @@
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
/* 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
@@ -15,7 +15,7 @@
* * 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
diff --git a/src/base/atomicops-internals-x86.h b/src/base/atomicops-internals-x86.h
index e441ac7..94c7aac 100644
--- a/src/base/atomicops-internals-x86.h
+++ b/src/base/atomicops-internals-x86.h
@@ -1,11 +1,11 @@
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
/* Copyright (c) 2006, 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
@@ -15,7 +15,7 @@
* * 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
@@ -128,11 +128,6 @@
__asm__ __volatile__("mfence" : : : "memory");
}
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
- *ptr = value;
- MemoryBarrier();
-}
-
#else
inline void MemoryBarrier() {
@@ -144,14 +139,6 @@
}
}
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
- if (AtomicOps_Internalx86CPUFeatures.has_sse2) {
- *ptr = value;
- __asm__ __volatile__("mfence" : : : "memory");
- } else {
- Acquire_AtomicExchange(ptr, value);
- }
-}
#endif
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
@@ -171,11 +158,6 @@
return value;
}
-inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
- MemoryBarrier();
- return *ptr;
-}
-
#if defined(__x86_64__)
// 64-bit low-level operations on 64-bit platform.
@@ -216,11 +198,6 @@
*ptr = value;
}
-inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
- *ptr = value;
- MemoryBarrier();
-}
-
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
ATOMICOPS_COMPILER_BARRIER();
@@ -254,11 +231,6 @@
return value;
}
-inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
- MemoryBarrier();
- return *ptr;
-}
-
#else // defined(__x86_64__)
// 64-bit low-level operations on 32-bit platform.
@@ -333,11 +305,6 @@
"mm2", "mm3", "mm4", "mm5", "mm6", "mm7");
}
-inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
- NoBarrier_Store(ptr, value);
- MemoryBarrier();
-}
-
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
ATOMICOPS_COMPILER_BARRIER();
NoBarrier_Store(ptr, value);
@@ -363,11 +330,6 @@
return value;
}
-inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
- MemoryBarrier();
- return NoBarrier_Load(ptr);
-}
-
#endif // defined(__x86_64__)
inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
diff --git a/src/base/atomicops.h b/src/base/atomicops.h
index be038f3..f1daf3b 100644
--- a/src/base/atomicops.h
+++ b/src/base/atomicops.h
@@ -1,11 +1,11 @@
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
/* Copyright (c) 2006, 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
@@ -15,7 +15,7 @@
* * 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
@@ -102,8 +102,14 @@
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
+#define CLANG_VERSION (__clang_major__ * 10000 \
+ + __clang_minor__ * 100 \
+ + __clang_patchlevel__)
+
#if defined(TCMALLOC_PREFER_GCC_ATOMICS) && defined(__GNUC__) && GCC_VERSION >= 40700
#include "base/atomicops-internals-gcc.h"
+#elif defined(TCMALLOC_PREFER_GCC_ATOMICS) && defined(__clang__) && CLANG_VERSION >= 30400
+#include "base/atomicops-internals-gcc.h"
#elif defined(__MACH__) && defined(__APPLE__)
#include "base/atomicops-internals-macosx.h"
#elif defined(__GNUC__) && defined(ARMV6)
@@ -120,6 +126,8 @@
#include "base/atomicops-internals-mips.h"
#elif defined(__GNUC__) && GCC_VERSION >= 40700
#include "base/atomicops-internals-gcc.h"
+#elif defined(__clang__) && CLANG_VERSION >= 30400
+#include "base/atomicops-internals-gcc.h"
#else
#error You need to implement atomic operations for this architecture
#endif
@@ -197,11 +205,6 @@
reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
}
-inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) {
- return base::subtle::Acquire_Store(
- reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
-}
-
inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) {
return base::subtle::Release_Store(
reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
@@ -217,11 +220,6 @@
reinterpret_cast<volatile const AtomicWordCastType*>(ptr));
}
-inline AtomicWord Release_Load(volatile const AtomicWord* ptr) {
- return base::subtle::Release_Load(
- reinterpret_cast<volatile const AtomicWordCastType*>(ptr));
-}
-
} // namespace base::subtle
} // namespace base
#endif // AtomicWordCastType
@@ -260,11 +258,9 @@
Atomic32 old_value,
Atomic32 new_value);
void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value);
-void Acquire_Store(volatile Atomic32* ptr, Atomic32 value);
void Release_Store(volatile Atomic32* ptr, Atomic32 value);
Atomic32 NoBarrier_Load(volatile const Atomic32* ptr);
Atomic32 Acquire_Load(volatile const Atomic32* ptr);
-Atomic32 Release_Load(volatile const Atomic32* ptr);
// Corresponding operations on Atomic64
Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
@@ -281,11 +277,9 @@
Atomic64 old_value,
Atomic64 new_value);
void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value);
-void Acquire_Store(volatile Atomic64* ptr, Atomic64 value);
void Release_Store(volatile Atomic64* ptr, Atomic64 value);
Atomic64 NoBarrier_Load(volatile const Atomic64* ptr);
Atomic64 Acquire_Load(volatile const Atomic64* ptr);
-Atomic64 Release_Load(volatile const Atomic64* ptr);
} // namespace base::subtle
} // namespace base
@@ -313,10 +307,6 @@
return base::subtle::Release_CompareAndSwap(ptr, old_value, new_value);
}
-inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) {
- return base::subtle::Acquire_Store(ptr, value);
-}
-
inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) {
return base::subtle::Release_Store(ptr, value);
}
@@ -324,10 +314,6 @@
inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) {
return base::subtle::Acquire_Load(ptr);
}
-
-inline AtomicWord Release_Load(volatile const AtomicWord* ptr) {
- return base::subtle::Release_Load(ptr);
-}
#endif // AtomicWordCastType
// 32-bit Acquire/Release operations to be deprecated.
@@ -342,18 +328,12 @@
Atomic32 new_value) {
return base::subtle::Release_CompareAndSwap(ptr, old_value, new_value);
}
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
- base::subtle::Acquire_Store(ptr, value);
-}
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
return base::subtle::Release_Store(ptr, value);
}
inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
return base::subtle::Acquire_Load(ptr);
}
-inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
- return base::subtle::Release_Load(ptr);
-}
#ifdef BASE_HAS_ATOMIC64
@@ -369,10 +349,6 @@
base::subtle::Atomic64 old_value, base::subtle::Atomic64 new_value) {
return base::subtle::Release_CompareAndSwap(ptr, old_value, new_value);
}
-inline void Acquire_Store(
- volatile base::subtle::Atomic64* ptr, base::subtle::Atomic64 value) {
- base::subtle::Acquire_Store(ptr, value);
-}
inline void Release_Store(
volatile base::subtle::Atomic64* ptr, base::subtle::Atomic64 value) {
return base::subtle::Release_Store(ptr, value);
@@ -381,10 +357,6 @@
volatile const base::subtle::Atomic64* ptr) {
return base::subtle::Acquire_Load(ptr);
}
-inline base::subtle::Atomic64 Release_Load(
- volatile const base::subtle::Atomic64* ptr) {
- return base::subtle::Release_Load(ptr);
-}
#endif // BASE_HAS_ATOMIC64
diff --git a/src/base/basictypes.h b/src/base/basictypes.h
index 4779611..ea87a6d 100644
--- a/src/base/basictypes.h
+++ b/src/base/basictypes.h
@@ -83,7 +83,7 @@
const int8 kint8min = ( ( int8) 0x80);
const int16 kint16min = ( ( int16) 0x8000);
const int32 kint32min = ( ( int32) 0x80000000);
-const int64 kint64min = ( ((( int64) kint32min) << 32) | 0 );
+const int64 kint64min = ( (((uint64) kint32min) << 32) | 0 );
// Define the "portable" printf and scanf macros, if they're not
// already there (via the inttypes.h we #included above, hopefully).
@@ -117,6 +117,14 @@
#define PRINTABLE_PTHREAD(pthreadt) pthreadt
#endif
+#if defined(__GNUC__)
+#define PREDICT_TRUE(x) __builtin_expect(!!(x), 1)
+#define PREDICT_FALSE(x) __builtin_expect(!!(x), 0)
+#else
+#define PREDICT_TRUE(x) (x)
+#define PREDICT_FALSE(x) (x)
+#endif
+
// A macro to disallow the evil copy constructor and operator= functions
// This should be used in the private: declarations for a class
#define DISALLOW_EVIL_CONSTRUCTORS(TypeName) \
@@ -192,6 +200,12 @@
# define ATTRIBUTE_UNUSED
#endif
+#if defined(HAVE___ATTRIBUTE__) && defined(HAVE_TLS)
+#define ATTR_INITIAL_EXEC __attribute__ ((tls_model ("initial-exec")))
+#else
+#define ATTR_INITIAL_EXEC
+#endif
+
#define COMPILE_ASSERT(expr, msg) \
typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] ATTRIBUTE_UNUSED
@@ -223,6 +237,16 @@
return dest;
}
+// bit_store<Dest,Source> implements the equivalent of
+// "dest = *reinterpret_cast<Dest*>(&source)".
+//
+// This prevents undefined behavior when the dest pointer is unaligned.
+template <class Dest, class Source>
+inline void bit_store(Dest *dest, const Source *source) {
+ COMPILE_ASSERT(sizeof(Dest) == sizeof(Source), bitcasting_unequal_sizes);
+ memcpy(dest, source, sizeof(Dest));
+}
+
#ifdef HAVE___ATTRIBUTE__
# define ATTRIBUTE_WEAK __attribute__((weak))
# define ATTRIBUTE_NOINLINE __attribute__((noinline))
@@ -257,7 +281,7 @@
// ATTRIBUTE_SECTION are guaranteed to be between START and STOP.
#if defined(HAVE___ATTRIBUTE__) && defined(__ELF__)
-# define ATTRIBUTE_SECTION(name) __attribute__ ((section (#name)))
+# define ATTRIBUTE_SECTION(name) __attribute__ ((section (#name))) __attribute__((noinline))
// Weak section declaration to be used as a global declaration
// for ATTRIBUTE_SECTION_START|STOP(name) to compile and link
@@ -357,13 +381,45 @@
# elif (defined(__aarch64__))
# define CACHELINE_ALIGNED __attribute__((aligned(64)))
// implementation specific, Cortex-A53 and 57 should have 64 bytes
+# elif (defined(__s390__))
+# define CACHELINE_ALIGNED __attribute__((aligned(256)))
+# elif (defined(__riscv) && __riscv_xlen == 64)
+# define CACHELINE_ALIGNED __attribute__((aligned(64)))
+# elif (defined(__e2k__))
+# define CACHELINE_ALIGNED __attribute__((aligned(64)))
# else
# error Could not determine cache line length - unknown architecture
# endif
#else
# define CACHELINE_ALIGNED
-#endif // defined(HAVE___ATTRIBUTE__) && (__i386__ || __x86_64__)
+#endif // defined(HAVE___ATTRIBUTE__)
+#if defined(HAVE___ATTRIBUTE__ALIGNED_FN)
+# define CACHELINE_ALIGNED_FN CACHELINE_ALIGNED
+#else
+# define CACHELINE_ALIGNED_FN
+#endif
+
+// Structure for discovering alignment
+union MemoryAligner {
+ void* p;
+ double d;
+ size_t s;
+} CACHELINE_ALIGNED;
+
+#if defined(HAVE___ATTRIBUTE__) && defined(__ELF__)
+#define ATTRIBUTE_HIDDEN __attribute__((visibility("hidden")))
+#else
+#define ATTRIBUTE_HIDDEN
+#endif
+
+#if defined(__GNUC__)
+#define ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline))
+#elif defined(_MSC_VER)
+#define ATTRIBUTE_ALWAYS_INLINE __forceinline
+#else
+#define ATTRIBUTE_ALWAYS_INLINE
+#endif
// The following enum should be used only as a constructor argument to indicate
// that the variable has static storage class, and that the constructor should
diff --git a/src/base/commandlineflags.h b/src/base/commandlineflags.h
index f54776a..038a94a 100644
--- a/src/base/commandlineflags.h
+++ b/src/base/commandlineflags.h
@@ -1,11 +1,11 @@
// -*- 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
@@ -15,7 +15,7 @@
// * 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
@@ -119,7 +119,16 @@
if (!value) {
return def;
}
- return memchr("tTyY1\0", value[0], 6) != NULL;
+ switch (value[0]) {
+ case 't':
+ case 'T':
+ case 'y':
+ case 'Y':
+ case '1':
+ case '\0':
+ return true;
+ }
+ return false;
}
inline int StringToInt(const char *value, int def) {
diff --git a/src/base/cycleclock.h b/src/base/cycleclock.h
deleted file mode 100644
index dc2d569..0000000
--- a/src/base/cycleclock.h
+++ /dev/null
@@ -1,173 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2004, 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.
-
-// ----------------------------------------------------------------------
-// CycleClock
-// A CycleClock tells you the current time in Cycles. The "time"
-// is actually time since power-on. This is like time() but doesn't
-// involve a system call and is much more precise.
-//
-// NOTE: Not all cpu/platform/kernel combinations guarantee that this
-// clock increments at a constant rate or is synchronized across all logical
-// cpus in a system.
-//
-// Also, in some out of order CPU implementations, the CycleClock is not
-// serializing. So if you're trying to count at cycles granularity, your
-// data might be inaccurate due to out of order instruction execution.
-// ----------------------------------------------------------------------
-
-#ifndef GOOGLE_BASE_CYCLECLOCK_H_
-#define GOOGLE_BASE_CYCLECLOCK_H_
-
-#include "base/basictypes.h" // make sure we get the def for int64
-#include "base/arm_instruction_set_select.h"
-// base/sysinfo.h is really big and we don't want to include it unless
-// it is necessary.
-#if defined(__arm__) || defined(__mips__) || defined(__aarch64__)
-# include "base/sysinfo.h"
-#endif
-#if defined(__MACH__) && defined(__APPLE__)
-# include <mach/mach_time.h>
-#endif
-// For MSVC, we want to use '_asm rdtsc' when possible (since it works
-// with even ancient MSVC compilers), and when not possible the
-// __rdtsc intrinsic, declared in <intrin.h>. Unfortunately, in some
-// environments, <windows.h> and <intrin.h> have conflicting
-// declarations of some other intrinsics, breaking compilation.
-// Therefore, we simply declare __rdtsc ourselves. See also
-// http://connect.microsoft.com/VisualStudio/feedback/details/262047
-#if defined(_MSC_VER) && !defined(_M_IX86)
-extern "C" uint64 __rdtsc();
-#pragma intrinsic(__rdtsc)
-#endif
-#if defined(ARMV3) || defined(__mips__) || defined(__aarch64__)
-#include <sys/time.h>
-#endif
-
-// NOTE: only i386 and x86_64 have been well tested.
-// PPC, sparc, alpha, and ia64 are based on
-// http://peter.kuscsik.com/wordpress/?p=14
-// with modifications by m3b. See also
-// https://setisvn.ssl.berkeley.edu/svn/lib/fftw-3.0.1/kernel/cycle.h
-struct CycleClock {
- // This should return the number of cycles since power-on. Thread-safe.
- static inline int64 Now() {
-#if defined(__MACH__) && defined(__APPLE__)
- // this goes at the top because we need ALL Macs, regardless of
- // architecture, to return the number of "mach time units" that
- // have passed since startup. See sysinfo.cc where
- // InitializeSystemInfo() sets the supposed cpu clock frequency of
- // macs to the number of mach time units per second, not actual
- // CPU clock frequency (which can change in the face of CPU
- // frequency scaling). Also note that when the Mac sleeps, this
- // counter pauses; it does not continue counting, nor does it
- // reset to zero.
- return mach_absolute_time();
-#elif defined(__i386__)
- int64 ret;
- __asm__ volatile ("rdtsc" : "=A" (ret) );
- return ret;
-#elif defined(__x86_64__) || defined(__amd64__)
- uint64 low, high;
- __asm__ volatile ("rdtsc" : "=a" (low), "=d" (high));
- return (high << 32) | low;
-#elif defined(__powerpc64__) || defined(__ppc64__)
- uint64 tb;
- __asm__ volatile (\
- "mfspr %0, 268"
- : "=r" (tb));
- return tb;
-#elif defined(__powerpc__) || defined(__ppc__)
- // This returns a time-base, which is not always precisely a cycle-count.
- uint32 tbu, tbl, tmp;
- __asm__ volatile (\
- "0:\n"
- "mftbu %0\n"
- "mftbl %1\n"
- "mftbu %2\n"
- "cmpw %0, %2\n"
- "bne- 0b"
- : "=r" (tbu), "=r" (tbl), "=r" (tmp));
- return (((uint64) tbu << 32) | tbl);
-#elif defined(__sparc__)
- int64 tick;
- asm(".byte 0x83, 0x41, 0x00, 0x00");
- asm("mov %%g1, %0" : "=r" (tick));
- return tick;
-#elif defined(__ia64__)
- int64 itc;
- asm("mov %0 = ar.itc" : "=r" (itc));
- return itc;
-#elif defined(_MSC_VER) && defined(_M_IX86)
- // Older MSVC compilers (like 7.x) don't seem to support the
- // __rdtsc intrinsic properly, so I prefer to use _asm instead
- // when I know it will work. Otherwise, I'll use __rdtsc and hope
- // the code is being compiled with a non-ancient compiler.
- _asm rdtsc
-#elif defined(_MSC_VER)
- return __rdtsc();
-#elif defined(ARMV3) || defined(__aarch64__)
-#if defined(ARMV7) // V7 is the earliest arch that has a standard cyclecount
- uint32 pmccntr;
- uint32 pmuseren;
- uint32 pmcntenset;
- // Read the user mode perf monitor counter access permissions.
- asm volatile ("mrc p15, 0, %0, c9, c14, 0" : "=r" (pmuseren));
- if (pmuseren & 1) { // Allows reading perfmon counters for user mode code.
- asm volatile ("mrc p15, 0, %0, c9, c12, 1" : "=r" (pmcntenset));
- if (pmcntenset & 0x80000000ul) { // Is it counting?
- asm volatile ("mrc p15, 0, %0, c9, c13, 0" : "=r" (pmccntr));
- // The counter is set up to count every 64th cycle
- return static_cast<int64>(pmccntr) * 64; // Should optimize to << 6
- }
- }
-#endif
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return static_cast<int64>((tv.tv_sec + tv.tv_usec * 0.000001)
- * CyclesPerSecond());
-#elif defined(__mips__)
- // mips apparently only allows rdtsc for superusers, so we fall
- // back to gettimeofday. It's possible clock_gettime would be better.
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return static_cast<int64>((tv.tv_sec + tv.tv_usec * 0.000001)
- * CyclesPerSecond());
-#else
-// The soft failover to a generic implementation is automatic only for ARM.
-// For other platforms the developer is expected to make an attempt to create
-// a fast implementation and use generic version if nothing better is available.
-#error You need to define CycleTimer for your O/S and CPU
-#endif
- }
-};
-
-
-#endif // GOOGLE_BASE_CYCLECLOCK_H_
diff --git a/src/base/dynamic_annotations.c b/src/base/dynamic_annotations.c
index 87bd2ec..9b966a7 100644
--- a/src/base/dynamic_annotations.c
+++ b/src/base/dynamic_annotations.c
@@ -1,3 +1,4 @@
+// -*- Mode: c; c-basic-offset: 2; indent-tabs-mode: nil -*-
/* Copyright (c) 2008-2009, Google Inc.
* All rights reserved.
*
@@ -42,101 +43,6 @@
#include "base/dynamic_annotations.h"
#include "getenv_safe.h" // for TCMallocGetenvSafe
-#ifdef __GNUC__
-/* valgrind.h uses gcc extensions so it won't build with other compilers */
-# ifdef HAVE_VALGRIND_H /* prefer the user's copy if they have it */
-# include <valgrind.h>
-# else /* otherwise just use the copy that we have */
-# include "third_party/valgrind.h"
-# endif
-#endif
-
-/* Compiler-based ThreadSanitizer defines
- DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL = 1
- and provides its own definitions of the functions. */
-
-#ifndef DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL
-# define DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL 0
-#endif
-
-/* Each function is empty and called (via a macro) only in debug mode.
- The arguments are captured by dynamic tools at runtime. */
-
-#if DYNAMIC_ANNOTATIONS_ENABLED == 1 \
- && DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0
-
-void AnnotateRWLockCreate(const char *file, int line,
- const volatile void *lock){}
-void AnnotateRWLockDestroy(const char *file, int line,
- const volatile void *lock){}
-void AnnotateRWLockAcquired(const char *file, int line,
- const volatile void *lock, long is_w){}
-void AnnotateRWLockReleased(const char *file, int line,
- const volatile void *lock, long is_w){}
-void AnnotateBarrierInit(const char *file, int line,
- const volatile void *barrier, long count,
- long reinitialization_allowed) {}
-void AnnotateBarrierWaitBefore(const char *file, int line,
- const volatile void *barrier) {}
-void AnnotateBarrierWaitAfter(const char *file, int line,
- const volatile void *barrier) {}
-void AnnotateBarrierDestroy(const char *file, int line,
- const volatile void *barrier) {}
-
-void AnnotateCondVarWait(const char *file, int line,
- const volatile void *cv,
- const volatile void *lock){}
-void AnnotateCondVarSignal(const char *file, int line,
- const volatile void *cv){}
-void AnnotateCondVarSignalAll(const char *file, int line,
- const volatile void *cv){}
-void AnnotatePublishMemoryRange(const char *file, int line,
- const volatile void *address,
- long size){}
-void AnnotateUnpublishMemoryRange(const char *file, int line,
- const volatile void *address,
- long size){}
-void AnnotatePCQCreate(const char *file, int line,
- const volatile void *pcq){}
-void AnnotatePCQDestroy(const char *file, int line,
- const volatile void *pcq){}
-void AnnotatePCQPut(const char *file, int line,
- const volatile void *pcq){}
-void AnnotatePCQGet(const char *file, int line,
- const volatile void *pcq){}
-void AnnotateNewMemory(const char *file, int line,
- const volatile void *mem,
- long size){}
-void AnnotateExpectRace(const char *file, int line,
- const volatile void *mem,
- const char *description){}
-void AnnotateBenignRace(const char *file, int line,
- const volatile void *mem,
- const char *description){}
-void AnnotateBenignRaceSized(const char *file, int line,
- const volatile void *mem,
- long size,
- const char *description) {}
-void AnnotateMutexIsUsedAsCondVar(const char *file, int line,
- const volatile void *mu){}
-void AnnotateTraceMemory(const char *file, int line,
- const volatile void *arg){}
-void AnnotateThreadName(const char *file, int line,
- const char *name){}
-void AnnotateIgnoreReadsBegin(const char *file, int line){}
-void AnnotateIgnoreReadsEnd(const char *file, int line){}
-void AnnotateIgnoreWritesBegin(const char *file, int line){}
-void AnnotateIgnoreWritesEnd(const char *file, int line){}
-void AnnotateEnableRaceDetection(const char *file, int line, int enable){}
-void AnnotateNoOp(const char *file, int line,
- const volatile void *arg){}
-void AnnotateFlushState(const char *file, int line){}
-
-#endif /* DYNAMIC_ANNOTATIONS_ENABLED == 1
- && DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 */
-
-#if DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0
-
static int GetRunningOnValgrind(void) {
#ifdef RUNNING_ON_VALGRIND
if (RUNNING_ON_VALGRIND) return 1;
@@ -152,28 +58,7 @@
int RunningOnValgrind(void) {
static volatile int running_on_valgrind = -1;
int local_running_on_valgrind = running_on_valgrind;
- /* C doesn't have thread-safe initialization of statics, and we
- don't want to depend on pthread_once here, so hack it. */
- ANNOTATE_BENIGN_RACE(&running_on_valgrind, "safe hack");
if (local_running_on_valgrind == -1)
running_on_valgrind = local_running_on_valgrind = GetRunningOnValgrind();
return local_running_on_valgrind;
}
-
-#endif /* DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 */
-
-/* See the comments in dynamic_annotations.h */
-double ValgrindSlowdown(void) {
- /* Same initialization hack as in RunningOnValgrind(). */
- static volatile double slowdown = 0.0;
- double local_slowdown = slowdown;
- ANNOTATE_BENIGN_RACE(&slowdown, "safe hack");
- if (RunningOnValgrind() == 0) {
- return 1.0;
- }
- if (local_slowdown == 0.0) {
- char *env = getenv("VALGRIND_SLOWDOWN");
- slowdown = local_slowdown = env ? atof(env) : 50.0;
- }
- return local_slowdown;
-}
diff --git a/src/base/dynamic_annotations.h b/src/base/dynamic_annotations.h
index 4669315..af944527 100644
--- a/src/base/dynamic_annotations.h
+++ b/src/base/dynamic_annotations.h
@@ -1,3 +1,4 @@
+/* -*- Mode: c; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/* Copyright (c) 2008, Google Inc.
* All rights reserved.
*
@@ -57,437 +58,9 @@
#ifndef BASE_DYNAMIC_ANNOTATIONS_H_
#define BASE_DYNAMIC_ANNOTATIONS_H_
-#ifndef DYNAMIC_ANNOTATIONS_ENABLED
-# define DYNAMIC_ANNOTATIONS_ENABLED 0
-#endif
-
-#if DYNAMIC_ANNOTATIONS_ENABLED != 0
-
- /* -------------------------------------------------------------
- Annotations useful when implementing condition variables such as CondVar,
- using conditional critical sections (Await/LockWhen) and when constructing
- user-defined synchronization mechanisms.
-
- The annotations ANNOTATE_HAPPENS_BEFORE() and ANNOTATE_HAPPENS_AFTER() can
- be used to define happens-before arcs in user-defined synchronization
- mechanisms: the race detector will infer an arc from the former to the
- latter when they share the same argument pointer.
-
- Example 1 (reference counting):
-
- void Unref() {
- ANNOTATE_HAPPENS_BEFORE(&refcount_);
- if (AtomicDecrementByOne(&refcount_) == 0) {
- ANNOTATE_HAPPENS_AFTER(&refcount_);
- delete this;
- }
- }
-
- Example 2 (message queue):
-
- void MyQueue::Put(Type *e) {
- MutexLock lock(&mu_);
- ANNOTATE_HAPPENS_BEFORE(e);
- PutElementIntoMyQueue(e);
- }
-
- Type *MyQueue::Get() {
- MutexLock lock(&mu_);
- Type *e = GetElementFromMyQueue();
- ANNOTATE_HAPPENS_AFTER(e);
- return e;
- }
-
- Note: when possible, please use the existing reference counting and message
- queue implementations instead of inventing new ones. */
-
- /* Report that wait on the condition variable at address "cv" has succeeded
- and the lock at address "lock" is held. */
- #define ANNOTATE_CONDVAR_LOCK_WAIT(cv, lock) \
- AnnotateCondVarWait(__FILE__, __LINE__, cv, lock)
-
- /* Report that wait on the condition variable at "cv" has succeeded. Variant
- w/o lock. */
- #define ANNOTATE_CONDVAR_WAIT(cv) \
- AnnotateCondVarWait(__FILE__, __LINE__, cv, NULL)
-
- /* Report that we are about to signal on the condition variable at address
- "cv". */
- #define ANNOTATE_CONDVAR_SIGNAL(cv) \
- AnnotateCondVarSignal(__FILE__, __LINE__, cv)
-
- /* Report that we are about to signal_all on the condition variable at "cv". */
- #define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) \
- AnnotateCondVarSignalAll(__FILE__, __LINE__, cv)
-
- /* Annotations for user-defined synchronization mechanisms. */
- #define ANNOTATE_HAPPENS_BEFORE(obj) ANNOTATE_CONDVAR_SIGNAL(obj)
- #define ANNOTATE_HAPPENS_AFTER(obj) ANNOTATE_CONDVAR_WAIT(obj)
-
- /* Report that the bytes in the range [pointer, pointer+size) are about
- to be published safely. The race checker will create a happens-before
- arc from the call ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size) to
- subsequent accesses to this memory.
- Note: this annotation may not work properly if the race detector uses
- sampling, i.e. does not observe all memory accesses.
- */
- #define ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size) \
- AnnotatePublishMemoryRange(__FILE__, __LINE__, pointer, size)
-
- /* DEPRECATED. Don't use it. */
- #define ANNOTATE_UNPUBLISH_MEMORY_RANGE(pointer, size) \
- AnnotateUnpublishMemoryRange(__FILE__, __LINE__, pointer, size)
-
- /* DEPRECATED. Don't use it. */
- #define ANNOTATE_SWAP_MEMORY_RANGE(pointer, size) \
- do { \
- ANNOTATE_UNPUBLISH_MEMORY_RANGE(pointer, size); \
- ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size); \
- } while (0)
-
- /* Instruct the tool to create a happens-before arc between mu->Unlock() and
- mu->Lock(). This annotation may slow down the race detector and hide real
- races. Normally it is used only when it would be difficult to annotate each
- of the mutex's critical sections individually using the annotations above.
- This annotation makes sense only for hybrid race detectors. For pure
- happens-before detectors this is a no-op. For more details see
- http://code.google.com/p/data-race-test/wiki/PureHappensBeforeVsHybrid . */
- #define ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mu) \
- AnnotateMutexIsUsedAsCondVar(__FILE__, __LINE__, mu)
-
- /* Deprecated. Use ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX. */
- #define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mu) \
- AnnotateMutexIsUsedAsCondVar(__FILE__, __LINE__, mu)
-
- /* -------------------------------------------------------------
- Annotations useful when defining memory allocators, or when memory that
- was protected in one way starts to be protected in another. */
-
- /* Report that a new memory at "address" of size "size" has been allocated.
- This might be used when the memory has been retrieved from a free list and
- is about to be reused, or when a the locking discipline for a variable
- changes. */
- #define ANNOTATE_NEW_MEMORY(address, size) \
- AnnotateNewMemory(__FILE__, __LINE__, address, size)
-
- /* -------------------------------------------------------------
- Annotations useful when defining FIFO queues that transfer data between
- threads. */
-
- /* Report that the producer-consumer queue (such as ProducerConsumerQueue) at
- address "pcq" has been created. The ANNOTATE_PCQ_* annotations
- should be used only for FIFO queues. For non-FIFO queues use
- ANNOTATE_HAPPENS_BEFORE (for put) and ANNOTATE_HAPPENS_AFTER (for get). */
- #define ANNOTATE_PCQ_CREATE(pcq) \
- AnnotatePCQCreate(__FILE__, __LINE__, pcq)
-
- /* Report that the queue at address "pcq" is about to be destroyed. */
- #define ANNOTATE_PCQ_DESTROY(pcq) \
- AnnotatePCQDestroy(__FILE__, __LINE__, pcq)
-
- /* Report that we are about to put an element into a FIFO queue at address
- "pcq". */
- #define ANNOTATE_PCQ_PUT(pcq) \
- AnnotatePCQPut(__FILE__, __LINE__, pcq)
-
- /* Report that we've just got an element from a FIFO queue at address "pcq". */
- #define ANNOTATE_PCQ_GET(pcq) \
- AnnotatePCQGet(__FILE__, __LINE__, pcq)
-
- /* -------------------------------------------------------------
- Annotations that suppress errors. It is usually better to express the
- program's synchronization using the other annotations, but these can
- be used when all else fails. */
-
- /* Report that we may have a benign race at "pointer", with size
- "sizeof(*(pointer))". "pointer" must be a non-void* pointer. Insert at the
- point where "pointer" has been allocated, preferably close to the point
- where the race happens. See also ANNOTATE_BENIGN_RACE_STATIC. */
- #define ANNOTATE_BENIGN_RACE(pointer, description) \
- AnnotateBenignRaceSized(__FILE__, __LINE__, pointer, \
- sizeof(*(pointer)), description)
-
- /* Same as ANNOTATE_BENIGN_RACE(address, description), but applies to
- the memory range [address, address+size). */
- #define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
- AnnotateBenignRaceSized(__FILE__, __LINE__, address, size, description)
-
- /* Request the analysis tool to ignore all reads in the current thread
- until ANNOTATE_IGNORE_READS_END is called.
- Useful to ignore intentional racey reads, while still checking
- other reads and all writes.
- See also ANNOTATE_UNPROTECTED_READ. */
- #define ANNOTATE_IGNORE_READS_BEGIN() \
- AnnotateIgnoreReadsBegin(__FILE__, __LINE__)
-
- /* Stop ignoring reads. */
- #define ANNOTATE_IGNORE_READS_END() \
- AnnotateIgnoreReadsEnd(__FILE__, __LINE__)
-
- /* Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes. */
- #define ANNOTATE_IGNORE_WRITES_BEGIN() \
- AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
-
- /* Stop ignoring writes. */
- #define ANNOTATE_IGNORE_WRITES_END() \
- AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
-
- /* Start ignoring all memory accesses (reads and writes). */
- #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
- do {\
- ANNOTATE_IGNORE_READS_BEGIN();\
- ANNOTATE_IGNORE_WRITES_BEGIN();\
- }while(0)\
-
- /* Stop ignoring all memory accesses. */
- #define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
- do {\
- ANNOTATE_IGNORE_WRITES_END();\
- ANNOTATE_IGNORE_READS_END();\
- }while(0)\
-
- /* Enable (enable!=0) or disable (enable==0) race detection for all threads.
- This annotation could be useful if you want to skip expensive race analysis
- during some period of program execution, e.g. during initialization. */
- #define ANNOTATE_ENABLE_RACE_DETECTION(enable) \
- AnnotateEnableRaceDetection(__FILE__, __LINE__, enable)
-
- /* -------------------------------------------------------------
- Annotations useful for debugging. */
-
- /* Request to trace every access to "address". */
- #define ANNOTATE_TRACE_MEMORY(address) \
- AnnotateTraceMemory(__FILE__, __LINE__, address)
-
- /* Report the current thread name to a race detector. */
- #define ANNOTATE_THREAD_NAME(name) \
- AnnotateThreadName(__FILE__, __LINE__, name)
-
- /* -------------------------------------------------------------
- Annotations useful when implementing locks. They are not
- normally needed by modules that merely use locks.
- The "lock" argument is a pointer to the lock object. */
-
- /* Report that a lock has been created at address "lock". */
- #define ANNOTATE_RWLOCK_CREATE(lock) \
- AnnotateRWLockCreate(__FILE__, __LINE__, lock)
-
- /* Report that the lock at address "lock" is about to be destroyed. */
- #define ANNOTATE_RWLOCK_DESTROY(lock) \
- AnnotateRWLockDestroy(__FILE__, __LINE__, lock)
-
- /* Report that the lock at address "lock" has been acquired.
- is_w=1 for writer lock, is_w=0 for reader lock. */
- #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
- AnnotateRWLockAcquired(__FILE__, __LINE__, lock, is_w)
-
- /* Report that the lock at address "lock" is about to be released. */
- #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
- AnnotateRWLockReleased(__FILE__, __LINE__, lock, is_w)
-
- /* -------------------------------------------------------------
- Annotations useful when implementing barriers. They are not
- normally needed by modules that merely use barriers.
- The "barrier" argument is a pointer to the barrier object. */
-
- /* Report that the "barrier" has been initialized with initial "count".
- If 'reinitialization_allowed' is true, initialization is allowed to happen
- multiple times w/o calling barrier_destroy() */
- #define ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed) \
- AnnotateBarrierInit(__FILE__, __LINE__, barrier, count, \
- reinitialization_allowed)
-
- /* Report that we are about to enter barrier_wait("barrier"). */
- #define ANNOTATE_BARRIER_WAIT_BEFORE(barrier) \
- AnnotateBarrierWaitBefore(__FILE__, __LINE__, barrier)
-
- /* Report that we just exited barrier_wait("barrier"). */
- #define ANNOTATE_BARRIER_WAIT_AFTER(barrier) \
- AnnotateBarrierWaitAfter(__FILE__, __LINE__, barrier)
-
- /* Report that the "barrier" has been destroyed. */
- #define ANNOTATE_BARRIER_DESTROY(barrier) \
- AnnotateBarrierDestroy(__FILE__, __LINE__, barrier)
-
- /* -------------------------------------------------------------
- Annotations useful for testing race detectors. */
-
- /* Report that we expect a race on the variable at "address".
- Use only in unit tests for a race detector. */
- #define ANNOTATE_EXPECT_RACE(address, description) \
- AnnotateExpectRace(__FILE__, __LINE__, address, description)
-
- /* A no-op. Insert where you like to test the interceptors. */
- #define ANNOTATE_NO_OP(arg) \
- AnnotateNoOp(__FILE__, __LINE__, arg)
-
- /* Force the race detector to flush its state. The actual effect depends on
- * the implementation of the detector. */
- #define ANNOTATE_FLUSH_STATE() \
- AnnotateFlushState(__FILE__, __LINE__)
-
-
-#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */
-
- #define ANNOTATE_RWLOCK_CREATE(lock) /* empty */
- #define ANNOTATE_RWLOCK_DESTROY(lock) /* empty */
- #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) /* empty */
- #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) /* empty */
- #define ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed) /* */
- #define ANNOTATE_BARRIER_WAIT_BEFORE(barrier) /* empty */
- #define ANNOTATE_BARRIER_WAIT_AFTER(barrier) /* empty */
- #define ANNOTATE_BARRIER_DESTROY(barrier) /* empty */
- #define ANNOTATE_CONDVAR_LOCK_WAIT(cv, lock) /* empty */
- #define ANNOTATE_CONDVAR_WAIT(cv) /* empty */
- #define ANNOTATE_CONDVAR_SIGNAL(cv) /* empty */
- #define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) /* empty */
- #define ANNOTATE_HAPPENS_BEFORE(obj) /* empty */
- #define ANNOTATE_HAPPENS_AFTER(obj) /* empty */
- #define ANNOTATE_PUBLISH_MEMORY_RANGE(address, size) /* empty */
- #define ANNOTATE_UNPUBLISH_MEMORY_RANGE(address, size) /* empty */
- #define ANNOTATE_SWAP_MEMORY_RANGE(address, size) /* empty */
- #define ANNOTATE_PCQ_CREATE(pcq) /* empty */
- #define ANNOTATE_PCQ_DESTROY(pcq) /* empty */
- #define ANNOTATE_PCQ_PUT(pcq) /* empty */
- #define ANNOTATE_PCQ_GET(pcq) /* empty */
- #define ANNOTATE_NEW_MEMORY(address, size) /* empty */
- #define ANNOTATE_EXPECT_RACE(address, description) /* empty */
- #define ANNOTATE_BENIGN_RACE(address, description) /* empty */
- #define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) /* empty */
- #define ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mu) /* empty */
- #define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mu) /* empty */
- #define ANNOTATE_TRACE_MEMORY(arg) /* empty */
- #define ANNOTATE_THREAD_NAME(name) /* empty */
- #define ANNOTATE_IGNORE_READS_BEGIN() /* empty */
- #define ANNOTATE_IGNORE_READS_END() /* empty */
- #define ANNOTATE_IGNORE_WRITES_BEGIN() /* empty */
- #define ANNOTATE_IGNORE_WRITES_END() /* empty */
- #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() /* empty */
- #define ANNOTATE_IGNORE_READS_AND_WRITES_END() /* empty */
- #define ANNOTATE_ENABLE_RACE_DETECTION(enable) /* empty */
- #define ANNOTATE_NO_OP(arg) /* empty */
- #define ANNOTATE_FLUSH_STATE() /* empty */
-
-#endif /* DYNAMIC_ANNOTATIONS_ENABLED */
-
-/* Macro definitions for GCC attributes that allow static thread safety
- analysis to recognize and use some of the dynamic annotations as
- escape hatches.
- TODO(lcwu): remove the check for __SUPPORT_DYN_ANNOTATION__ once the
- default crosstool/GCC supports these GCC attributes. */
-
-#define ANNOTALYSIS_STATIC_INLINE
-#define ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY ;
-#define ANNOTALYSIS_IGNORE_READS_BEGIN
-#define ANNOTALYSIS_IGNORE_READS_END
-#define ANNOTALYSIS_IGNORE_WRITES_BEGIN
-#define ANNOTALYSIS_IGNORE_WRITES_END
-#define ANNOTALYSIS_UNPROTECTED_READ
-
-#if defined(__GNUC__) && (!defined(SWIG)) && (!defined(__clang__)) && \
- defined(__SUPPORT_TS_ANNOTATION__) && defined(__SUPPORT_DYN_ANNOTATION__)
-
-#if DYNAMIC_ANNOTATIONS_ENABLED == 0
-#define ANNOTALYSIS_ONLY 1
-#undef ANNOTALYSIS_STATIC_INLINE
-#define ANNOTALYSIS_STATIC_INLINE static inline
-#undef ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
-#define ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY { (void)file; (void)line; }
-#endif
-
-/* Only emit attributes when annotalysis is enabled. */
-#if defined(__SUPPORT_TS_ANNOTATION__) && defined(__SUPPORT_DYN_ANNOTATION__)
-#undef ANNOTALYSIS_IGNORE_READS_BEGIN
-#define ANNOTALYSIS_IGNORE_READS_BEGIN __attribute__ ((ignore_reads_begin))
-#undef ANNOTALYSIS_IGNORE_READS_END
-#define ANNOTALYSIS_IGNORE_READS_END __attribute__ ((ignore_reads_end))
-#undef ANNOTALYSIS_IGNORE_WRITES_BEGIN
-#define ANNOTALYSIS_IGNORE_WRITES_BEGIN __attribute__ ((ignore_writes_begin))
-#undef ANNOTALYSIS_IGNORE_WRITES_END
-#define ANNOTALYSIS_IGNORE_WRITES_END __attribute__ ((ignore_writes_end))
-#undef ANNOTALYSIS_UNPROTECTED_READ
-#define ANNOTALYSIS_UNPROTECTED_READ __attribute__ ((unprotected_read))
-#endif
-
-#endif // defined(__GNUC__) && (!defined(SWIG)) && (!defined(__clang__))
-
-/* Use the macros above rather than using these functions directly. */
#ifdef __cplusplus
extern "C" {
#endif
-void AnnotateRWLockCreate(const char *file, int line,
- const volatile void *lock);
-void AnnotateRWLockDestroy(const char *file, int line,
- const volatile void *lock);
-void AnnotateRWLockAcquired(const char *file, int line,
- const volatile void *lock, long is_w);
-void AnnotateRWLockReleased(const char *file, int line,
- const volatile void *lock, long is_w);
-void AnnotateBarrierInit(const char *file, int line,
- const volatile void *barrier, long count,
- long reinitialization_allowed);
-void AnnotateBarrierWaitBefore(const char *file, int line,
- const volatile void *barrier);
-void AnnotateBarrierWaitAfter(const char *file, int line,
- const volatile void *barrier);
-void AnnotateBarrierDestroy(const char *file, int line,
- const volatile void *barrier);
-void AnnotateCondVarWait(const char *file, int line,
- const volatile void *cv,
- const volatile void *lock);
-void AnnotateCondVarSignal(const char *file, int line,
- const volatile void *cv);
-void AnnotateCondVarSignalAll(const char *file, int line,
- const volatile void *cv);
-void AnnotatePublishMemoryRange(const char *file, int line,
- const volatile void *address,
- long size);
-void AnnotateUnpublishMemoryRange(const char *file, int line,
- const volatile void *address,
- long size);
-void AnnotatePCQCreate(const char *file, int line,
- const volatile void *pcq);
-void AnnotatePCQDestroy(const char *file, int line,
- const volatile void *pcq);
-void AnnotatePCQPut(const char *file, int line,
- const volatile void *pcq);
-void AnnotatePCQGet(const char *file, int line,
- const volatile void *pcq);
-void AnnotateNewMemory(const char *file, int line,
- const volatile void *address,
- long size);
-void AnnotateExpectRace(const char *file, int line,
- const volatile void *address,
- const char *description);
-void AnnotateBenignRace(const char *file, int line,
- const volatile void *address,
- const char *description);
-void AnnotateBenignRaceSized(const char *file, int line,
- const volatile void *address,
- long size,
- const char *description);
-void AnnotateMutexIsUsedAsCondVar(const char *file, int line,
- const volatile void *mu);
-void AnnotateTraceMemory(const char *file, int line,
- const volatile void *arg);
-void AnnotateThreadName(const char *file, int line,
- const char *name);
-ANNOTALYSIS_STATIC_INLINE
-void AnnotateIgnoreReadsBegin(const char *file, int line)
- ANNOTALYSIS_IGNORE_READS_BEGIN ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
-ANNOTALYSIS_STATIC_INLINE
-void AnnotateIgnoreReadsEnd(const char *file, int line)
- ANNOTALYSIS_IGNORE_READS_END ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
-ANNOTALYSIS_STATIC_INLINE
-void AnnotateIgnoreWritesBegin(const char *file, int line)
- ANNOTALYSIS_IGNORE_WRITES_BEGIN ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
-ANNOTALYSIS_STATIC_INLINE
-void AnnotateIgnoreWritesEnd(const char *file, int line)
- ANNOTALYSIS_IGNORE_WRITES_END ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
-void AnnotateEnableRaceDetection(const char *file, int line, int enable);
-void AnnotateNoOp(const char *file, int line,
- const volatile void *arg);
-void AnnotateFlushState(const char *file, int line);
/* Return non-zero value if running under valgrind.
@@ -506,122 +79,8 @@
*/
int RunningOnValgrind(void);
-/* ValgrindSlowdown returns:
- * 1.0, if (RunningOnValgrind() == 0)
- * 50.0, if (RunningOnValgrind() != 0 && getenv("VALGRIND_SLOWDOWN") == NULL)
- * atof(getenv("VALGRIND_SLOWDOWN")) otherwise
- This function can be used to scale timeout values:
- EXAMPLE:
- for (;;) {
- DoExpensiveBackgroundTask();
- SleepForSeconds(5 * ValgrindSlowdown());
- }
- */
-double ValgrindSlowdown(void);
-
#ifdef __cplusplus
}
#endif
-#if DYNAMIC_ANNOTATIONS_ENABLED != 0 && defined(__cplusplus)
-
- /* ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
-
- Instead of doing
- ANNOTATE_IGNORE_READS_BEGIN();
- ... = x;
- ANNOTATE_IGNORE_READS_END();
- one can use
- ... = ANNOTATE_UNPROTECTED_READ(x); */
- template <class T>
- inline T ANNOTATE_UNPROTECTED_READ(const volatile T &x)
- ANNOTALYSIS_UNPROTECTED_READ {
- ANNOTATE_IGNORE_READS_BEGIN();
- T res = x;
- ANNOTATE_IGNORE_READS_END();
- return res;
- }
- /* Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable. */
- #define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \
- namespace { \
- class static_var ## _annotator { \
- public: \
- static_var ## _annotator() { \
- ANNOTATE_BENIGN_RACE_SIZED(&static_var, \
- sizeof(static_var), \
- # static_var ": " description); \
- } \
- }; \
- static static_var ## _annotator the ## static_var ## _annotator;\
- }
-#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */
-
- #define ANNOTATE_UNPROTECTED_READ(x) (x)
- #define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) /* empty */
-
-#endif /* DYNAMIC_ANNOTATIONS_ENABLED */
-
-/* Annotalysis, a GCC based static analyzer, is able to understand and use
- some of the dynamic annotations defined in this file. However, dynamic
- annotations are usually disabled in the opt mode (to avoid additional
- runtime overheads) while Annotalysis only works in the opt mode.
- In order for Annotalysis to use these dynamic annotations when they
- are disabled, we re-define these annotations here. Note that unlike the
- original macro definitions above, these macros are expanded to calls to
- static inline functions so that the compiler will be able to remove the
- calls after the analysis. */
-
-#ifdef ANNOTALYSIS_ONLY
-
- #undef ANNOTALYSIS_ONLY
-
- /* Undefine and re-define the macros that the static analyzer understands. */
- #undef ANNOTATE_IGNORE_READS_BEGIN
- #define ANNOTATE_IGNORE_READS_BEGIN() \
- AnnotateIgnoreReadsBegin(__FILE__, __LINE__)
-
- #undef ANNOTATE_IGNORE_READS_END
- #define ANNOTATE_IGNORE_READS_END() \
- AnnotateIgnoreReadsEnd(__FILE__, __LINE__)
-
- #undef ANNOTATE_IGNORE_WRITES_BEGIN
- #define ANNOTATE_IGNORE_WRITES_BEGIN() \
- AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
-
- #undef ANNOTATE_IGNORE_WRITES_END
- #define ANNOTATE_IGNORE_WRITES_END() \
- AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
-
- #undef ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN
- #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
- do { \
- ANNOTATE_IGNORE_READS_BEGIN(); \
- ANNOTATE_IGNORE_WRITES_BEGIN(); \
- }while(0) \
-
- #undef ANNOTATE_IGNORE_READS_AND_WRITES_END
- #define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
- do { \
- ANNOTATE_IGNORE_WRITES_END(); \
- ANNOTATE_IGNORE_READS_END(); \
- }while(0) \
-
- #if defined(__cplusplus)
- #undef ANNOTATE_UNPROTECTED_READ
- template <class T>
- inline T ANNOTATE_UNPROTECTED_READ(const volatile T &x)
- ANNOTALYSIS_UNPROTECTED_READ {
- ANNOTATE_IGNORE_READS_BEGIN();
- T res = x;
- ANNOTATE_IGNORE_READS_END();
- return res;
- }
- #endif /* __cplusplus */
-
-#endif /* ANNOTALYSIS_ONLY */
-
-/* Undefine the macros intended only in this file. */
-#undef ANNOTALYSIS_STATIC_INLINE
-#undef ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
-
#endif /* BASE_DYNAMIC_ANNOTATIONS_H_ */
diff --git a/src/base/elfcore.h b/src/base/elfcore.h
index d9599ed..11c09b4 100644
--- a/src/base/elfcore.h
+++ b/src/base/elfcore.h
@@ -41,13 +41,14 @@
/* We currently only support x86-32, x86-64, ARM, MIPS, PPC on Linux.
* Porting to other related platforms should not be difficult.
*/
-#if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) || \
+#if (defined(__i386__) || defined(__x86_64__) || defined(__arm__) || \
defined(__mips__) || defined(__PPC__)) && defined(__linux)
+#include "config.h"
+
#include <stdarg.h>
#include <stdint.h>
#include <sys/types.h>
-#include <config.h>
/* Define the DUMPER symbol to make sure that there is exactly one
@@ -89,7 +90,7 @@
uint16_t ss, __ss;
#endif
} i386_regs;
-#elif defined(__ARM_ARCH_3__)
+#elif defined(__arm__)
typedef struct arm_regs { /* General purpose registers */
#define BP uregs[11] /* Frame pointer */
#define SP uregs[13] /* Stack pointer */
@@ -126,274 +127,7 @@
} ppc_regs;
#endif
-#if defined(__i386__) && defined(__GNUC__)
- /* On x86 we provide an optimized version of the FRAME() macro, if the
- * compiler supports a GCC-style asm() directive. This results in somewhat
- * more accurate values for CPU registers.
- */
- typedef struct Frame {
- struct i386_regs uregs;
- int errno_;
- pid_t tid;
- } Frame;
- #define FRAME(f) Frame f; \
- do { \
- f.errno_ = errno; \
- f.tid = sys_gettid(); \
- __asm__ volatile ( \
- "push %%ebp\n" \
- "push %%ebx\n" \
- "mov %%ebx,0(%%eax)\n" \
- "mov %%ecx,4(%%eax)\n" \
- "mov %%edx,8(%%eax)\n" \
- "mov %%esi,12(%%eax)\n" \
- "mov %%edi,16(%%eax)\n" \
- "mov %%ebp,20(%%eax)\n" \
- "mov %%eax,24(%%eax)\n" \
- "mov %%ds,%%ebx\n" \
- "mov %%ebx,28(%%eax)\n" \
- "mov %%es,%%ebx\n" \
- "mov %%ebx,32(%%eax)\n" \
- "mov %%fs,%%ebx\n" \
- "mov %%ebx,36(%%eax)\n" \
- "mov %%gs,%%ebx\n" \
- "mov %%ebx, 40(%%eax)\n" \
- "call 0f\n" \
- "0:pop %%ebx\n" \
- "add $1f-0b,%%ebx\n" \
- "mov %%ebx,48(%%eax)\n" \
- "mov %%cs,%%ebx\n" \
- "mov %%ebx,52(%%eax)\n" \
- "pushf\n" \
- "pop %%ebx\n" \
- "mov %%ebx,56(%%eax)\n" \
- "mov %%esp,%%ebx\n" \
- "add $8,%%ebx\n" \
- "mov %%ebx,60(%%eax)\n" \
- "mov %%ss,%%ebx\n" \
- "mov %%ebx,64(%%eax)\n" \
- "pop %%ebx\n" \
- "pop %%ebp\n" \
- "1:" \
- : : "a" (&f) : "memory"); \
- } while (0)
- #define SET_FRAME(f,r) \
- do { \
- errno = (f).errno_; \
- (r) = (f).uregs; \
- } while (0)
-#elif defined(__x86_64__) && defined(__GNUC__)
- /* The FRAME and SET_FRAME macros for x86_64. */
- typedef struct Frame {
- struct i386_regs uregs;
- int errno_;
- pid_t tid;
- } Frame;
- #define FRAME(f) Frame f; \
- do { \
- f.errno_ = errno; \
- f.tid = sys_gettid(); \
- __asm__ volatile ( \
- "push %%rbp\n" \
- "push %%rbx\n" \
- "mov %%r15,0(%%rax)\n" \
- "mov %%r14,8(%%rax)\n" \
- "mov %%r13,16(%%rax)\n" \
- "mov %%r12,24(%%rax)\n" \
- "mov %%rbp,32(%%rax)\n" \
- "mov %%rbx,40(%%rax)\n" \
- "mov %%r11,48(%%rax)\n" \
- "mov %%r10,56(%%rax)\n" \
- "mov %%r9,64(%%rax)\n" \
- "mov %%r8,72(%%rax)\n" \
- "mov %%rax,80(%%rax)\n" \
- "mov %%rcx,88(%%rax)\n" \
- "mov %%rdx,96(%%rax)\n" \
- "mov %%rsi,104(%%rax)\n" \
- "mov %%rdi,112(%%rax)\n" \
- "mov %%ds,%%rbx\n" \
- "mov %%rbx,184(%%rax)\n" \
- "mov %%es,%%rbx\n" \
- "mov %%rbx,192(%%rax)\n" \
- "mov %%fs,%%rbx\n" \
- "mov %%rbx,200(%%rax)\n" \
- "mov %%gs,%%rbx\n" \
- "mov %%rbx,208(%%rax)\n" \
- "call 0f\n" \
- "0:pop %%rbx\n" \
- "add $1f-0b,%%rbx\n" \
- "mov %%rbx,128(%%rax)\n" \
- "mov %%cs,%%rbx\n" \
- "mov %%rbx,136(%%rax)\n" \
- "pushf\n" \
- "pop %%rbx\n" \
- "mov %%rbx,144(%%rax)\n" \
- "mov %%rsp,%%rbx\n" \
- "add $16,%%ebx\n" \
- "mov %%rbx,152(%%rax)\n" \
- "mov %%ss,%%rbx\n" \
- "mov %%rbx,160(%%rax)\n" \
- "pop %%rbx\n" \
- "pop %%rbp\n" \
- "1:" \
- : : "a" (&f) : "memory"); \
- } while (0)
- #define SET_FRAME(f,r) \
- do { \
- errno = (f).errno_; \
- (f).uregs.fs_base = (r).fs_base; \
- (f).uregs.gs_base = (r).gs_base; \
- (r) = (f).uregs; \
- } while (0)
-#elif defined(__ARM_ARCH_3__) && defined(__GNUC__)
- /* ARM calling conventions are a little more tricky. A little assembly
- * helps in obtaining an accurate snapshot of all registers.
- */
- typedef struct Frame {
- struct arm_regs arm;
- int errno_;
- pid_t tid;
- } Frame;
- #define FRAME(f) Frame f; \
- do { \
- long cpsr; \
- f.errno_ = errno; \
- f.tid = sys_gettid(); \
- __asm__ volatile( \
- "stmia %0, {r0-r15}\n" /* All integer regs */\
- : : "r"(&f.arm) : "memory"); \
- f.arm.uregs[16] = 0; \
- __asm__ volatile( \
- "mrs %0, cpsr\n" /* Condition code reg */\
- : "=r"(cpsr)); \
- f.arm.uregs[17] = cpsr; \
- } while (0)
- #define SET_FRAME(f,r) \
- do { \
- /* Don't override the FPU status register. */\
- /* Use the value obtained from ptrace(). This*/\
- /* works, because our code does not perform */\
- /* any FPU operations, itself. */\
- long fps = (f).arm.uregs[16]; \
- errno = (f).errno_; \
- (r) = (f).arm; \
- (r).uregs[16] = fps; \
- } while (0)
-#elif defined(__mips__) && defined(__GNUC__)
- typedef struct Frame {
- struct mips_regs mips_regs;
- int errno_;
- pid_t tid;
- } Frame;
- #define MIPSREG(n) ({ register unsigned long r __asm__("$"#n); r; })
- #define FRAME(f) Frame f = { 0 }; \
- do { \
- unsigned long hi, lo; \
- register unsigned long pc __asm__("$31"); \
- f.mips_regs.uregs[ 0] = MIPSREG( 0); \
- f.mips_regs.uregs[ 1] = MIPSREG( 1); \
- f.mips_regs.uregs[ 2] = MIPSREG( 2); \
- f.mips_regs.uregs[ 3] = MIPSREG( 3); \
- f.mips_regs.uregs[ 4] = MIPSREG( 4); \
- f.mips_regs.uregs[ 5] = MIPSREG( 5); \
- f.mips_regs.uregs[ 6] = MIPSREG( 6); \
- f.mips_regs.uregs[ 7] = MIPSREG( 7); \
- f.mips_regs.uregs[ 8] = MIPSREG( 8); \
- f.mips_regs.uregs[ 9] = MIPSREG( 9); \
- f.mips_regs.uregs[10] = MIPSREG(10); \
- f.mips_regs.uregs[11] = MIPSREG(11); \
- f.mips_regs.uregs[12] = MIPSREG(12); \
- f.mips_regs.uregs[13] = MIPSREG(13); \
- f.mips_regs.uregs[14] = MIPSREG(14); \
- f.mips_regs.uregs[15] = MIPSREG(15); \
- f.mips_regs.uregs[16] = MIPSREG(16); \
- f.mips_regs.uregs[17] = MIPSREG(17); \
- f.mips_regs.uregs[18] = MIPSREG(18); \
- f.mips_regs.uregs[19] = MIPSREG(19); \
- f.mips_regs.uregs[20] = MIPSREG(20); \
- f.mips_regs.uregs[21] = MIPSREG(21); \
- f.mips_regs.uregs[22] = MIPSREG(22); \
- f.mips_regs.uregs[23] = MIPSREG(23); \
- f.mips_regs.uregs[24] = MIPSREG(24); \
- f.mips_regs.uregs[25] = MIPSREG(25); \
- f.mips_regs.uregs[26] = MIPSREG(26); \
- f.mips_regs.uregs[27] = MIPSREG(27); \
- f.mips_regs.uregs[28] = MIPSREG(28); \
- f.mips_regs.uregs[29] = MIPSREG(29); \
- f.mips_regs.uregs[30] = MIPSREG(30); \
- f.mips_regs.uregs[31] = MIPSREG(31); \
- __asm__ volatile ("mfhi %0" : "=r"(hi)); \
- __asm__ volatile ("mflo %0" : "=r"(lo)); \
- __asm__ volatile ("jal 1f; 1:nop" : "=r"(pc)); \
- f.mips_regs.hi = hi; \
- f.mips_regs.lo = lo; \
- f.mips_regs.cp0_epc = pc; \
- f.errno_ = errno; \
- f.tid = sys_gettid(); \
- } while (0)
- #define SET_FRAME(f,r) \
- do { \
- errno = (f).errno_; \
- memcpy((r).uregs, (f).mips_regs.uregs, \
- 32*sizeof(unsigned long)); \
- (r).hi = (f).mips_regs.hi; \
- (r).lo = (f).mips_regs.lo; \
- (r).cp0_epc = (f).mips_regs.cp0_epc; \
- } while (0)
-#else
- /* If we do not have a hand-optimized assembly version of the FRAME()
- * macro, we cannot reliably unroll the stack. So, we show a few additional
- * stack frames for the coredumper.
- */
- typedef struct Frame {
- pid_t tid;
- } Frame;
- #define FRAME(f) Frame f; do { f.tid = sys_gettid(); } while (0)
- #define SET_FRAME(f,r) do { } while (0)
-#endif
-
-
-/* Internal function for generating a core file. This API can change without
- * notice and is only supposed to be used internally by the core dumper.
- *
- * This function works for both single- and multi-threaded core
- * dumps. If called as
- *
- * FRAME(frame);
- * InternalGetCoreDump(&frame, 0, NULL, ap);
- *
- * it creates a core file that only contains information about the
- * calling thread.
- *
- * Optionally, the caller can provide information about other threads
- * by passing their process ids in "thread_pids". The process id of
- * the caller should not be included in this array. All of the threads
- * must have been attached to with ptrace(), prior to calling this
- * function. They will be detached when "InternalGetCoreDump()" returns.
- *
- * This function either returns a file handle that can be read for obtaining
- * a core dump, or "-1" in case of an error. In the latter case, "errno"
- * will be set appropriately.
- *
- * While "InternalGetCoreDump()" is not technically async signal safe, you
- * might be tempted to invoke it from a signal handler. The code goes to
- * great lengths to make a best effort that this will actually work. But in
- * any case, you must make sure that you preserve the value of "errno"
- * yourself. It is guaranteed to be clobbered otherwise.
- *
- * Also, "InternalGetCoreDump" is not strictly speaking re-entrant. Again,
- * it makes a best effort to behave reasonably when called in a multi-
- * threaded environment, but it is ultimately the caller's responsibility
- * to provide locking.
- */
-int InternalGetCoreDump(void *frame, int num_threads, pid_t *thread_pids,
- va_list ap
- /* const struct CoreDumpParameters *params,
- const char *file_name,
- const char *PATH
- */);
-
-#endif
+#endif // __linux and various arches
#ifdef __cplusplus
}
diff --git a/src/base/googleinit.h b/src/base/googleinit.h
index 3ea411a..a290427 100644
--- a/src/base/googleinit.h
+++ b/src/base/googleinit.h
@@ -1,11 +1,11 @@
// -*- 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
@@ -15,7 +15,7 @@
// * 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
diff --git a/src/base/linux_syscall_support.h b/src/base/linux_syscall_support.h
index 56b8fac..d6899b8 100644
--- a/src/base/linux_syscall_support.h
+++ b/src/base/linux_syscall_support.h
@@ -130,11 +130,14 @@
#ifndef SYS_LINUX_SYSCALL_SUPPORT_H
#define SYS_LINUX_SYSCALL_SUPPORT_H
-/* We currently only support x86-32, x86-64, ARM, MIPS, PPC/PPC64 and Aarch64 on Linux.
+/* We currently only support x86-32, x86-64, ARM, MIPS, PPC/PPC64, Aarch64,
+ * s390, s390x, and riscv64 on Linux.
* Porting to other related platforms should not be difficult.
*/
#if (defined(__i386__) || defined(__x86_64__) || defined(__arm__) || \
- defined(__mips__) || defined(__PPC__) || defined(__aarch64__)) && defined(__linux)
+ defined(__mips__) || defined(__mips64) || defined(__mips64el__) || defined(__PPC__) || \
+ defined(__aarch64__) || defined(__s390__) || defined(__riscv)) \
+ && (defined(__linux))
#ifndef SYS_CPLUSPLUS
#ifdef __cplusplus
@@ -159,6 +162,7 @@
#include <unistd.h>
#include <linux/unistd.h>
#include <endian.h>
+#include <fcntl.h>
#ifdef __mips__
/* Include definitions of the ABI currently in use. */
@@ -245,7 +249,8 @@
long ru_nivcsw;
};
-#if defined(__i386__) || defined(__arm__) || defined(__PPC__)
+#if defined(__i386__) || defined(__arm__) \
+ || defined(__PPC__) || (defined(__s390__) && !defined(__s390x__))
/* include/asm-{arm,i386,mips,ppc}/signal.h */
struct kernel_old_sigaction {
@@ -259,6 +264,8 @@
} __attribute__((packed,aligned(4)));
#elif (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32)
#define kernel_old_sigaction kernel_sigaction
+#elif defined(__aarch64__)
+ // No kernel_old_sigaction defined for arm64.
#endif
/* Some kernel functions (e.g. sigaction() in 2.6.23) require that the
@@ -302,9 +309,9 @@
#endif
};
-/* include/asm-{arm,i386,mips,ppc}/stat.h */
+/* include/asm-{arm,i386,mips,ppc,s390}/stat.h */
#ifdef __mips__
-#if _MIPS_SIM == _MIPS_SIM_ABI64
+#if (_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32)
struct kernel_stat {
#else
struct kernel_stat64 {
@@ -373,7 +380,7 @@
};
#endif
-/* include/asm-{arm,generic,i386,mips,x86_64,ppc}/stat.h */
+/* include/asm-{arm,generic,i386,mips,x86_64,ppc,s390}/stat.h */
#if defined(__i386__) || defined(__arm__)
struct kernel_stat {
/* The kernel headers suggest that st_dev and st_rdev should be 32bit
@@ -443,7 +450,8 @@
unsigned long __unused5;
unsigned long __unused6;
};
-#elif (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI64)
+#elif defined(__mips__) \
+ && !(_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32)
struct kernel_stat {
unsigned st_dev;
int st_pad1[3];
@@ -489,6 +497,50 @@
unsigned int __unused4;
unsigned int __unused5;
};
+#elif defined(__s390x__)
+struct kernel_stat {
+ unsigned long st_dev;
+ unsigned long st_ino;
+ unsigned long st_nlink;
+ unsigned int st_mode;
+ unsigned int st_uid;
+ unsigned int st_gid;
+ unsigned int __pad1;
+ unsigned long st_rdev;
+ unsigned long st_size;
+ unsigned long st_atime_;
+ unsigned long st_atime_nsec_;
+ unsigned long st_mtime_;
+ unsigned long st_mtime_nsec_;
+ unsigned long st_ctime_;
+ unsigned long st_ctime_nsec_;
+ unsigned long st_blksize;
+ long st_blocks;
+ unsigned long __unused[3];
+};
+#elif defined(__s390__)
+struct kernel_stat {
+ unsigned short st_dev;
+ unsigned short __pad1;
+ unsigned long st_ino;
+ unsigned short st_mode;
+ unsigned short st_nlink;
+ unsigned short st_uid;
+ unsigned short st_gid;
+ unsigned short st_rdev;
+ unsigned short __pad2;
+ unsigned long st_size;
+ unsigned long st_blksize;
+ unsigned long st_blocks;
+ unsigned long st_atime_;
+ unsigned long st_atime_nsec_;
+ unsigned long st_mtime_;
+ unsigned long st_mtime_nsec_;
+ unsigned long st_ctime_;
+ unsigned long st_ctime_nsec_;
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
#endif
@@ -632,7 +684,7 @@
#define __NR_getcpu (__NR_Linux + 312)
#endif
/* End of MIPS (old 32bit API) definitions */
-#elif _MIPS_SIM == _MIPS_SIM_ABI64
+#elif (_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32)
#ifndef __NR_gettid
#define __NR_gettid (__NR_Linux + 178)
#endif
@@ -697,12 +749,211 @@
#ifndef __NR_getcpu
#define __NR_getcpu 302
#endif
-/* End of powerpc defininitions */
+/* End of powerpc definitions */
#elif defined(__aarch64__)
#ifndef __NR_fstatat
#define __NR_fstatat 79
#endif
-/* End of aarch64 defininitions */
+/* End of aarch64 definitions */
+#elif defined(__s390__)
+#ifndef __NR_quotactl
+#define __NR_quotactl 131
+#endif
+#ifndef __NR_rt_sigreturn
+#define __NR_rt_sigreturn 173
+#endif
+#ifndef __NR_rt_sigaction
+#define __NR_rt_sigaction 174
+#endif
+#ifndef __NR_rt_sigprocmask
+#define __NR_rt_sigprocmask 175
+#endif
+#ifndef __NR_rt_sigpending
+#define __NR_rt_sigpending 176
+#endif
+#ifndef __NR_rt_sigsuspend
+#define __NR_rt_sigsuspend 179
+#endif
+#ifndef __NR_pread64
+#define __NR_pread64 180
+#endif
+#ifndef __NR_pwrite64
+#define __NR_pwrite64 181
+#endif
+#ifndef __NR_getdents64
+#define __NR_getdents64 220
+#endif
+#ifndef __NR_readahead
+#define __NR_readahead 222
+#endif
+#ifndef __NR_setxattr
+#define __NR_setxattr 224
+#endif
+#ifndef __NR_lsetxattr
+#define __NR_lsetxattr 225
+#endif
+#ifndef __NR_getxattr
+#define __NR_getxattr 227
+#endif
+#ifndef __NR_lgetxattr
+#define __NR_lgetxattr 228
+#endif
+#ifndef __NR_listxattr
+#define __NR_listxattr 230
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr 231
+#endif
+#ifndef __NR_gettid
+#define __NR_gettid 236
+#endif
+#ifndef __NR_tkill
+#define __NR_tkill 237
+#endif
+#ifndef __NR_futex
+#define __NR_futex 238
+#endif
+#ifndef __NR_sched_setaffinity
+#define __NR_sched_setaffinity 239
+#endif
+#ifndef __NR_sched_getaffinity
+#define __NR_sched_getaffinity 240
+#endif
+#ifndef __NR_set_tid_address
+#define __NR_set_tid_address 252
+#endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime 260
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres 261
+#endif
+#ifndef __NR_statfs64
+#define __NR_statfs64 265
+#endif
+#ifndef __NR_fstatfs64
+#define __NR_fstatfs64 266
+#endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set 282
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get 283
+#endif
+#ifndef __NR_openat
+#define __NR_openat 288
+#endif
+#ifndef __NR_unlinkat
+#define __NR_unlinkat 294
+#endif
+#ifndef __NR_move_pages
+#define __NR_move_pages 310
+#endif
+#ifndef __NR_getcpu
+#define __NR_getcpu 311
+#endif
+#ifndef __NR_fallocate
+#define __NR_fallocate 314
+#endif
+/* Some syscalls are named/numbered differently between s390 and s390x. */
+#ifdef __s390x__
+# ifndef __NR_getrlimit
+# define __NR_getrlimit 191
+# endif
+# ifndef __NR_setresuid
+# define __NR_setresuid 208
+# endif
+# ifndef __NR_getresuid
+# define __NR_getresuid 209
+# endif
+# ifndef __NR_setresgid
+# define __NR_setresgid 210
+# endif
+# ifndef __NR_getresgid
+# define __NR_getresgid 211
+# endif
+# ifndef __NR_setfsuid
+# define __NR_setfsuid 215
+# endif
+# ifndef __NR_setfsgid
+# define __NR_setfsgid 216
+# endif
+# ifndef __NR_fadvise64
+# define __NR_fadvise64 253
+# endif
+# ifndef __NR_newfstatat
+# define __NR_newfstatat 293
+# endif
+#else /* __s390x__ */
+# ifndef __NR_getrlimit
+# define __NR_getrlimit 76
+# endif
+# ifndef __NR_setfsuid
+# define __NR_setfsuid 138
+# endif
+# ifndef __NR_setfsgid
+# define __NR_setfsgid 139
+# endif
+# ifndef __NR_setresuid
+# define __NR_setresuid 164
+# endif
+# ifndef __NR_getresuid
+# define __NR_getresuid 165
+# endif
+# ifndef __NR_setresgid
+# define __NR_setresgid 170
+# endif
+# ifndef __NR_getresgid
+# define __NR_getresgid 171
+# endif
+# ifndef __NR_ugetrlimit
+# define __NR_ugetrlimit 191
+# endif
+# ifndef __NR_mmap2
+# define __NR_mmap2 192
+# endif
+# ifndef __NR_setresuid32
+# define __NR_setresuid32 208
+# endif
+# ifndef __NR_getresuid32
+# define __NR_getresuid32 209
+# endif
+# ifndef __NR_setresgid32
+# define __NR_setresgid32 210
+# endif
+# ifndef __NR_getresgid32
+# define __NR_getresgid32 211
+# endif
+# ifndef __NR_setfsuid32
+# define __NR_setfsuid32 215
+# endif
+# ifndef __NR_setfsgid32
+# define __NR_setfsgid32 216
+# endif
+# ifndef __NR_fadvise64_64
+# define __NR_fadvise64_64 264
+# endif
+# ifndef __NR_fstatat64
+# define __NR_fstatat64 293
+# endif
+#endif /* __s390__ */
+/* End of s390/s390x definitions */
+#elif defined(__riscv)
+# ifndef __NR_gettid
+# define __NR_gettid 178
+# endif
+# ifndef __NR_futex
+# define __NR_futex 422
+# endif
+# ifndef __NR_getdents64
+# define __NR_getdents64 61
+# endif
+# ifndef __NR_openat
+# define __NR_openat 56
+# endif
+# ifndef __NR_fstatat
+# define __NR_fstatat 79
+# endif
#endif
@@ -766,7 +1017,7 @@
#undef LSS_RETURN
#if (defined(__i386__) || defined(__x86_64__) || defined(__arm__) || \
- defined(__aarch64__))
+ defined(__aarch64__) || defined(__s390__) || defined(__riscv))
/* Failing system calls return a negative result in the range of
* -1..-4095. These are "errno" values with the sign inverted.
*/
@@ -831,7 +1082,7 @@
"pop %%ebx\n" \
CFI_ADJUST_CFA_OFFSET(-4) \
args \
- : "esp", "memory"); \
+ : "memory"); \
LSS_RETURN(type,__res)
#undef _syscall0
#define _syscall0(type,name) \
@@ -888,7 +1139,7 @@
: "i" (__NR_##name), "ri" ((long)(arg1)), \
"c" ((long)(arg2)), "d" ((long)(arg3)), \
"S" ((long)(arg4)), "D" ((long)(arg5)) \
- : "esp", "memory"); \
+ : "memory"); \
LSS_RETURN(type,__res); \
}
#undef _syscall6
@@ -910,7 +1161,7 @@
: "i" (__NR_##name), "0" ((long)(&__s)), \
"c" ((long)(arg2)), "d" ((long)(arg3)), \
"S" ((long)(arg4)), "D" ((long)(arg5)) \
- : "esp", "memory"); \
+ : "memory"); \
LSS_RETURN(type,__res); \
}
LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
@@ -996,7 +1247,7 @@
: "0"(-EINVAL), "i"(__NR_clone),
"m"(fn), "m"(child_stack), "m"(flags), "m"(arg),
"m"(parent_tidptr), "m"(newtls), "m"(child_tidptr)
- : "esp", "memory", "ecx", "edx", "esi", "edi");
+ : "memory", "ecx", "edx", "esi", "edi");
LSS_RETURN(int, __res);
}
@@ -1250,7 +1501,7 @@
"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);
}
@@ -1582,8 +1833,8 @@
".set reorder\n" \
: "=&r"(__v0), "+r" (__r7) \
: "i" (__NR_##name), "r"(__r4), "r"(__r5), \
- "r"(__r6), "r" ((unsigned long)arg5), \
- "r" ((unsigned long)arg6) \
+ "r"(__r6), "m" ((unsigned long)arg5), \
+ "m" ((unsigned long)arg6) \
: MIPS_SYSCALL_CLOBBERS); \
LSS_RETURN(type, __v0, __r7); \
}
@@ -1972,7 +2223,7 @@
"svc 0x0\n" \
: "=r"(__res_x0) \
: "i"(__NR_##name) , ## args \
- : "memory"); \
+ : "x8", "memory"); \
__res = __res_x0; \
LSS_RETURN(type, __res)
#undef _syscall0
@@ -1986,17 +2237,23 @@
LSS_REG(0, arg1); LSS_BODY(type, name, "r"(__x0)); \
}
#undef _syscall2
- #define _syscall2(type, name, type1, arg1, type2, arg2) \
+ #define _syscall2_long(type, name, svc, type1, arg1, type2, arg2) \
type LSS_NAME(name)(type1 arg1, type2 arg2) { \
LSS_REG(0, arg1); LSS_REG(1, arg2); \
- LSS_BODY(type, name, "r"(__x0), "r"(__x1)); \
+ LSS_BODY(type, svc, "r"(__x0), "r"(__x1)); \
}
+ #define _syscall2(type, name, type1, arg1, type2, arg2) \
+ _syscall2_long(type, name, name, type1, arg1, type2, arg2)
#undef _syscall3
- #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
+ #define _syscall3_long(type, name, svc, type1, arg1, type2, arg2, \
+ type3, arg3) \
type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \
LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \
- LSS_BODY(type, name, "r"(__x0), "r"(__x1), "r"(__x2)); \
+ LSS_BODY(type, svc, "r"(__x0), "r"(__x1), "r"(__x2)); \
}
+ #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
+ _syscall3_long(type, name, name, type1, arg1, type2, arg2, \
+ type3, arg3)
#undef _syscall4
#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
@@ -2015,15 +2272,19 @@
"r"(__x4)); \
}
#undef _syscall6
- #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
- type5,arg5,type6,arg6) \
+ #define _syscall6_long(type,name,svc,type1,arg1,type2,arg2,type3,arg3, \
+ type4,arg4,type5,arg5,type6,arg6) \
type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
type5 arg5, type6 arg6) { \
LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \
LSS_REG(3, arg4); LSS_REG(4, arg5); LSS_REG(5, arg6); \
- LSS_BODY(type, name, "r"(__x0), "r"(__x1), "x"(__x2), "r"(__x3), \
+ LSS_BODY(type, svc, "r"(__x0), "r"(__x1), "x"(__x2), "r"(__x3), \
"r"(__x4), "r"(__x5)); \
}
+ #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+ type5,arg5,type6,arg6) \
+ _syscall6_long(type,name,name,type1,arg1,type2,arg2,type3,arg3, \
+ type4,arg4,type5,arg5,type6,arg6)
/* clone function adapted from glibc 2.18 clone.S */
LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
int flags, void *arg, int *parent_tidptr,
@@ -2079,20 +2340,252 @@
"r"(__fn), "r"(__stack), "r"(__flags), "r"(__arg),
"r"(__ptid), "r"(__tls), "r"(__ctid),
"i"(__NR_clone), "i"(__NR_exit)
- : "x30", "memory");
+ : "x8", "x30", "memory");
}
LSS_RETURN(int, __res);
}
+ #elif defined(__s390__)
+ #undef LSS_REG
+ #define LSS_REG(r, a) register unsigned long __r##r __asm__("r"#r) = (unsigned long) a
+ #undef LSS_BODY
+ #define LSS_BODY(type, name, args...) \
+ register unsigned long __nr __asm__("r1") \
+ = (unsigned long)(__NR_##name); \
+ register long __res_r2 __asm__("r2"); \
+ long __res; \
+ __asm__ __volatile__ \
+ ("svc 0\n\t" \
+ : "=d"(__res_r2) \
+ : "d"(__nr), ## args \
+ : "memory"); \
+ __res = __res_r2; \
+ LSS_RETURN(type, __res)
+ #undef _syscall0
+ #define _syscall0(type, name) \
+ type LSS_NAME(name)(void) { \
+ LSS_BODY(type, name); \
+ }
+ #undef _syscall1
+ #define _syscall1(type, name, type1, arg1) \
+ type LSS_NAME(name)(type1 arg1) { \
+ LSS_REG(2, arg1); \
+ LSS_BODY(type, name, "0"(__r2)); \
+ }
+ #undef _syscall2
+ #define _syscall2(type, name, type1, arg1, type2, arg2) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2) { \
+ LSS_REG(2, arg1); LSS_REG(3, arg2); \
+ LSS_BODY(type, name, "0"(__r2), "d"(__r3)); \
+ }
+ #undef _syscall3
+ #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \
+ LSS_REG(2, arg1); LSS_REG(3, arg2); LSS_REG(4, arg3); \
+ LSS_BODY(type, name, "0"(__r2), "d"(__r3), "d"(__r4)); \
+ }
+ #undef _syscall4
+ #define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, \
+ type4 arg4) { \
+ LSS_REG(2, arg1); LSS_REG(3, arg2); LSS_REG(4, arg3); \
+ LSS_REG(5, arg4); \
+ LSS_BODY(type, name, "0"(__r2), "d"(__r3), "d"(__r4), \
+ "d"(__r5)); \
+ }
+ #undef _syscall5
+ #define _syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4, type5, arg5) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, \
+ type4 arg4, type5 arg5) { \
+ LSS_REG(2, arg1); LSS_REG(3, arg2); LSS_REG(4, arg3); \
+ LSS_REG(5, arg4); LSS_REG(6, arg5); \
+ LSS_BODY(type, name, "0"(__r2), "d"(__r3), "d"(__r4), \
+ "d"(__r5), "d"(__r6)); \
+ }
+ #undef _syscall6
+ #define _syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4, type5, arg5, type6, arg6) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, \
+ type4 arg4, type5 arg5, type6 arg6) { \
+ LSS_REG(2, arg1); LSS_REG(3, arg2); LSS_REG(4, arg3); \
+ LSS_REG(5, arg4); LSS_REG(6, arg5); LSS_REG(7, arg6); \
+ LSS_BODY(type, name, "0"(__r2), "d"(__r3), "d"(__r4), \
+ "d"(__r5), "d"(__r6), "d"(__r7)); \
+ }
+ LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
+ int flags, void *arg, int *parent_tidptr,
+ void *newtls, int *child_tidptr) {
+ long __ret;
+ {
+ register int (*__fn)(void *) __asm__ ("r1") = fn;
+ register void *__cstack __asm__ ("r2") = child_stack;
+ register int __flags __asm__ ("r3") = flags;
+ register void *__arg __asm__ ("r0") = arg;
+ register int *__ptidptr __asm__ ("r4") = parent_tidptr;
+ register void *__newtls __asm__ ("r6") = newtls;
+ register int *__ctidptr __asm__ ("r5") = child_tidptr;
+ __asm__ __volatile__ (
+ #ifndef __s390x__
+ /* arg already in r0 */
+ "ltr %4, %4\n\t" /* check fn, which is already in r1 */
+ "jz 1f\n\t" /* NULL function pointer, return -EINVAL */
+ "ltr %5, %5\n\t" /* check child_stack, which is already in r2 */
+ "jz 1f\n\t" /* NULL stack pointer, return -EINVAL */
+ /* flags already in r3 */
+ /* parent_tidptr already in r4 */
+ /* child_tidptr already in r5 */
+ /* newtls already in r6 */
+ "svc %2\n\t" /* invoke clone syscall */
+ "ltr %0,%%r2\n\t" /* load return code into __ret and test */
+ "jnz 1f\n\t" /* return to parent if non-zero */
+ /* start child thread */
+ "lr %%r2, %7\n\t" /* set first parameter to void *arg */
+ "ahi %%r15, -96\n\t" /* make room on the stack for the save area */
+ "xc 0(4,%%r15), 0(%%r15)\n\t"
+ "basr %%r14, %4\n\t" /* jump to fn */
+ "svc %3\n" /* invoke exit syscall */
+ "1:\n"
+ #else
+ /* arg already in r0 */
+ "ltgr %4, %4\n\t" /* check fn, which is already in r1 */
+ "jz 1f\n\t" /* NULL function pointer, return -EINVAL */
+ "ltgr %5, %5\n\t" /* check child_stack, which is already in r2 */
+ "jz 1f\n\t" /* NULL stack pointer, return -EINVAL */
+ /* flags already in r3 */
+ /* parent_tidptr already in r4 */
+ /* child_tidptr already in r5 */
+ /* newtls already in r6 */
+ "svc %2\n\t" /* invoke clone syscall */
+ "ltgr %0, %%r2\n\t" /* load return code into __ret and test */
+ "jnz 1f\n\t" /* return to parent if non-zero */
+ /* start child thread */
+ "lgr %%r2, %7\n\t" /* set first parameter to void *arg */
+ "aghi %%r15, -160\n\t" /* make room on the stack for the save area */
+ "xc 0(8,%%r15), 0(%%r15)\n\t"
+ "basr %%r14, %4\n\t" /* jump to fn */
+ "svc %3\n" /* invoke exit syscall */
+ "1:\n"
+ #endif
+ : "=r" (__ret)
+ : "0" (-EINVAL), "i" (__NR_clone), "i" (__NR_exit),
+ "d" (__fn), "d" (__cstack), "d" (__flags), "d" (__arg),
+ "d" (__ptidptr), "d" (__newtls), "d" (__ctidptr)
+ : "cc", "r14", "memory"
+ );
+ }
+ LSS_RETURN(int, __ret);
+ }
+ #elif defined(__riscv)
+ #undef LSS_REG
+ #define LSS_REG(r,a) register long __a##r __asm__("a"#r) = \
+ (long)(a)
+
+ #undef LSS_BODY
+ #define LSS_BODY(type, name, args...) \
+ register long __a7 __asm__("a7") = __NR_##name; \
+ long __res; \
+ __asm__ __volatile__ ( \
+ "scall\n\t" \
+ : "+r" (__a0) \
+ : "r" (__a7), ##args \
+ : "memory"); \
+ __res = __a0; \
+ LSS_RETURN(type, __res)
+ #undef _syscall0
+ #define _syscall0(type,name) \
+ type LSS_NAME(name)() { \
+ register long __a7 __asm__("a7") = __NR_##name; \
+ register long __a0 __asm__("a0"); \
+ long __res; \
+ __asm__ __volatile__ ( \
+ "scall\n\t" \
+ : "=r" (__a0) \
+ : "r" (__a7) \
+ : "memory"); \
+ __res = __a0; \
+ LSS_RETURN(type, __res); \
+ }
+ #undef _syscall1
+ #define _syscall1(type, name, type1, arg1) \
+ type LSS_NAME(name)(type1 arg1) { \
+ /* There is no need for using a volatile temp. */ \
+ LSS_REG(0, arg1); \
+ LSS_BODY(type, name); \
+ }
+ #undef _syscall2
+ #define _syscall2(type, name, type1, arg1, type2, arg2) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2) { \
+ LSS_REG(0, arg1); \
+ LSS_REG(1, arg2); \
+ LSS_BODY(type, name, "r"(__a1)); \
+ }
+ #undef _syscall3
+ #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \
+ LSS_REG(0, arg1); \
+ LSS_REG(1, arg2); \
+ LSS_REG(2, arg3); \
+ LSS_BODY(type, name, "r"(__a1), "r"(__a2)); \
+ }
+ #undef _syscall4
+ #define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
+ LSS_REG(0, arg1); \
+ LSS_REG(1, arg2); \
+ LSS_REG(2, arg3); \
+ LSS_REG(3, arg4); \
+ LSS_BODY(type, name, "r"(__a1), "r"(__a2), "r"(__a3)); \
+ }
+ #undef _syscall5
+ #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+ type5,arg5) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+ type5 arg5) { \
+ LSS_REG(0, arg1); \
+ LSS_REG(1, arg2); \
+ LSS_REG(2, arg3); \
+ LSS_REG(3, arg4); \
+ LSS_REG(4, arg5); \
+ LSS_BODY(type, name, "r"(__a1), "r"(__a2), "r"(__a3), "r"(__a4)); \
+ }
+ #undef _syscall6
+ #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+ type5,arg5,type6,arg6) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+ type5 arg5, type6 arg6) { \
+ LSS_REG(0, arg1); \
+ LSS_REG(1, arg2); \
+ LSS_REG(2, arg3); \
+ LSS_REG(3, arg4); \
+ LSS_REG(4, arg5); \
+ LSS_REG(5, arg6); \
+ LSS_BODY(type, name, "r"(__a1), "r"(__a2), "r"(__a3), "r"(__a4), \
+ "r"(__a5)); \
+ }
#endif
#define __NR__exit __NR_exit
#define __NR__gettid __NR_gettid
#define __NR__mremap __NR_mremap
LSS_INLINE _syscall1(int, close, int, f)
LSS_INLINE _syscall1(int, _exit, int, e)
+#if defined(__aarch64__) && defined (__ILP32__)
+ /* aarch64_ilp32 uses fcntl64 for sys_fcntl() */
+ LSS_INLINE _syscall3_long(int, fcntl, fcntl64, int, f,
+ int, c, long, a)
+#else
LSS_INLINE _syscall3(int, fcntl, int, f,
int, c, long, a)
+#endif
+#if defined(__aarch64__) && defined (__ILP32__)
+ /* aarch64_ilp32 uses fstat64 for sys_fstat() */
+ LSS_INLINE _syscall2_long(int, fstat, fstat64, int, f,
+ struct kernel_stat*, b)
+#else
LSS_INLINE _syscall2(int, fstat, int, f,
struct kernel_stat*, b)
+#endif
LSS_INLINE _syscall6(int, futex, int*, a,
int, o, int, v,
struct kernel_timespec*, t,
@@ -2120,6 +2613,10 @@
_LSS_BODY(3, off_t, lseek, off_t, LSS_SYSCALL_ARG(f), (uint64_t)(o),
LSS_SYSCALL_ARG(w));
}
+ #elif defined(__aarch64__) && defined (__ILP32__)
+ /* aarch64_ilp32 uses llseek for sys_lseek() */
+ LSS_INLINE _syscall3_long(off_t, lseek, llseek, int, f,
+ off_t, o, int, w)
#else
LSS_INLINE _syscall3(off_t, lseek, int, f,
off_t, o, int, w)
@@ -2165,18 +2662,11 @@
LSS_INLINE _syscall3(int, socket, int, d,
int, t, int, p)
#endif
- #if defined(__x86_64__)
- /* Need to make sure __off64_t isn't truncated to 32-bits under x32. */
- LSS_INLINE void* LSS_NAME(mmap)(void *s, size_t l, int p, int f, int d,
- __off64_t o) {
- LSS_BODY(6, void*, mmap, LSS_SYSCALL_ARG(s), LSS_SYSCALL_ARG(l),
- LSS_SYSCALL_ARG(p), LSS_SYSCALL_ARG(f),
- LSS_SYSCALL_ARG(d), (uint64_t)(o));
- }
-
+ #if defined(__x86_64__) || defined(__s390x__)
LSS_INLINE int LSS_NAME(sigaction)(int signum,
const struct kernel_sigaction *act,
struct kernel_sigaction *oldact) {
+ #if defined(__x86_64__)
/* On x86_64, the kernel requires us to always set our own
* SA_RESTORER in order to be able to return from a signal handler.
* This function must have a "magic" signature that the "gdb"
@@ -2188,10 +2678,10 @@
a.sa_restorer = LSS_NAME(restore_rt)();
return LSS_NAME(rt_sigaction)(signum, &a, oldact,
(KERNEL_NSIG+7)/8);
- } else {
+ } else
+ #endif
return LSS_NAME(rt_sigaction)(signum, act, oldact,
(KERNEL_NSIG+7)/8);
- }
}
LSS_INLINE int LSS_NAME(sigprocmask)(int how,
@@ -2201,11 +2691,8 @@
}
#endif
#if (defined(__aarch64__)) || \
- (defined(__mips__) && (_MIPS_ISA == _MIPS_ISA_MIPS64))
- LSS_INLINE _syscall6(void*, mmap, void*, s,
- size_t, l, int, p,
- int, f, int, d,
- __off64_t, o)
+ (defined(__mips__) \
+ && (_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32))
LSS_INLINE int LSS_NAME(sigaction)(int signum,
const struct kernel_sigaction *act,
struct kernel_sigaction *oldact) {
@@ -2272,26 +2759,30 @@
}
}
- #if defined(__i386__) || \
- defined(__arm__) || \
- (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || defined(__PPC__)
+ #if defined(__i386__) || \
+ defined(__arm__) || \
+ (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || \
+ defined(__PPC__) || \
+ (defined(__s390__) && !defined(__s390x__))
#define __NR__sigaction __NR_sigaction
#define __NR__sigprocmask __NR_sigprocmask
LSS_INLINE _syscall2(int, fstat64, int, f,
struct kernel_stat64 *, b)
LSS_INLINE _syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
loff_t *, res, uint, wh)
-#ifdef __PPC64__
- LSS_INLINE _syscall6(void*, mmap, void*, s,
- size_t, l, int, p,
- int, f, int, d,
- off_t, o)
-#else
- #ifndef __ARM_EABI__
- /* Not available on ARM EABI Linux. */
- LSS_INLINE _syscall1(void*, mmap, void*, a)
- #endif
- LSS_INLINE _syscall6(void*, mmap2, void*, s,
+#if defined(__s390__) && !defined(__s390x__)
+ /* On s390, mmap2() arguments are passed in memory. */
+ LSS_INLINE void* LSS_NAME(_mmap2)(void *s, size_t l, int p, int f, int d,
+ off_t o) {
+ unsigned long buf[6] = { (unsigned long) s, (unsigned long) l,
+ (unsigned long) p, (unsigned long) f,
+ (unsigned long) d, (unsigned long) o };
+ LSS_REG(2, buf);
+ LSS_BODY(void*, mmap2, "0"(__r2));
+ }
+#elif !defined(__PPC64__)
+ #define __NR__mmap2 __NR_mmap2
+ LSS_INLINE _syscall6(void*, _mmap2, void*, s,
size_t, l, int, p,
int, f, int, d,
off_t, o)
@@ -2384,16 +2875,58 @@
return rc;
}
#endif
+ #if defined(__i386__) || \
+ defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) || \
+ (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || \
+ (defined(__PPC__) && !defined(__PPC64__)) || \
+ (defined(__s390__) && !defined(__s390x__))
+ /* On these architectures, implement mmap() with mmap2(). */
+ LSS_INLINE void* LSS_NAME(mmap)(void *s, size_t l, int p, int f, int d,
+ int64_t o) {
+ if (o % 4096) {
+ LSS_ERRNO = EINVAL;
+ return (void *) -1;
+ }
+ return LSS_NAME(_mmap2)(s, l, p, f, d, (o / 4096));
+ }
+ #elif defined(__s390x__)
+ /* On s390x, mmap() arguments are passed in memory. */
+ LSS_INLINE void* LSS_NAME(mmap)(void *s, size_t l, int p, int f, int d,
+ int64_t o) {
+ unsigned long buf[6] = { (unsigned long) s, (unsigned long) l,
+ (unsigned long) p, (unsigned long) f,
+ (unsigned long) d, (unsigned long) o };
+ LSS_REG(2, buf);
+ LSS_BODY(void*, mmap, "0"(__r2));
+ }
+ #elif defined(__x86_64__)
+ /* Need to make sure __off64_t isn't truncated to 32-bits under x32. */
+ LSS_INLINE void* LSS_NAME(mmap)(void *s, size_t l, int p, int f, int d,
+ int64_t o) {
+ LSS_BODY(6, void*, mmap, LSS_SYSCALL_ARG(s), LSS_SYSCALL_ARG(l),
+ LSS_SYSCALL_ARG(p), LSS_SYSCALL_ARG(f),
+ LSS_SYSCALL_ARG(d), (uint64_t)(o));
+ }
+ #elif defined(__aarch64__) && defined (__ILP32__)
+ /* aarch64_ilp32 uses mmap2 for sys_mmap() */
+ LSS_INLINE _syscall6_long(void*, mmap, mmap2, void*, addr, size_t, length,
+ int, prot, int, flags, int, fd, int64_t, offset)
+ #else
+ /* Remaining 64-bit architectures. */
+ LSS_INLINE _syscall6(void*, mmap, void*, addr, size_t, length, int, prot,
+ int, flags, int, fd, int64_t, offset)
+ #endif
#if defined(__i386__) || \
defined(__PPC__) || \
(defined(__arm__) && !defined(__ARM_EABI__)) || \
- (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32)
+ (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || \
+ defined(__s390__)
/* See sys_socketcall in net/socket.c in kernel source.
* It de-multiplexes on its first arg and unpacks the arglist
* array in its second arg.
*/
- LSS_INLINE _syscall2(long, socketcall, int, c, unsigned long*, a)
+ LSS_INLINE _syscall2(int, socketcall, int, c, unsigned long*, a)
LSS_INLINE int LSS_NAME(socket)(int domain, int type, int protocol) {
unsigned long args[3] = {
diff --git a/src/base/linuxthreads.cc b/src/base/linuxthreads.cc
index 891e70c..1e7f137 100644
--- a/src/base/linuxthreads.cc
+++ b/src/base/linuxthreads.cc
@@ -333,7 +333,7 @@
sa.sa_flags = SA_ONSTACK|SA_SIGINFO|SA_RESETHAND;
sys_sigaction(sync_signals[sig], &sa, (struct kernel_sigaction *)NULL);
}
-
+
/* Read process directories in /proc/... */
for (;;) {
/* Some kernels know about threads, and hide them in "/proc"
@@ -349,7 +349,7 @@
}
if (sys_fstat(proc, &proc_sb) < 0)
goto failure;
-
+
/* Since we are suspending threads, we cannot call any libc
* functions that might acquire locks. Most notably, we cannot
* call malloc(). So, we have to allocate memory on the stack,
@@ -363,7 +363,7 @@
*/
if (max_threads < proc_sb.st_nlink + 100)
max_threads = proc_sb.st_nlink + 100;
-
+
/* scope */ {
pid_t pids[max_threads];
int added_entries = 0;
@@ -395,11 +395,11 @@
if (entry->d_ino != 0) {
const char *ptr = entry->d_name;
pid_t pid;
-
+
/* Some kernels hide threads by preceding the pid with a '.' */
if (*ptr == '.')
ptr++;
-
+
/* If the directory is not numeric, it cannot be a
* process/thread
*/
@@ -413,7 +413,7 @@
char fname[entry->d_reclen + 48];
strcat(strcat(strcpy(fname, "/proc/"),
entry->d_name), marker_path);
-
+
/* Check if the marker is identical to the one we created */
if (sys_stat(fname, &tmp_sb) >= 0 &&
marker_sb.st_ino == tmp_sb.st_ino) {
@@ -429,7 +429,7 @@
goto next_entry;
}
}
-
+
/* Check whether data structure needs growing */
if (num_threads >= max_threads) {
/* Back to square one, this time with more memory */
diff --git a/src/base/linuxthreads.h b/src/base/linuxthreads.h
index 16bc8c6..a087628 100644
--- a/src/base/linuxthreads.h
+++ b/src/base/linuxthreads.h
@@ -1,3 +1,4 @@
+// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
/* Copyright (c) 2005-2007, Google Inc.
* All rights reserved.
*
@@ -37,11 +38,12 @@
/* Include thread_lister.h to get the interface that we implement for linux.
*/
-/* We currently only support x86-32 and x86-64 on Linux. Porting to other
+/* We currently only support certain platforms on Linux. Porting to other
* related platforms should not be difficult.
*/
-#if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) || \
- defined(__mips__) || defined(__PPC__) || defined(__aarch64__)) && defined(__linux)
+#if (defined(__i386__) || defined(__x86_64__) || defined(__arm__) || \
+ defined(__mips__) || defined(__PPC__) || defined(__aarch64__) || \
+ defined(__s390__)) && defined(__linux)
/* Define the THREADS symbol to make sure that there is exactly one core dumper
* built into the library.
diff --git a/src/base/logging.cc b/src/base/logging.cc
index 761c2fd..52d9bd3 100644
--- a/src/base/logging.cc
+++ b/src/base/logging.cc
@@ -1,11 +1,11 @@
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
// 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
@@ -15,7 +15,7 @@
// * 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
diff --git a/src/base/logging.h b/src/base/logging.h
index a1afe4d..94b9138 100644
--- a/src/base/logging.h
+++ b/src/base/logging.h
@@ -1,11 +1,11 @@
// -*- 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
@@ -15,7 +15,7 @@
// * 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
diff --git a/src/base/low_level_alloc.cc b/src/base/low_level_alloc.cc
index 4d2ae8d..db91155 100644
--- a/src/base/low_level_alloc.cc
+++ b/src/base/low_level_alloc.cc
@@ -1,11 +1,11 @@
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
/* Copyright (c) 2006, 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
@@ -15,7 +15,7 @@
* * 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
@@ -57,6 +57,9 @@
// A first-fit allocator with amortized logarithmic free() time.
+LowLevelAlloc::PagesAllocator::~PagesAllocator() {
+}
+
// ---------------------------------------------------------------------------
static const int kMaxLevel = 30;
@@ -104,8 +107,7 @@
// Return a random integer n: p(n)=1/(2**n) if 1 <= n; p(n)=0 if n < 1.
static int Random() {
- static int32 r = 1; // no locking---it's not critical
- ANNOTATE_BENIGN_RACE(&r, "benign race, not critical.");
+ static uint32 r = 1; // no locking---it's not critical
int result = 1;
while ((((r = r*1103515245 + 12345) >> 30) & 1) == 0) {
result++;
@@ -196,6 +198,7 @@
// (init under mu, then ro)
size_t min_size; // smallest allocation block size
// (init under mu, then ro)
+ PagesAllocator *allocator;
};
// The default arena, which is used when 0 is passed instead of an Arena
@@ -208,6 +211,17 @@
static struct LowLevelAlloc::Arena unhooked_arena;
static struct LowLevelAlloc::Arena unhooked_async_sig_safe_arena;
+namespace {
+
+ class DefaultPagesAllocator : public LowLevelAlloc::PagesAllocator {
+ public:
+ virtual ~DefaultPagesAllocator() {};
+ virtual void *MapPages(int32 flags, size_t size);
+ virtual void UnMapPages(int32 flags, void *addr, size_t size);
+ };
+
+}
+
// magic numbers to identify allocated and unallocated blocks
static const intptr_t kMagicAllocated = 0x4c833e95;
static const intptr_t kMagicUnallocated = ~kMagicAllocated;
@@ -234,7 +248,7 @@
this->arena_->mu.Lock();
}
~ArenaLock() { RAW_CHECK(this->left_, "haven't left Arena region"); }
- void Leave() /*UNLOCK_FUNCTION()*/ {
+ void Leave() UNLOCK_FUNCTION() {
this->arena_->mu.Unlock();
#if 0
if (this->mask_valid_) {
@@ -289,12 +303,20 @@
arena->flags = 0; // other arenas' flags may be overridden by client,
// but unhooked_arena will have 0 in 'flags'.
}
+ arena->allocator = LowLevelAlloc::GetDefaultPagesAllocator();
}
}
// L < meta_data_arena->mu
LowLevelAlloc::Arena *LowLevelAlloc::NewArena(int32 flags,
Arena *meta_data_arena) {
+ return NewArenaWithCustomAlloc(flags, meta_data_arena, NULL);
+}
+
+// L < meta_data_arena->mu
+LowLevelAlloc::Arena *LowLevelAlloc::NewArenaWithCustomAlloc(int32 flags,
+ Arena *meta_data_arena,
+ PagesAllocator *allocator) {
RAW_CHECK(meta_data_arena != 0, "must pass a valid arena");
if (meta_data_arena == &default_arena) {
if ((flags & LowLevelAlloc::kAsyncSignalSafe) != 0) {
@@ -308,6 +330,9 @@
new (AllocWithArena(sizeof (*result), meta_data_arena)) Arena(0);
ArenaInit(result);
result->flags = flags;
+ if (allocator) {
+ result->allocator = allocator;
+ }
return result;
}
@@ -458,15 +483,7 @@
// mmap generous 64K chunks to decrease
// the chances/impact of fragmentation:
size_t new_pages_size = RoundUp(req_rnd, arena->pagesize * 16);
- void *new_pages;
- if ((arena->flags & LowLevelAlloc::kAsyncSignalSafe) != 0) {
- new_pages = MallocHook::UnhookedMMap(0, new_pages_size,
- PROT_WRITE|PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
- } else {
- new_pages = mmap(0, new_pages_size,
- PROT_WRITE|PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
- }
- RAW_CHECK(new_pages != MAP_FAILED, "mmap error");
+ void *new_pages = arena->allocator->MapPages(arena->flags, new_pages_size);
arena->mu.Lock();
s = reinterpret_cast<AllocList *>(new_pages);
s->header.size = new_pages_size;
@@ -493,7 +510,6 @@
section.Leave();
result = &s->levels;
}
- ANNOTATE_NEW_MEMORY(result, request);
return result;
}
@@ -521,3 +537,44 @@
LowLevelAlloc::Arena *LowLevelAlloc::DefaultArena() {
return &default_arena;
}
+
+static DefaultPagesAllocator *default_pages_allocator;
+static union {
+ char chars[sizeof(DefaultPagesAllocator)];
+ void *ptr;
+} debug_pages_allocator_space;
+
+LowLevelAlloc::PagesAllocator *LowLevelAlloc::GetDefaultPagesAllocator(void) {
+ if (default_pages_allocator) {
+ return default_pages_allocator;
+ }
+ default_pages_allocator = new (debug_pages_allocator_space.chars) DefaultPagesAllocator();
+ return default_pages_allocator;
+}
+
+void *DefaultPagesAllocator::MapPages(int32 flags, size_t size) {
+ void *new_pages;
+ if ((flags & LowLevelAlloc::kAsyncSignalSafe) != 0) {
+ new_pages = MallocHook::UnhookedMMap(0, size,
+ PROT_WRITE|PROT_READ,
+ MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+ } else {
+ new_pages = mmap(0, size,
+ PROT_WRITE|PROT_READ,
+ MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+ }
+ RAW_CHECK(new_pages != MAP_FAILED, "mmap error");
+
+ return new_pages;
+}
+
+void DefaultPagesAllocator::UnMapPages(int32 flags, void *region, size_t size) {
+ int munmap_result;
+ if ((flags & LowLevelAlloc::kAsyncSignalSafe) == 0) {
+ munmap_result = munmap(region, size);
+ } else {
+ munmap_result = MallocHook::UnhookedMUnmap(region, size);
+ }
+ RAW_CHECK(munmap_result == 0,
+ "LowLevelAlloc::DeleteArena: munmap failed address");
+}
diff --git a/src/base/low_level_alloc.h b/src/base/low_level_alloc.h
index 4081ff8..406bfff 100644
--- a/src/base/low_level_alloc.h
+++ b/src/base/low_level_alloc.h
@@ -1,11 +1,11 @@
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
/* Copyright (c) 2006, 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
@@ -15,7 +15,7 @@
* * 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
@@ -43,6 +43,15 @@
class LowLevelAlloc {
public:
+ class PagesAllocator {
+ public:
+ virtual ~PagesAllocator();
+ virtual void *MapPages(int32 flags, size_t size) = 0;
+ virtual void UnMapPages(int32 flags, void *addr, size_t size) = 0;
+ };
+
+ static PagesAllocator *GetDefaultPagesAllocator(void);
+
struct Arena; // an arena from which memory may be allocated
// Returns a pointer to a block of at least "request" bytes
@@ -90,6 +99,10 @@
};
static Arena *NewArena(int32 flags, Arena *meta_data_arena);
+ // note: pages allocator will never be destroyed and allocated pages will never be freed
+ // When allocator is NULL, it's same as NewArena
+ static Arena *NewArenaWithCustomAlloc(int32 flags, Arena *meta_data_arena, PagesAllocator *allocator);
+
// Destroys an arena allocated by NewArena and returns true,
// provided no allocated blocks remain in the arena.
// If allocated blocks remain in the arena, does nothing and
diff --git a/src/base/simple_mutex.h b/src/base/simple_mutex.h
index a1886e4..5913b9e 100644
--- a/src/base/simple_mutex.h
+++ b/src/base/simple_mutex.h
@@ -1,11 +1,11 @@
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
// 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
@@ -15,7 +15,7 @@
// * 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
@@ -27,7 +27,7 @@
// 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.
//
diff --git a/src/base/spinlock.cc b/src/base/spinlock.cc
index 2021fec..d2a9e1c 100644
--- a/src/base/spinlock.cc
+++ b/src/base/spinlock.cc
@@ -1,11 +1,11 @@
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
/* Copyright (c) 2006, 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
@@ -15,7 +15,7 @@
* * 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
@@ -34,21 +34,14 @@
#include <config.h>
#include "base/spinlock.h"
-#include "base/synchronization_profiling.h"
#include "base/spinlock_internal.h"
-#include "base/cycleclock.h"
-#include "base/sysinfo.h" /* for NumCPUs() */
+#include "base/sysinfo.h" /* for GetSystemCPUsCount() */
// NOTE on the Lock-state values:
//
-// kSpinLockFree represents the unlocked state
-// kSpinLockHeld represents the locked state with no waiters
-//
-// Values greater than kSpinLockHeld represent the locked state with waiters,
-// where the value is the time the current lock holder had to
-// wait before obtaining the lock. The kSpinLockSleeper state is a special
-// "locked with waiters" state that indicates that a sleeper needs to
-// be woken, but the thread that just released the lock didn't wait.
+// kSpinLockFree represents the unlocked state
+// kSpinLockHeld represents the locked state with no waiters
+// kSpinLockSleeper represents the locked state with waiters
static int adaptive_spin_count = 0;
@@ -60,7 +53,7 @@
SpinLock_InitHelper() {
// On multi-cpu machines, spin for longer before yielding
// the processor or sleeping. Reduces idle time significantly.
- if (NumCPUs() > 1) {
+ if (GetSystemCPUsCount() > 1) {
adaptive_spin_count = 1000;
}
}
@@ -71,35 +64,28 @@
// but nothing lock-intensive should be going on at that time.
static SpinLock_InitHelper init_helper;
+inline void SpinlockPause(void) {
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+ __asm__ __volatile__("rep; nop" : : );
+#endif
+}
+
} // unnamed namespace
-// Monitor the lock to see if its value changes within some time period
-// (adaptive_spin_count loop iterations). A timestamp indicating
-// when the thread initially started waiting for the lock is passed in via
-// the initial_wait_timestamp value. The total wait time in cycles for the
-// lock is returned in the wait_cycles parameter. The last value read
+// Monitor the lock to see if its value changes within some time
+// period (adaptive_spin_count loop iterations). The last value read
// from the lock is returned from the method.
-Atomic32 SpinLock::SpinLoop(int64 initial_wait_timestamp,
- Atomic32* wait_cycles) {
+Atomic32 SpinLock::SpinLoop() {
int c = adaptive_spin_count;
while (base::subtle::NoBarrier_Load(&lockword_) != kSpinLockFree && --c > 0) {
+ SpinlockPause();
}
- Atomic32 spin_loop_wait_cycles = CalculateWaitCycles(initial_wait_timestamp);
- Atomic32 lock_value =
- base::subtle::Acquire_CompareAndSwap(&lockword_, kSpinLockFree,
- spin_loop_wait_cycles);
- *wait_cycles = spin_loop_wait_cycles;
- return lock_value;
+ return base::subtle::Acquire_CompareAndSwap(&lockword_, kSpinLockFree,
+ kSpinLockSleeper);
}
void SpinLock::SlowLock() {
- // The lock was not obtained initially, so this thread needs to wait for
- // it. Record the current timestamp in the local variable wait_start_time
- // so the total wait time can be stored in the lockword once this thread
- // obtains the lock.
- int64 wait_start_time = CycleClock::Now();
- Atomic32 wait_cycles;
- Atomic32 lock_value = SpinLoop(wait_start_time, &wait_cycles);
+ Atomic32 lock_value = SpinLoop();
int lock_wait_call_count = 0;
while (lock_value != kSpinLockFree) {
@@ -114,7 +100,7 @@
kSpinLockSleeper);
if (lock_value == kSpinLockHeld) {
// Successfully transitioned to kSpinLockSleeper. Pass
- // kSpinLockSleeper to the SpinLockWait routine to properly indicate
+ // kSpinLockSleeper to the SpinLockDelay routine to properly indicate
// the last lock_value observed.
lock_value = kSpinLockSleeper;
} else if (lock_value == kSpinLockFree) {
@@ -123,7 +109,7 @@
// this thread obtains the lock.
lock_value = base::subtle::Acquire_CompareAndSwap(&lockword_,
kSpinLockFree,
- wait_cycles);
+ kSpinLockSleeper);
continue; // skip the delay at the end of the loop
}
}
@@ -133,51 +119,11 @@
++lock_wait_call_count);
// Spin again after returning from the wait routine to give this thread
// some chance of obtaining the lock.
- lock_value = SpinLoop(wait_start_time, &wait_cycles);
+ lock_value = SpinLoop();
}
}
-// The wait time for contentionz lock profiling must fit into 32 bits.
-// However, the lower 32-bits of the cycle counter wrap around too quickly
-// with high frequency processors, so a right-shift by 7 is performed to
-// quickly divide the cycles by 128. Using these 32 bits, reduces the
-// granularity of time measurement to 128 cycles, and loses track
-// of wait time for waits greater than 109 seconds on a 5 GHz machine
-// [(2^32 cycles/5 Ghz)*128 = 109.95 seconds]. Waits this long should be
-// very rare and the reduced granularity should not be an issue given
-// processors in the Google fleet operate at a minimum of one billion
-// cycles/sec.
-enum { PROFILE_TIMESTAMP_SHIFT = 7 };
-
-void SpinLock::SlowUnlock(uint64 wait_cycles) {
- base::internal::SpinLockWake(&lockword_, false); // wake waiter if necessary
-
- // Collect contentionz profile info, expanding the wait_cycles back out to
- // the full value. If wait_cycles is <= kSpinLockSleeper, then no wait
- // was actually performed, so don't record the wait time. Note, that the
- // CalculateWaitCycles method adds in kSpinLockSleeper cycles
- // unconditionally to guarantee the wait time is not kSpinLockFree or
- // kSpinLockHeld. The adding in of these small number of cycles may
- // overestimate the contention by a slight amount 50% of the time. However,
- // if this code tried to correct for that addition by subtracting out the
- // kSpinLockSleeper amount that would underestimate the contention slightly
- // 50% of the time. Both ways get the wrong answer, so the code
- // overestimates to be more conservative. Overestimating also makes the code
- // a little simpler.
- //
- if (wait_cycles > kSpinLockSleeper) {
- base::SubmitSpinLockProfileData(this,
- wait_cycles << PROFILE_TIMESTAMP_SHIFT);
- }
-}
-
-inline int32 SpinLock::CalculateWaitCycles(int64 wait_start_time) {
- int32 wait_cycles = ((CycleClock::Now() - wait_start_time) >>
- PROFILE_TIMESTAMP_SHIFT);
- // The number of cycles waiting for the lock is used as both the
- // wait_cycles and lock value, so it can't be kSpinLockFree or
- // kSpinLockHeld. Make sure the value returned is at least
- // kSpinLockSleeper.
- wait_cycles |= kSpinLockSleeper;
- return wait_cycles;
+void SpinLock::SlowUnlock() {
+ // wake waiter if necessary
+ base::internal::SpinLockWake(&lockword_, false);
}
diff --git a/src/base/spinlock.h b/src/base/spinlock.h
index 033a75e..118f541 100644
--- a/src/base/spinlock.h
+++ b/src/base/spinlock.h
@@ -1,11 +1,11 @@
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
/* Copyright (c) 2006, 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
@@ -15,7 +15,7 @@
* * 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
@@ -63,14 +63,11 @@
}
// Acquire this SpinLock.
- // TODO(csilvers): uncomment the annotation when we figure out how to
- // support this macro with 0 args (see thread_annotations.h)
- inline void Lock() /*EXCLUSIVE_LOCK_FUNCTION()*/ {
+ inline void Lock() EXCLUSIVE_LOCK_FUNCTION() {
if (base::subtle::Acquire_CompareAndSwap(&lockword_, kSpinLockFree,
kSpinLockHeld) != kSpinLockFree) {
SlowLock();
}
- ANNOTATE_RWLOCK_ACQUIRED(this, 1);
}
// Try to acquire this SpinLock without blocking and return true if the
@@ -81,24 +78,16 @@
bool res =
(base::subtle::Acquire_CompareAndSwap(&lockword_, kSpinLockFree,
kSpinLockHeld) == kSpinLockFree);
- if (res) {
- ANNOTATE_RWLOCK_ACQUIRED(this, 1);
- }
return res;
}
// Release this SpinLock, which must be held by the calling thread.
- // TODO(csilvers): uncomment the annotation when we figure out how to
- // support this macro with 0 args (see thread_annotations.h)
- inline void Unlock() /*UNLOCK_FUNCTION()*/ {
- ANNOTATE_RWLOCK_RELEASED(this, 1);
- uint64 wait_cycles = static_cast<uint64>(
+ inline void Unlock() UNLOCK_FUNCTION() {
+ uint64 prev_value = static_cast<uint64>(
base::subtle::Release_AtomicExchange(&lockword_, kSpinLockFree));
- if (wait_cycles != kSpinLockHeld) {
- // Collect contentionz profile info, and speed the wakeup of any waiter.
- // The wait_cycles value indicates how long this thread spent waiting
- // for the lock.
- SlowUnlock(wait_cycles);
+ if (prev_value != kSpinLockHeld) {
+ // Speed the wakeup of any waiter.
+ SlowUnlock();
}
}
@@ -118,9 +107,8 @@
volatile Atomic32 lockword_;
void SlowLock();
- void SlowUnlock(uint64 wait_cycles);
- Atomic32 SpinLoop(int64 initial_wait_timestamp, Atomic32* wait_cycles);
- inline int32 CalculateWaitCycles(int64 wait_start_time);
+ void SlowUnlock();
+ Atomic32 SpinLoop();
DISALLOW_COPY_AND_ASSIGN(SpinLock);
};
@@ -135,9 +123,7 @@
: lock_(l) {
l->Lock();
}
- // TODO(csilvers): uncomment the annotation when we figure out how to
- // support this macro with 0 args (see thread_annotations.h)
- inline ~SpinLockHolder() /*UNLOCK_FUNCTION()*/ { lock_->Unlock(); }
+ inline ~SpinLockHolder() UNLOCK_FUNCTION() { lock_->Unlock(); }
};
// Catch bug where variable name is omitted, e.g. SpinLockHolder (&lock);
#define SpinLockHolder(x) COMPILE_ASSERT(0, spin_lock_decl_missing_var_name)
diff --git a/src/base/spinlock_internal.cc b/src/base/spinlock_internal.cc
index e090f9b..d962971 100644
--- a/src/base/spinlock_internal.cc
+++ b/src/base/spinlock_internal.cc
@@ -57,26 +57,6 @@
namespace base {
namespace internal {
-// See spinlock_internal.h for spec.
-int32 SpinLockWait(volatile Atomic32 *w, int n,
- const SpinLockWaitTransition trans[]) {
- int32 v;
- bool done = false;
- for (int loop = 0; !done; loop++) {
- v = base::subtle::Acquire_Load(w);
- int i;
- for (i = 0; i != n && v != trans[i].from; i++) {
- }
- if (i == n) {
- SpinLockDelay(w, v, loop); // no matching transition
- } else if (trans[i].to == v || // null transition
- base::subtle::Acquire_CompareAndSwap(w, v, trans[i].to) == v) {
- done = trans[i].done;
- }
- }
- return v;
-}
-
// Return a suggested delay in nanoseconds for iteration number "loop"
static int SuggestedDelayNS(int loop) {
// Weak pseudo-random number generator to get some spread between threads
diff --git a/src/base/spinlock_internal.h b/src/base/spinlock_internal.h
index 4d3c17f..aa47e67 100644
--- a/src/base/spinlock_internal.h
+++ b/src/base/spinlock_internal.h
@@ -43,20 +43,6 @@
namespace base {
namespace internal {
-// SpinLockWait() waits until it can perform one of several transitions from
-// "from" to "to". It returns when it performs a transition where done==true.
-struct SpinLockWaitTransition {
- int32 from;
- int32 to;
- bool done;
-};
-
-// Wait until *w can transition from trans[i].from to trans[i].to for some i
-// satisfying 0<=i<n && trans[i].done, atomically make the transition,
-// then return the old value of *w. Make any other atomic tranistions
-// where !trans[i].done, but continue waiting.
-int32 SpinLockWait(volatile Atomic32 *w, int n,
- const SpinLockWaitTransition trans[]);
void SpinLockWake(volatile Atomic32 *w, bool all);
void SpinLockDelay(volatile Atomic32 *w, int32 value, int loop);
diff --git a/src/base/spinlock_linux-inl.h b/src/base/spinlock_linux-inl.h
index aadf62a..ad48aae 100644
--- a/src/base/spinlock_linux-inl.h
+++ b/src/base/spinlock_linux-inl.h
@@ -1,11 +1,11 @@
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
/* Copyright (c) 2009, 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
@@ -15,7 +15,7 @@
* * 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
@@ -33,15 +33,19 @@
*/
#include <errno.h>
-#include <sched.h>
-#include <time.h>
#include <limits.h>
-#include "base/linux_syscall_support.h"
+#include <sched.h>
+#include <sys/syscall.h>
+#include <time.h>
+#include <unistd.h>
#define FUTEX_WAIT 0
#define FUTEX_WAKE 1
#define FUTEX_PRIVATE_FLAG 128
+// Note: Instead of making direct system calls that are inlined, we rely
+// on the syscall() function in glibc to do the right thing.
+
static bool have_futex;
static int futex_private_flag = FUTEX_PRIVATE_FLAG;
@@ -51,10 +55,10 @@
int x = 0;
// futexes are ints, so we can use them only when
// that's the same size as the lockword_ in SpinLock.
- have_futex = (sizeof (Atomic32) == sizeof (int) &&
- sys_futex(&x, FUTEX_WAKE, 1, NULL, NULL, 0) >= 0);
- if (have_futex &&
- sys_futex(&x, FUTEX_WAKE | futex_private_flag, 1, NULL, NULL, 0) < 0) {
+ have_futex = (sizeof(Atomic32) == sizeof(int) &&
+ syscall(__NR_futex, &x, FUTEX_WAKE, 1, NULL, NULL, 0) >= 0);
+ if (have_futex && syscall(__NR_futex, &x, FUTEX_WAKE | futex_private_flag,
+ 1, NULL, NULL, 0) < 0) {
futex_private_flag = 0;
}
}
@@ -78,10 +82,9 @@
}
if (have_futex) {
tm.tv_nsec *= 16; // increase the delay; we expect explicit wakeups
- sys_futex(reinterpret_cast<int *>(const_cast<Atomic32 *>(w)),
- FUTEX_WAIT | futex_private_flag,
- value, reinterpret_cast<struct kernel_timespec *>(&tm),
- NULL, 0);
+ syscall(__NR_futex, reinterpret_cast<int*>(const_cast<Atomic32*>(w)),
+ FUTEX_WAIT | futex_private_flag, value,
+ reinterpret_cast<struct kernel_timespec*>(&tm), NULL, 0);
} else {
nanosleep(&tm, NULL);
}
@@ -91,9 +94,8 @@
void SpinLockWake(volatile Atomic32 *w, bool all) {
if (have_futex) {
- sys_futex(reinterpret_cast<int *>(const_cast<Atomic32 *>(w)),
- FUTEX_WAKE | futex_private_flag, all? INT_MAX : 1,
- NULL, NULL, 0);
+ syscall(__NR_futex, reinterpret_cast<int*>(const_cast<Atomic32*>(w)),
+ FUTEX_WAKE | futex_private_flag, all ? INT_MAX : 1, NULL, NULL, 0);
}
}
diff --git a/src/base/spinlock_posix-inl.h b/src/base/spinlock_posix-inl.h
index e73a30f..f4d217b 100644
--- a/src/base/spinlock_posix-inl.h
+++ b/src/base/spinlock_posix-inl.h
@@ -1,11 +1,11 @@
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
/* Copyright (c) 2009, 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
@@ -15,7 +15,7 @@
* * 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
diff --git a/src/base/spinlock_win32-inl.h b/src/base/spinlock_win32-inl.h
index 956b965..05caa54 100644
--- a/src/base/spinlock_win32-inl.h
+++ b/src/base/spinlock_win32-inl.h
@@ -1,11 +1,11 @@
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
/* Copyright (c) 2009, 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
@@ -15,7 +15,7 @@
* * 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
diff --git a/src/base/stl_allocator.h b/src/base/stl_allocator.h
index 2345f46..94debe8 100644
--- a/src/base/stl_allocator.h
+++ b/src/base/stl_allocator.h
@@ -1,11 +1,11 @@
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
/* Copyright (c) 2006, 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
@@ -15,7 +15,7 @@
* * 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
diff --git a/src/base/synchronization_profiling.h b/src/base/synchronization_profiling.h
deleted file mode 100644
index b495034..0000000
--- a/src/base/synchronization_profiling.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2010, 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: Chris Ruemmler
- */
-
-#ifndef BASE_AUXILIARY_SYNCHRONIZATION_PROFILING_H_
-#define BASE_AUXILIARY_SYNCHRONIZATION_PROFILING_H_
-
-#include "base/basictypes.h"
-
-namespace base {
-
-// We can do contention-profiling of SpinLocks, but the code is in
-// mutex.cc, which is not always linked in with spinlock. Hence we
-// provide a weak definition, which are used if mutex.cc isn't linked in.
-
-// Submit the number of cycles the spinlock spent contending.
-ATTRIBUTE_WEAK extern void SubmitSpinLockProfileData(const void *, int64);
-extern void SubmitSpinLockProfileData(const void *contendedlock,
- int64 wait_cycles) {}
-}
-#endif // BASE_AUXILIARY_SYNCHRONIZATION_PROFILING_H_
diff --git a/src/base/sysinfo.cc b/src/base/sysinfo.cc
index cad751b..669efaf 100644
--- a/src/base/sysinfo.cc
+++ b/src/base/sysinfo.cc
@@ -1,11 +1,11 @@
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
// Copyright (c) 2006, 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
@@ -15,7 +15,7 @@
// * 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
@@ -60,7 +60,6 @@
#include "base/commandlineflags.h"
#include "base/dynamic_annotations.h" // for RunningOnValgrind
#include "base/logging.h"
-#include "base/cycleclock.h"
#ifdef PLATFORM_WINDOWS
#ifdef MODULEENTRY32
@@ -111,6 +110,40 @@
// Some non-trivial getenv-related functions.
// ----------------------------------------------------------------------
+// we reimplement memcmp and friends to avoid depending on any glibc
+// calls too early in the process lifetime. This allows us to use
+// GetenvBeforeMain from inside ifunc handler
+static int slow_memcmp(const void *_a, const void *_b, size_t n) {
+ const uint8_t *a = reinterpret_cast<const uint8_t *>(_a);
+ const uint8_t *b = reinterpret_cast<const uint8_t *>(_b);
+ while (n-- != 0) {
+ uint8_t ac = *a++;
+ uint8_t bc = *b++;
+ if (ac != bc) {
+ if (ac < bc) {
+ return -1;
+ }
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static const char *slow_memchr(const char *s, int c, size_t n) {
+ uint8_t ch = static_cast<uint8_t>(c);
+ while (n--) {
+ if (*s++ == ch) {
+ return s - 1;
+ }
+ }
+ return 0;
+}
+
+static size_t slow_strlen(const char *s) {
+ const char *s2 = slow_memchr(s, '\0', static_cast<size_t>(-1));
+ return s2 - s;
+}
+
// It's not safe to call getenv() in the malloc hooks, because they
// might be called extremely early, before libc is done setting up
// correctly. In particular, the thread library may not be done
@@ -120,15 +153,12 @@
// /proc/self/environ has a limit of how much data it exports (around
// 8K), so it's not an ideal solution.
const char* GetenvBeforeMain(const char* name) {
+ const int namelen = slow_strlen(name);
#if defined(HAVE___ENVIRON) // if we have it, it's declared in unistd.h
if (__environ) { // can exist but be NULL, if statically linked
- const int namelen = strlen(name);
for (char** p = __environ; *p; p++) {
- if (strlen(*p) < namelen) {
- continue;
- }
- if (!memcmp(*p, name, namelen) && (*p)[namelen] == '=') // it's a match
- return *p + namelen+1; // point after =
+ if (!slow_memcmp(*p, name, namelen) && (*p)[namelen] == '=')
+ return *p + namelen+1;
}
return NULL;
}
@@ -156,14 +186,14 @@
}
safeclose(fd);
}
- const int namelen = strlen(name);
const char* p = envbuf;
while (*p != '\0') { // will happen at the \0\0 that terminates the buffer
// proc file has the format NAME=value\0NAME=value\0NAME=value\0...
- const char* endp = (char*)memchr(p, '\0', sizeof(envbuf) - (p - envbuf));
+ const char* endp = (char*)slow_memchr(p, '\0',
+ sizeof(envbuf) - (p - envbuf));
if (endp == NULL) // this entry isn't NUL terminated
return NULL;
- else if (!memcmp(p, name, namelen) && p[namelen] == '=') // it's a match
+ else if (!slow_memcmp(p, name, namelen) && p[namelen] == '=') // it's a match
return p + namelen+1; // point after =
p = endp + 1;
}
@@ -212,327 +242,22 @@
return true;
}
-// ----------------------------------------------------------------------
-// CyclesPerSecond()
-// NumCPUs()
-// It's important this not call malloc! -- they may be called at
-// global-construct time, before we've set up all our proper malloc
-// hooks and such.
-// ----------------------------------------------------------------------
-
-static double cpuinfo_cycles_per_second = 1.0; // 0.0 might be dangerous
-static int cpuinfo_num_cpus = 1; // Conservative guess
-
-void SleepForMilliseconds(int milliseconds) {
-#ifdef PLATFORM_WINDOWS
- _sleep(milliseconds); // Windows's _sleep takes milliseconds argument
-#else
- // Sleep for a few milliseconds
- struct timespec sleep_time;
- sleep_time.tv_sec = milliseconds / 1000;
- sleep_time.tv_nsec = (milliseconds % 1000) * 1000000;
- while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR)
- ; // Ignore signals and wait for the full interval to elapse.
-#endif
-}
-
-// Helper function estimates cycles/sec by observing cycles elapsed during
-// sleep(). Using small sleep time decreases accuracy significantly.
-static int64 EstimateCyclesPerSecond(const int estimate_time_ms) {
- assert(estimate_time_ms > 0);
- if (estimate_time_ms <= 0)
- return 1;
- double multiplier = 1000.0 / (double)estimate_time_ms; // scale by this much
-
- const int64 start_ticks = CycleClock::Now();
- SleepForMilliseconds(estimate_time_ms);
- const int64 guess = int64(multiplier * (CycleClock::Now() - start_ticks));
- return guess;
-}
-
-// ReadIntFromFile is only called on linux and cygwin platforms.
-#if defined(__linux__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
-// Helper function for reading an int from a file. Returns true if successful
-// and the memory location pointed to by value is set to the value read.
-static bool ReadIntFromFile(const char *file, int *value) {
- bool ret = false;
- int fd = open(file, O_RDONLY);
- if (fd != -1) {
- char line[1024];
- char* err;
- memset(line, '\0', sizeof(line));
- read(fd, line, sizeof(line) - 1);
- const int temp_value = strtol(line, &err, 10);
- if (line[0] != '\0' && (*err == '\n' || *err == '\0')) {
- *value = temp_value;
- ret = true;
- }
- close(fd);
- }
- return ret;
-}
-#endif
-
-// WARNING: logging calls back to InitializeSystemInfo() so it must
-// not invoke any logging code. Also, InitializeSystemInfo() can be
-// called before main() -- in fact it *must* be since already_called
-// isn't protected -- before malloc hooks are properly set up, so
-// we make an effort not to call any routines which might allocate
-// memory.
-
-static void InitializeSystemInfo() {
- static bool already_called = false; // safe if we run before threads
- if (already_called) return;
- already_called = true;
-
- bool saw_mhz = false;
-
- if (RunningOnValgrind()) {
- // Valgrind may slow the progress of time artificially (--scale-time=N
- // option). We thus can't rely on CPU Mhz info stored in /sys or /proc
- // files. Thus, actually measure the cps.
- cpuinfo_cycles_per_second = EstimateCyclesPerSecond(100);
- saw_mhz = true;
- }
-
-#if defined(__linux__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
- char line[1024];
- char* err;
- int freq;
-
- // If the kernel is exporting the tsc frequency use that. There are issues
- // where cpuinfo_max_freq cannot be relied on because the BIOS may be
- // exporintg an invalid p-state (on x86) or p-states may be used to put the
- // processor in a new mode (turbo mode). Essentially, those frequencies
- // cannot always be relied upon. The same reasons apply to /proc/cpuinfo as
- // well.
- if (!saw_mhz &&
- ReadIntFromFile("/sys/devices/system/cpu/cpu0/tsc_freq_khz", &freq)) {
- // The value is in kHz (as the file name suggests). For example, on a
- // 2GHz warpstation, the file contains the value "2000000".
- cpuinfo_cycles_per_second = freq * 1000.0;
- saw_mhz = true;
- }
-
- // If CPU scaling is in effect, we want to use the *maximum* frequency,
- // not whatever CPU speed some random processor happens to be using now.
- if (!saw_mhz &&
- ReadIntFromFile("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq",
- &freq)) {
- // The value is in kHz. For example, on a 2GHz machine, the file
- // contains the value "2000000".
- cpuinfo_cycles_per_second = freq * 1000.0;
- saw_mhz = true;
- }
-
- // Read /proc/cpuinfo for other values, and if there is no cpuinfo_max_freq.
- const char* pname = "/proc/cpuinfo";
- int fd = open(pname, O_RDONLY);
- if (fd == -1) {
- perror(pname);
- if (!saw_mhz) {
- cpuinfo_cycles_per_second = EstimateCyclesPerSecond(1000);
- }
- return; // TODO: use generic tester instead?
- }
-
- double bogo_clock = 1.0;
- bool saw_bogo = false;
- int num_cpus = 0;
- line[0] = line[1] = '\0';
- int chars_read = 0;
- do { // we'll exit when the last read didn't read anything
- // Move the next line to the beginning of the buffer
- const int oldlinelen = strlen(line);
- if (sizeof(line) == oldlinelen + 1) // oldlinelen took up entire line
- line[0] = '\0';
- else // still other lines left to save
- memmove(line, line + oldlinelen+1, sizeof(line) - (oldlinelen+1));
- // Terminate the new line, reading more if we can't find the newline
- char* newline = strchr(line, '\n');
- if (newline == NULL) {
- const int linelen = strlen(line);
- const int bytes_to_read = sizeof(line)-1 - linelen;
- assert(bytes_to_read > 0); // because the memmove recovered >=1 bytes
- chars_read = read(fd, line + linelen, bytes_to_read);
- line[linelen + chars_read] = '\0';
- newline = strchr(line, '\n');
- }
- if (newline != NULL)
- *newline = '\0';
-
-#if defined(__powerpc__) || defined(__ppc__)
- // PowerPC cpus report the frequency in "clock" line
- if (strncasecmp(line, "clock", sizeof("clock")-1) == 0) {
- const char* freqstr = strchr(line, ':');
- if (freqstr) {
- // PowerPC frequencies are only reported as MHz (check 'show_cpuinfo'
- // function at arch/powerpc/kernel/setup-common.c)
- char *endp = strstr(line, "MHz");
- if (endp) {
- *endp = 0;
- cpuinfo_cycles_per_second = strtod(freqstr+1, &err) * 1000000.0;
- if (freqstr[1] != '\0' && *err == '\0' && cpuinfo_cycles_per_second > 0)
- saw_mhz = true;
- }
- }
-#else
- // When parsing the "cpu MHz" and "bogomips" (fallback) entries, we only
- // accept postive values. Some environments (virtual machines) report zero,
- // which would cause infinite looping in WallTime_Init.
- if (!saw_mhz && strncasecmp(line, "cpu MHz", sizeof("cpu MHz")-1) == 0) {
- const char* freqstr = strchr(line, ':');
- if (freqstr) {
- cpuinfo_cycles_per_second = strtod(freqstr+1, &err) * 1000000.0;
- if (freqstr[1] != '\0' && *err == '\0' && cpuinfo_cycles_per_second > 0)
- saw_mhz = true;
- }
- } else if (strncasecmp(line, "bogomips", sizeof("bogomips")-1) == 0) {
- const char* freqstr = strchr(line, ':');
- if (freqstr) {
- bogo_clock = strtod(freqstr+1, &err) * 1000000.0;
- if (freqstr[1] != '\0' && *err == '\0' && bogo_clock > 0)
- saw_bogo = true;
- }
-#endif
- } else if (strncasecmp(line, "processor", sizeof("processor")-1) == 0) {
- num_cpus++; // count up every time we see an "processor :" entry
- }
- } while (chars_read > 0);
- close(fd);
-
- if (!saw_mhz) {
- if (saw_bogo) {
- // If we didn't find anything better, we'll use bogomips, but
- // we're not happy about it.
- cpuinfo_cycles_per_second = bogo_clock;
- } else {
- // If we don't even have bogomips, we'll use the slow estimation.
- cpuinfo_cycles_per_second = EstimateCyclesPerSecond(1000);
- }
- }
- if (cpuinfo_cycles_per_second == 0.0) {
- cpuinfo_cycles_per_second = 1.0; // maybe unnecessary, but safe
- }
- if (num_cpus > 0) {
- cpuinfo_num_cpus = num_cpus;
- }
-
-#elif defined __FreeBSD__
- // For this sysctl to work, the machine must be configured without
- // SMP, APIC, or APM support. hz should be 64-bit in freebsd 7.0
- // and later. Before that, it's a 32-bit quantity (and gives the
- // wrong answer on machines faster than 2^32 Hz). See
- // http://lists.freebsd.org/pipermail/freebsd-i386/2004-November/001846.html
- // But also compare FreeBSD 7.0:
- // http://fxr.watson.org/fxr/source/i386/i386/tsc.c?v=RELENG70#L223
- // 231 error = sysctl_handle_quad(oidp, &freq, 0, req);
- // To FreeBSD 6.3 (it's the same in 6-STABLE):
- // http://fxr.watson.org/fxr/source/i386/i386/tsc.c?v=RELENG6#L131
- // 139 error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
-#if __FreeBSD__ >= 7
- uint64_t hz = 0;
-#else
- unsigned int hz = 0;
-#endif
- size_t sz = sizeof(hz);
- const char *sysctl_path = "machdep.tsc_freq";
- if ( sysctlbyname(sysctl_path, &hz, &sz, NULL, 0) != 0 ) {
- fprintf(stderr, "Unable to determine clock rate from sysctl: %s: %s\n",
- sysctl_path, strerror(errno));
- cpuinfo_cycles_per_second = EstimateCyclesPerSecond(1000);
- } else {
- cpuinfo_cycles_per_second = hz;
- }
- // TODO(csilvers): also figure out cpuinfo_num_cpus
-
-#elif defined(PLATFORM_WINDOWS)
-# pragma comment(lib, "shlwapi.lib") // for SHGetValue()
- // In NT, read MHz from the registry. If we fail to do so or we're in win9x
- // then make a crude estimate.
- OSVERSIONINFO os;
- os.dwOSVersionInfoSize = sizeof(os);
- DWORD data, data_size = sizeof(data);
- if (GetVersionEx(&os) &&
- os.dwPlatformId == VER_PLATFORM_WIN32_NT &&
- SUCCEEDED(SHGetValueA(HKEY_LOCAL_MACHINE,
- "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
- "~MHz", NULL, &data, &data_size)))
- cpuinfo_cycles_per_second = (int64)data * (int64)(1000 * 1000); // was mhz
- else
- cpuinfo_cycles_per_second = EstimateCyclesPerSecond(500); // TODO <500?
-
+int GetSystemCPUsCount()
+{
+#if defined(PLATFORM_WINDOWS)
// Get the number of processors.
SYSTEM_INFO info;
GetSystemInfo(&info);
- cpuinfo_num_cpus = info.dwNumberOfProcessors;
-
-#elif defined(__MACH__) && defined(__APPLE__)
- // returning "mach time units" per second. the current number of elapsed
- // mach time units can be found by calling uint64 mach_absolute_time();
- // while not as precise as actual CPU cycles, it is accurate in the face
- // of CPU frequency scaling and multi-cpu/core machines.
- // Our mac users have these types of machines, and accuracy
- // (i.e. correctness) trumps precision.
- // See cycleclock.h: CycleClock::Now(), which returns number of mach time
- // units on Mac OS X.
- mach_timebase_info_data_t timebase_info;
- mach_timebase_info(&timebase_info);
- double mach_time_units_per_nanosecond =
- static_cast<double>(timebase_info.denom) /
- static_cast<double>(timebase_info.numer);
- cpuinfo_cycles_per_second = mach_time_units_per_nanosecond * 1e9;
-
- int num_cpus = 0;
- size_t size = sizeof(num_cpus);
- int numcpus_name[] = { CTL_HW, HW_NCPU };
- if (::sysctl(numcpus_name, arraysize(numcpus_name), &num_cpus, &size, 0, 0)
- == 0
- && (size == sizeof(num_cpus)))
- cpuinfo_num_cpus = num_cpus;
-
+ return info.dwNumberOfProcessors;
#else
- // Generic cycles per second counter
- cpuinfo_cycles_per_second = EstimateCyclesPerSecond(1000);
+ long rv = sysconf(_SC_NPROCESSORS_ONLN);
+ if (rv < 0) {
+ return 1;
+ }
+ return static_cast<int>(rv);
#endif
}
-double CyclesPerSecond(void) {
- InitializeSystemInfo();
- return cpuinfo_cycles_per_second;
-}
-
-int NumCPUs(void) {
- InitializeSystemInfo();
- return cpuinfo_num_cpus;
-}
-
-// ----------------------------------------------------------------------
-// HasPosixThreads()
-// Return true if we're running POSIX (e.g., NPTL on Linux)
-// threads, as opposed to a non-POSIX thread library. The thing
-// that we care about is whether a thread's pid is the same as
-// the thread that spawned it. If so, this function returns
-// true.
-// ----------------------------------------------------------------------
-bool HasPosixThreads() {
-#if defined(__linux__)
-#ifndef _CS_GNU_LIBPTHREAD_VERSION
-#define _CS_GNU_LIBPTHREAD_VERSION 3
-#endif
- char buf[32];
- // We assume that, if confstr() doesn't know about this name, then
- // the same glibc is providing LinuxThreads.
- if (confstr(_CS_GNU_LIBPTHREAD_VERSION, buf, sizeof(buf)) == 0)
- return false;
- return strncmp(buf, "NPTL", 4) == 0;
-#elif defined(PLATFORM_WINDOWS) || defined(__CYGWIN__) || defined(__CYGWIN32__)
- return false;
-#else // other OS
- return true; // Assume that everything else has Posix
-#endif // else OS_LINUX
-}
-
// ----------------------------------------------------------------------
#if defined __linux__ || defined __FreeBSD__ || defined __sun__ || defined __CYGWIN__ || defined __CYGWIN32__
diff --git a/src/base/sysinfo.h b/src/base/sysinfo.h
index cc5cb74..77d956e 100644
--- a/src/base/sysinfo.h
+++ b/src/base/sysinfo.h
@@ -1,11 +1,11 @@
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
// Copyright (c) 2006, 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
@@ -15,7 +15,7 @@
// * 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
@@ -55,7 +55,7 @@
// routines that run before main(), when the state required for getenv() may
// not be set up yet. In particular, errno isn't set up until relatively late
// (after the pthreads library has a chance to make it threadsafe), and
-// getenv() doesn't work until then.
+// getenv() doesn't work until then.
// On some platforms, this call will utilize the same, static buffer for
// repeated GetenvBeforeMain() calls. Callers should not expect pointers from
// this routine to be long lived.
@@ -70,13 +70,7 @@
// reasons, as documented in sysinfo.cc. path must have space PATH_MAX.
extern bool GetUniquePathFromEnv(const char* env_name, char* path);
-extern int NumCPUs();
-
-void SleepForMilliseconds(int milliseconds);
-
-// processor cycles per second of each processor. Thread-safe.
-extern double CyclesPerSecond(void);
-
+extern int GetSystemCPUsCount();
// Return true if we're running POSIX (e.g., NPTL on Linux) threads,
// as opposed to a non-POSIX thread library. The thing that we care
diff --git a/src/base/thread_annotations.h b/src/base/thread_annotations.h
index f57b299..b68e756 100644
--- a/src/base/thread_annotations.h
+++ b/src/base/thread_annotations.h
@@ -1,10 +1,11 @@
+// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
// Copyright (c) 2008, 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
@@ -14,7 +15,7 @@
// * 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
@@ -35,8 +36,8 @@
// of their multi-threaded code. The annotations can also help program
// analysis tools to identify potential thread safety issues.
//
-// The annotations are implemented using GCC's "attributes" extension.
-// Using the macros defined here instead of the raw GCC attributes allows
+// The annotations are implemented using clang's "attributes" extension.
+// Using the macros defined here instead of the raw clang attributes allows
// for portability and future compatibility.
//
// This functionality is not yet fully implemented in perftools,
@@ -46,9 +47,7 @@
#define BASE_THREAD_ANNOTATIONS_H_
-#if defined(__GNUC__) \
- && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) \
- && defined(__SUPPORT_TS_ANNOTATION__) && (!defined(SWIG))
+#if defined(__clang__)
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
#else
#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
@@ -113,19 +112,19 @@
// The following annotations specify lock and unlock primitives.
#define EXCLUSIVE_LOCK_FUNCTION(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock(x))
+ THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(x))
#define SHARED_LOCK_FUNCTION(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(shared_lock(x))
+ THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(x))
#define EXCLUSIVE_TRYLOCK_FUNCTION(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock(x))
+ THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(x))
#define SHARED_TRYLOCK_FUNCTION(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock(x))
+ THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(x))
#define UNLOCK_FUNCTION(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(unlock(x))
+ THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(x))
// An escape hatch for thread safety analysis to ignore the annotated function.
#define NO_THREAD_SAFETY_ANALYSIS \
diff --git a/src/base/thread_lister.c b/src/base/thread_lister.c
index ca1b2de..2d7beb3 100644
--- a/src/base/thread_lister.c
+++ b/src/base/thread_lister.c
@@ -1,3 +1,4 @@
+/* -*- Mode: c; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/* Copyright (c) 2005-2007, Google Inc.
* All rights reserved.
*
@@ -32,11 +33,17 @@
*/
#include "config.h"
+
+#include "base/thread_lister.h"
+
#include <stdio.h> /* needed for NULL on some powerpc platforms (?!) */
+#include <sys/types.h>
+#include <unistd.h> /* for getpid */
+
#ifdef HAVE_SYS_PRCTL
# include <sys/prctl.h>
#endif
-#include "base/thread_lister.h"
+
#include "base/linuxthreads.h"
/* Include other thread listers here that define THREADS macro
* only when they can provide a good implementation.
diff --git a/src/base/vdso_support.cc b/src/base/vdso_support.cc
index 730df30..e4805e9 100644
--- a/src/base/vdso_support.cc
+++ b/src/base/vdso_support.cc
@@ -1,10 +1,11 @@
+// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
// Copyright (c) 2008, 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
@@ -14,7 +15,7 @@
// * 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
@@ -43,7 +44,6 @@
#include <stddef.h> // for ptrdiff_t
#include "base/atomicops.h" // for MemoryBarrier
-#include "base/linux_syscall_support.h"
#include "base/logging.h"
#include "base/dynamic_annotations.h"
#include "base/basictypes.h" // for COMPILE_ASSERT
diff --git a/src/base/vdso_support.h b/src/base/vdso_support.h
index c1209a4..073386c 100644
--- a/src/base/vdso_support.h
+++ b/src/base/vdso_support.h
@@ -1,3 +1,4 @@
+// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
@@ -61,7 +62,11 @@
#ifdef HAVE_ELF_MEM_IMAGE
+// Enable VDSO support only for the architectures/operating systems that
+// support it.
+#if defined(__linux__) && (defined(__i386__) || defined(__PPC__))
#define HAVE_VDSO_SUPPORT 1
+#endif
#include <stdlib.h> // for NULL