diff options
Diffstat (limited to 'absl/base/internal')
-rw-r--r-- | absl/base/internal/direct_mmap.h | 4 | ||||
-rw-r--r-- | absl/base/internal/exception_safety_testing.h | 2 | ||||
-rw-r--r-- | absl/base/internal/low_level_alloc.cc | 89 | ||||
-rw-r--r-- | absl/base/internal/low_level_alloc.h | 3 | ||||
-rw-r--r-- | absl/base/internal/nullability_impl.h | 106 | ||||
-rw-r--r-- | absl/base/internal/prefetch.h | 35 | ||||
-rw-r--r-- | absl/base/internal/raw_logging.cc | 35 | ||||
-rw-r--r-- | absl/base/internal/raw_logging.h | 28 | ||||
-rw-r--r-- | absl/base/internal/sysinfo.cc | 104 | ||||
-rw-r--r-- | absl/base/internal/thread_identity.cc | 17 | ||||
-rw-r--r-- | absl/base/internal/thread_identity.h | 22 | ||||
-rw-r--r-- | absl/base/internal/thread_identity_test.cc | 2 | ||||
-rw-r--r-- | absl/base/internal/throw_delegate.cc | 55 | ||||
-rw-r--r-- | absl/base/internal/unscaledcycleclock.cc | 5 |
14 files changed, 311 insertions, 196 deletions
diff --git a/absl/base/internal/direct_mmap.h b/absl/base/internal/direct_mmap.h index 815b8d23..1beb2ee4 100644 --- a/absl/base/internal/direct_mmap.h +++ b/absl/base/internal/direct_mmap.h @@ -72,7 +72,7 @@ namespace base_internal { // Platform specific logic extracted from // https://chromium.googlesource.com/linux-syscall-support/+/master/linux_syscall_support.h inline void* DirectMmap(void* start, size_t length, int prot, int flags, int fd, - off64_t offset) noexcept { + off_t offset) noexcept { #if defined(__i386__) || defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) || \ defined(__m68k__) || defined(__sh__) || \ (defined(__hppa__) && !defined(__LP64__)) || \ @@ -102,7 +102,7 @@ inline void* DirectMmap(void* start, size_t length, int prot, int flags, int fd, #else return reinterpret_cast<void*>( syscall(SYS_mmap2, start, length, prot, flags, fd, - static_cast<off_t>(offset / pagesize))); + static_cast<unsigned long>(offset / pagesize))); // NOLINT #endif #elif defined(__s390x__) // On s390x, mmap() arguments are passed in memory. diff --git a/absl/base/internal/exception_safety_testing.h b/absl/base/internal/exception_safety_testing.h index 77a5aec6..c1061544 100644 --- a/absl/base/internal/exception_safety_testing.h +++ b/absl/base/internal/exception_safety_testing.h @@ -946,7 +946,7 @@ class ExceptionSafetyTest { * `std::unique_ptr<T> operator()() const` where T is the type being tested. * It is used for reliably creating identical T instances to test on. * - * - Operation: The operation object (passsed in via tester.WithOperation(...) + * - Operation: The operation object (passed in via tester.WithOperation(...) * or tester.Test(...)) must be invocable with the signature * `void operator()(T*) const` where T is the type being tested. It is used * for performing steps on a T instance that may throw and that need to be diff --git a/absl/base/internal/low_level_alloc.cc b/absl/base/internal/low_level_alloc.cc index 662167b0..6d2cfeac 100644 --- a/absl/base/internal/low_level_alloc.cc +++ b/absl/base/internal/low_level_alloc.cc @@ -42,25 +42,25 @@ #include <windows.h> #endif +#ifdef __linux__ +#include <sys/prctl.h> +#endif + #include <string.h> + #include <algorithm> #include <atomic> #include <cerrno> #include <cstddef> -#include <new> // for placement-new +#include <new> // for placement-new #include "absl/base/dynamic_annotations.h" #include "absl/base/internal/raw_logging.h" #include "absl/base/internal/spinlock.h" -// MAP_ANONYMOUS -#if defined(__APPLE__) -// For mmap, Linux defines both MAP_ANONYMOUS and MAP_ANON and says MAP_ANON is -// deprecated. In Darwin, MAP_ANON is all there is. -#if !defined MAP_ANONYMOUS +#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) #define MAP_ANONYMOUS MAP_ANON -#endif // !MAP_ANONYMOUS -#endif // __APPLE__ +#endif namespace absl { ABSL_NAMESPACE_BEGIN @@ -122,7 +122,7 @@ static int IntLog2(size_t size, size_t base) { static int Random(uint32_t *state) { uint32_t r = *state; int result = 1; - while ((((r = r*1103515245 + 12345) >> 30) & 1) == 0) { + while ((((r = r * 1103515245 + 12345) >> 30) & 1) == 0) { result++; } *state = r; @@ -144,7 +144,7 @@ static int LLA_SkiplistLevels(size_t size, size_t base, uint32_t *random) { size_t max_fit = (size - offsetof(AllocList, next)) / sizeof(AllocList *); int level = IntLog2(size, base) + (random != nullptr ? Random(random) : 1); if (static_cast<size_t>(level) > max_fit) level = static_cast<int>(max_fit); - if (level > kMaxLevel-1) level = kMaxLevel - 1; + if (level > kMaxLevel - 1) level = kMaxLevel - 1; ABSL_RAW_CHECK(level >= 1, "block not big enough for even one level"); return level; } @@ -153,8 +153,8 @@ static int LLA_SkiplistLevels(size_t size, size_t base, uint32_t *random) { // For 0 <= i < head->levels, set prev[i] to "no_greater", where no_greater // points to the last element at level i in the AllocList less than *e, or is // head if no such element exists. -static AllocList *LLA_SkiplistSearch(AllocList *head, - AllocList *e, AllocList **prev) { +static AllocList *LLA_SkiplistSearch(AllocList *head, AllocList *e, + AllocList **prev) { AllocList *p = head; for (int level = head->levels - 1; level >= 0; level--) { for (AllocList *n; (n = p->next[level]) != nullptr && n < e; p = n) { @@ -190,7 +190,7 @@ static void LLA_SkiplistDelete(AllocList *head, AllocList *e, prev[i]->next[i] = e->next[i]; } while (head->levels > 0 && head->next[head->levels - 1] == nullptr) { - head->levels--; // reduce head->levels if level unused + head->levels--; // reduce head->levels if level unused } } @@ -249,9 +249,9 @@ void CreateGlobalArenas() { // Returns a global arena that does not call into hooks. Used by NewArena() // when kCallMallocHook is not set. -LowLevelAlloc::Arena* UnhookedArena() { +LowLevelAlloc::Arena *UnhookedArena() { base_internal::LowLevelCallOnce(&create_globals_once, CreateGlobalArenas); - return reinterpret_cast<LowLevelAlloc::Arena*>(&unhooked_arena_storage); + return reinterpret_cast<LowLevelAlloc::Arena *>(&unhooked_arena_storage); } #ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING @@ -269,7 +269,7 @@ LowLevelAlloc::Arena *UnhookedAsyncSigSafeArena() { // Returns the default arena, as used by LowLevelAlloc::Alloc() and friends. LowLevelAlloc::Arena *LowLevelAlloc::DefaultArena() { base_internal::LowLevelCallOnce(&create_globals_once, CreateGlobalArenas); - return reinterpret_cast<LowLevelAlloc::Arena*>(&default_arena_storage); + return reinterpret_cast<LowLevelAlloc::Arena *>(&default_arena_storage); } // magic numbers to identify allocated and unallocated blocks @@ -356,8 +356,7 @@ LowLevelAlloc::Arena::Arena(uint32_t flags_value) min_size(2 * round_up), random(0) { freelist.header.size = 0; - freelist.header.magic = - Magic(kMagicUnallocated, &freelist.header); + freelist.header.magic = Magic(kMagicUnallocated, &freelist.header); freelist.header.arena = this; freelist.levels = 0; memset(freelist.next, 0, sizeof(freelist.next)); @@ -375,7 +374,7 @@ LowLevelAlloc::Arena *LowLevelAlloc::NewArena(uint32_t flags) { meta_data_arena = UnhookedArena(); } Arena *result = - new (AllocWithArena(sizeof (*result), meta_data_arena)) Arena(flags); + new (AllocWithArena(sizeof(*result), meta_data_arena)) Arena(flags); return result; } @@ -480,8 +479,8 @@ static void Coalesce(AllocList *a) { AllocList *prev[kMaxLevel]; LLA_SkiplistDelete(&arena->freelist, n, prev); LLA_SkiplistDelete(&arena->freelist, a, prev); - a->levels = LLA_SkiplistLevels(a->header.size, arena->min_size, - &arena->random); + a->levels = + LLA_SkiplistLevels(a->header.size, arena->min_size, &arena->random); LLA_SkiplistInsert(&arena->freelist, a, prev); } } @@ -489,27 +488,27 @@ static void Coalesce(AllocList *a) { // Adds block at location "v" to the free list // L >= arena->mu static void AddToFreelist(void *v, LowLevelAlloc::Arena *arena) { - AllocList *f = reinterpret_cast<AllocList *>( - reinterpret_cast<char *>(v) - sizeof (f->header)); + AllocList *f = reinterpret_cast<AllocList *>(reinterpret_cast<char *>(v) - + sizeof(f->header)); ABSL_RAW_CHECK(f->header.magic == Magic(kMagicAllocated, &f->header), "bad magic number in AddToFreelist()"); ABSL_RAW_CHECK(f->header.arena == arena, "bad arena pointer in AddToFreelist()"); - f->levels = LLA_SkiplistLevels(f->header.size, arena->min_size, - &arena->random); + f->levels = + LLA_SkiplistLevels(f->header.size, arena->min_size, &arena->random); AllocList *prev[kMaxLevel]; LLA_SkiplistInsert(&arena->freelist, f, prev); f->header.magic = Magic(kMagicUnallocated, &f->header); - Coalesce(f); // maybe coalesce with successor - Coalesce(prev[0]); // maybe coalesce with predecessor + Coalesce(f); // maybe coalesce with successor + Coalesce(prev[0]); // maybe coalesce with predecessor } // Frees storage allocated by LowLevelAlloc::Alloc(). // L < arena->mu void LowLevelAlloc::Free(void *v) { if (v != nullptr) { - AllocList *f = reinterpret_cast<AllocList *>( - reinterpret_cast<char *>(v) - sizeof (f->header)); + AllocList *f = reinterpret_cast<AllocList *>(reinterpret_cast<char *>(v) - + sizeof(f->header)); LowLevelAlloc::Arena *arena = f->header.arena; ArenaLock section(arena); AddToFreelist(v, arena); @@ -524,21 +523,21 @@ void LowLevelAlloc::Free(void *v) { static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) { void *result = nullptr; if (request != 0) { - AllocList *s; // will point to region that satisfies request + AllocList *s; // will point to region that satisfies request ArenaLock section(arena); // round up with header - size_t req_rnd = RoundUp(CheckedAdd(request, sizeof (s->header)), - arena->round_up); - for (;;) { // loop until we find a suitable region + size_t req_rnd = + RoundUp(CheckedAdd(request, sizeof(s->header)), arena->round_up); + for (;;) { // loop until we find a suitable region // find the minimum levels that a block of this size must have int i = LLA_SkiplistLevels(req_rnd, arena->min_size, nullptr) - 1; - if (i < arena->freelist.levels) { // potential blocks exist + if (i < arena->freelist.levels) { // potential blocks exist AllocList *before = &arena->freelist; // predecessor of s while ((s = Next(i, before, arena)) != nullptr && s->header.size < req_rnd) { before = s; } - if (s != nullptr) { // we found a region + if (s != nullptr) { // we found a region break; } } @@ -550,7 +549,7 @@ static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) { size_t new_pages_size = RoundUp(req_rnd, arena->pagesize * 16); void *new_pages; #ifdef _WIN32 - new_pages = VirtualAlloc(0, new_pages_size, + new_pages = VirtualAlloc(nullptr, new_pages_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); ABSL_RAW_CHECK(new_pages != nullptr, "VirtualAlloc failed"); #else @@ -570,6 +569,18 @@ static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) { ABSL_RAW_LOG(FATAL, "mmap error: %d", errno); } +#ifdef __linux__ +#if defined(PR_SET_VMA) && defined(PR_SET_VMA_ANON_NAME) + // Attempt to name the allocated address range in /proc/$PID/smaps on + // Linux. + // + // This invocation of prctl() may fail if the Linux kernel was not + // configured with the CONFIG_ANON_VMA_NAME option. This is OK since + // the naming of arenas is primarily a debugging aid. + prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, new_pages, new_pages_size, + "absl"); +#endif +#endif // __linux__ #endif // _WIN32 arena->mu.Lock(); s = reinterpret_cast<AllocList *>(new_pages); @@ -580,12 +591,12 @@ static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) { AddToFreelist(&s->levels, arena); // insert new region into free list } AllocList *prev[kMaxLevel]; - LLA_SkiplistDelete(&arena->freelist, s, prev); // remove from free list + LLA_SkiplistDelete(&arena->freelist, s, prev); // remove from free list // s points to the first free region that's big enough if (CheckedAdd(req_rnd, arena->min_size) <= s->header.size) { // big enough to split - AllocList *n = reinterpret_cast<AllocList *> - (req_rnd + reinterpret_cast<char *>(s)); + AllocList *n = + reinterpret_cast<AllocList *>(req_rnd + reinterpret_cast<char *>(s)); n->header.size = s->header.size - req_rnd; n->header.magic = Magic(kMagicAllocated, &n->header); n->header.arena = arena; diff --git a/absl/base/internal/low_level_alloc.h b/absl/base/internal/low_level_alloc.h index eabb14a9..c2f1f25d 100644 --- a/absl/base/internal/low_level_alloc.h +++ b/absl/base/internal/low_level_alloc.h @@ -46,7 +46,8 @@ // for more information. #ifdef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING #error ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING cannot be directly set -#elif defined(_WIN32) || defined(__asmjs__) || defined(__wasm__) +#elif defined(_WIN32) || defined(__asmjs__) || defined(__wasm__) || \ + defined(__hexagon__) #define ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING 1 #endif diff --git a/absl/base/internal/nullability_impl.h b/absl/base/internal/nullability_impl.h new file mode 100644 index 00000000..36e1b33d --- /dev/null +++ b/absl/base/internal/nullability_impl.h @@ -0,0 +1,106 @@ +// Copyright 2023 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_ +#define ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_ + +#include <memory> +#include <type_traits> + +#include "absl/base/attributes.h" +#include "absl/meta/type_traits.h" + +namespace absl { + +namespace nullability_internal { + +// `IsNullabilityCompatible` checks whether its first argument is a class +// explicitly tagged as supporting nullability annotations. The tag is the type +// declaration `absl_nullability_compatible`. +template <typename, typename = void> +struct IsNullabilityCompatible : std::false_type {}; + +template <typename T> +struct IsNullabilityCompatible< + T, absl::void_t<typename T::absl_nullability_compatible>> : std::true_type { +}; + +template <typename T> +constexpr bool IsSupportedType = IsNullabilityCompatible<T>::value; + +template <typename T> +constexpr bool IsSupportedType<T*> = true; + +template <typename T, typename U> +constexpr bool IsSupportedType<T U::*> = true; + +template <typename T, typename... Deleter> +constexpr bool IsSupportedType<std::unique_ptr<T, Deleter...>> = true; + +template <typename T> +constexpr bool IsSupportedType<std::shared_ptr<T>> = true; + +template <typename T> +struct EnableNullable { + static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>, + "Template argument must be a raw or supported smart pointer " + "type. See absl/base/nullability.h."); + using type = T; +}; + +template <typename T> +struct EnableNonnull { + static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>, + "Template argument must be a raw or supported smart pointer " + "type. See absl/base/nullability.h."); + using type = T; +}; + +template <typename T> +struct EnableNullabilityUnknown { + static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>, + "Template argument must be a raw or supported smart pointer " + "type. See absl/base/nullability.h."); + using type = T; +}; + +// Note: we do not apply Clang nullability attributes (e.g. _Nullable). These +// only support raw pointers, and conditionally enabling them only for raw +// pointers inhibits template arg deduction. Ideally, they would support all +// pointer-like types. +template <typename T, typename = typename EnableNullable<T>::type> +using NullableImpl +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate) + [[clang::annotate("Nullable")]] +#endif + = T; + +template <typename T, typename = typename EnableNonnull<T>::type> +using NonnullImpl +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate) + [[clang::annotate("Nonnull")]] +#endif + = T; + +template <typename T, typename = typename EnableNullabilityUnknown<T>::type> +using NullabilityUnknownImpl +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate) + [[clang::annotate("Nullability_Unspecified")]] +#endif + = T; + +} // namespace nullability_internal +} // namespace absl + +#endif // ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_ diff --git a/absl/base/internal/prefetch.h b/absl/base/internal/prefetch.h index 06419283..aecfd877 100644 --- a/absl/base/internal/prefetch.h +++ b/absl/base/internal/prefetch.h @@ -12,10 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. +// TODO(b/265984188): remove all uses and delete this header. + #ifndef ABSL_BASE_INTERNAL_PREFETCH_H_ #define ABSL_BASE_INTERNAL_PREFETCH_H_ +#include "absl/base/attributes.h" #include "absl/base/config.h" +#include "absl/base/prefetch.h" #ifdef __SSE__ #include <xmmintrin.h> @@ -72,10 +76,21 @@ namespace absl { ABSL_NAMESPACE_BEGIN namespace base_internal { -void PrefetchT0(const void* addr); +ABSL_DEPRECATED("Use absl::PrefetchToLocalCache() instead") +inline void PrefetchT0(const void* address) { + absl::PrefetchToLocalCache(address); +} + +ABSL_DEPRECATED("Use absl::PrefetchToLocalCache() instead") +inline void PrefetchNta(const void* address) { + absl::PrefetchToLocalCacheNta(address); +} + +ABSL_DEPRECATED("Use __builtin_prefetch() for advanced prefetch logic instead") void PrefetchT1(const void* addr); + +ABSL_DEPRECATED("Use __builtin_prefetch() for advanced prefetch logic instead") void PrefetchT2(const void* addr); -void PrefetchNta(const void* addr); // Implementation details follow. @@ -90,10 +105,6 @@ void PrefetchNta(const void* addr); // safe for all currently supported platforms. However, prefetch for // store may have problems depending on the target platform. // -inline void PrefetchT0(const void* addr) { - // Note: this uses prefetcht0 on Intel. - __builtin_prefetch(addr, 0, 3); -} inline void PrefetchT1(const void* addr) { // Note: this uses prefetcht1 on Intel. __builtin_prefetch(addr, 0, 2); @@ -102,33 +113,21 @@ inline void PrefetchT2(const void* addr) { // Note: this uses prefetcht2 on Intel. __builtin_prefetch(addr, 0, 1); } -inline void PrefetchNta(const void* addr) { - // Note: this uses prefetchtnta on Intel. - __builtin_prefetch(addr, 0, 0); -} #elif defined(ABSL_INTERNAL_HAVE_SSE) #define ABSL_INTERNAL_HAVE_PREFETCH 1 -inline void PrefetchT0(const void* addr) { - _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T0); -} inline void PrefetchT1(const void* addr) { _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T1); } inline void PrefetchT2(const void* addr) { _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T2); } -inline void PrefetchNta(const void* addr) { - _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_NTA); -} #else -inline void PrefetchT0(const void*) {} inline void PrefetchT1(const void*) {} inline void PrefetchT2(const void*) {} -inline void PrefetchNta(const void*) {} #endif } // namespace base_internal diff --git a/absl/base/internal/raw_logging.cc b/absl/base/internal/raw_logging.cc index 6273e847..4c922ccf 100644 --- a/absl/base/internal/raw_logging.cc +++ b/absl/base/internal/raw_logging.cc @@ -21,6 +21,10 @@ #include <cstring> #include <string> +#ifdef __EMSCRIPTEN__ +#include <emscripten/console.h> +#endif + #include "absl/base/attributes.h" #include "absl/base/config.h" #include "absl/base/internal/atomic_hook.h" @@ -173,7 +177,7 @@ void RawLogVA(absl::LogSeverity severity, const char* file, int line, } else { DoRawLog(&buf, &size, "%s", kTruncated); } - AsyncSignalSafeWriteToStderr(buffer, strlen(buffer)); + AsyncSignalSafeWriteError(buffer, strlen(buffer)); } #else static_cast<void>(format); @@ -201,9 +205,34 @@ void DefaultInternalLog(absl::LogSeverity severity, const char* file, int line, } // namespace -void AsyncSignalSafeWriteToStderr(const char* s, size_t len) { +void AsyncSignalSafeWriteError(const char* s, size_t len) { + if (!len) return; absl::base_internal::ErrnoSaver errno_saver; -#if defined(ABSL_HAVE_SYSCALL_WRITE) +#if defined(__EMSCRIPTEN__) + // In WebAssembly, bypass filesystem emulation via fwrite. + if (s[len - 1] == '\n') { + // Skip a trailing newline character as emscripten_errn adds one itself. + len--; + } + // emscripten_errn was introduced in 3.1.41 but broken in standalone mode + // until 3.1.43. +#if ABSL_INTERNAL_EMSCRIPTEN_VERSION >= 3001043 + emscripten_errn(s, len); +#else + char buf[kLogBufSize]; + if (len >= kLogBufSize) { + len = kLogBufSize - 1; + constexpr size_t trunc_len = sizeof(kTruncated) - 2; + memcpy(buf + len - trunc_len, kTruncated, trunc_len); + buf[len] = '\0'; + len -= trunc_len; + } else { + buf[len] = '\0'; + } + memcpy(buf, s, len); + _emscripten_err(buf); +#endif +#elif defined(ABSL_HAVE_SYSCALL_WRITE) // We prefer calling write via `syscall` to minimize the risk of libc doing // something "helpful". syscall(SYS_write, STDERR_FILENO, s, len); diff --git a/absl/base/internal/raw_logging.h b/absl/base/internal/raw_logging.h index c7b889cd..b79550b2 100644 --- a/absl/base/internal/raw_logging.h +++ b/absl/base/internal/raw_logging.h @@ -48,6 +48,7 @@ ::absl::raw_log_internal::RawLog(ABSL_RAW_LOG_INTERNAL_##severity, \ absl_raw_log_internal_basename, __LINE__, \ __VA_ARGS__); \ + ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_##severity; \ } while (0) // Similar to CHECK(condition) << message, but for low-level modules: @@ -77,8 +78,7 @@ ::absl::raw_log_internal::internal_log_function( \ ABSL_RAW_LOG_INTERNAL_##severity, absl_raw_log_internal_filename, \ __LINE__, message); \ - if (ABSL_RAW_LOG_INTERNAL_##severity == ::absl::LogSeverity::kFatal) \ - ABSL_UNREACHABLE(); \ + ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_##severity; \ } while (0) #define ABSL_INTERNAL_CHECK(condition, message) \ @@ -90,6 +90,20 @@ } \ } while (0) +#ifndef NDEBUG + +#define ABSL_RAW_DLOG(severity, ...) ABSL_RAW_LOG(severity, __VA_ARGS__) +#define ABSL_RAW_DCHECK(condition, message) ABSL_RAW_CHECK(condition, message) + +#else // NDEBUG + +#define ABSL_RAW_DLOG(severity, ...) \ + while (false) ABSL_RAW_LOG(severity, __VA_ARGS__) +#define ABSL_RAW_DCHECK(condition, message) \ + while (false) ABSL_RAW_CHECK(condition, message) + +#endif // NDEBUG + #define ABSL_RAW_LOG_INTERNAL_INFO ::absl::LogSeverity::kInfo #define ABSL_RAW_LOG_INTERNAL_WARNING ::absl::LogSeverity::kWarning #define ABSL_RAW_LOG_INTERNAL_ERROR ::absl::LogSeverity::kError @@ -97,6 +111,12 @@ #define ABSL_RAW_LOG_INTERNAL_LEVEL(severity) \ ::absl::NormalizeLogSeverity(severity) +#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_INFO +#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_WARNING +#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_ERROR +#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_FATAL ABSL_UNREACHABLE() +#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_LEVEL(severity) + namespace absl { ABSL_NAMESPACE_BEGIN namespace raw_log_internal { @@ -109,8 +129,8 @@ void RawLog(absl::LogSeverity severity, const char* file, int line, const char* format, ...) ABSL_PRINTF_ATTRIBUTE(4, 5); // Writes the provided buffer directly to stderr, in a signal-safe, low-level -// manner. -void AsyncSignalSafeWriteToStderr(const char* s, size_t len); +// manner. Preserves errno. +void AsyncSignalSafeWriteError(const char* s, size_t len); // compile-time function to get the "base" filename, that is, the part of // a filename after the last "/" or "\" path separator. The search starts at diff --git a/absl/base/internal/sysinfo.cc b/absl/base/internal/sysinfo.cc index da499d3a..8bcc4faf 100644 --- a/absl/base/internal/sysinfo.cc +++ b/absl/base/internal/sysinfo.cc @@ -41,6 +41,7 @@ #include <string.h> #include <cassert> +#include <cerrno> #include <cstdint> #include <cstdio> #include <cstdlib> @@ -159,7 +160,7 @@ static double GetNominalCPUFrequency() { DWORD type = 0; DWORD data = 0; DWORD data_size = sizeof(data); - auto result = RegQueryValueExA(key, "~MHz", 0, &type, + auto result = RegQueryValueExA(key, "~MHz", nullptr, &type, reinterpret_cast<LPBYTE>(&data), &data_size); RegCloseKey(key); if (result == ERROR_SUCCESS && type == REG_DWORD && @@ -189,7 +190,13 @@ static double GetNominalCPUFrequency() { // and the memory location pointed to by value is set to the value read. static bool ReadLongFromFile(const char *file, long *value) { bool ret = false; - int fd = open(file, O_RDONLY | O_CLOEXEC); +#if defined(_POSIX_C_SOURCE) + const int file_mode = (O_RDONLY | O_CLOEXEC); +#else + const int file_mode = O_RDONLY; +#endif + + int fd = open(file, file_mode); if (fd != -1) { char line[1024]; char *err; @@ -225,8 +232,8 @@ static int64_t ReadMonotonicClockNanos() { int rc = clock_gettime(CLOCK_MONOTONIC, &t); #endif if (rc != 0) { - perror("clock_gettime() failed"); - abort(); + ABSL_INTERNAL_LOG( + FATAL, "clock_gettime() failed: (" + std::to_string(errno) + ")"); } return int64_t{t.tv_sec} * 1000000000 + t.tv_nsec; } @@ -414,82 +421,33 @@ pid_t GetTID() { return tid; } -#else +#elif defined(__APPLE__) -// Fallback implementation of GetTID using pthread_getspecific. -ABSL_CONST_INIT static once_flag tid_once; -ABSL_CONST_INIT static pthread_key_t tid_key; -ABSL_CONST_INIT static absl::base_internal::SpinLock tid_lock( - absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY); - -// We set a bit per thread in this array to indicate that an ID is in -// use. ID 0 is unused because it is the default value returned by -// pthread_getspecific(). -ABSL_CONST_INIT static std::vector<uint32_t> *tid_array - ABSL_GUARDED_BY(tid_lock) = nullptr; -static constexpr int kBitsPerWord = 32; // tid_array is uint32_t. - -// Returns the TID to tid_array. -static void FreeTID(void *v) { - intptr_t tid = reinterpret_cast<intptr_t>(v); - intptr_t word = tid / kBitsPerWord; - uint32_t mask = ~(1u << (tid % kBitsPerWord)); - absl::base_internal::SpinLockHolder lock(&tid_lock); - assert(0 <= word && static_cast<size_t>(word) < tid_array->size()); - (*tid_array)[static_cast<size_t>(word)] &= mask; +pid_t GetTID() { + uint64_t tid; + // `nullptr` here implies this thread. This only fails if the specified + // thread is invalid or the pointer-to-tid is null, so we needn't worry about + // it. + pthread_threadid_np(nullptr, &tid); + return static_cast<pid_t>(tid); } -static void InitGetTID() { - if (pthread_key_create(&tid_key, FreeTID) != 0) { - // The logging system calls GetTID() so it can't be used here. - perror("pthread_key_create failed"); - abort(); - } - - // Initialize tid_array. - absl::base_internal::SpinLockHolder lock(&tid_lock); - tid_array = new std::vector<uint32_t>(1); - (*tid_array)[0] = 1; // ID 0 is never-allocated. -} +#elif defined(__native_client__) -// Return a per-thread small integer ID from pthread's thread-specific data. pid_t GetTID() { - absl::call_once(tid_once, InitGetTID); - - intptr_t tid = reinterpret_cast<intptr_t>(pthread_getspecific(tid_key)); - if (tid != 0) { - return static_cast<pid_t>(tid); - } - - int bit; // tid_array[word] = 1u << bit; - size_t word; - { - // Search for the first unused ID. - absl::base_internal::SpinLockHolder lock(&tid_lock); - // First search for a word in the array that is not all ones. - word = 0; - while (word < tid_array->size() && ~(*tid_array)[word] == 0) { - ++word; - } - if (word == tid_array->size()) { - tid_array->push_back(0); // No space left, add kBitsPerWord more IDs. - } - // Search for a zero bit in the word. - bit = 0; - while (bit < kBitsPerWord && (((*tid_array)[word] >> bit) & 1) != 0) { - ++bit; - } - tid = - static_cast<intptr_t>((word * kBitsPerWord) + static_cast<size_t>(bit)); - (*tid_array)[word] |= 1u << bit; // Mark the TID as allocated. - } + auto* thread = pthread_self(); + static_assert(sizeof(pid_t) == sizeof(thread), + "In NaCL int expected to be the same size as a pointer"); + return reinterpret_cast<pid_t>(thread); +} - if (pthread_setspecific(tid_key, reinterpret_cast<void *>(tid)) != 0) { - perror("pthread_setspecific failed"); - abort(); - } +#else - return static_cast<pid_t>(tid); +// Fallback implementation of `GetTID` using `pthread_self`. +pid_t GetTID() { + // `pthread_t` need not be arithmetic per POSIX; platforms where it isn't + // should be handled above. + return static_cast<pid_t>(pthread_self()); } #endif diff --git a/absl/base/internal/thread_identity.cc b/absl/base/internal/thread_identity.cc index 79853f09..252443eb 100644 --- a/absl/base/internal/thread_identity.cc +++ b/absl/base/internal/thread_identity.cc @@ -58,18 +58,19 @@ void AllocateThreadIdentityKey(ThreadIdentityReclaimerFunction reclaimer) { // that protected visibility is unsupported. ABSL_CONST_INIT // Must come before __attribute__((visibility("protected"))) #if ABSL_HAVE_ATTRIBUTE(visibility) && !defined(__APPLE__) -__attribute__((visibility("protected"))) + __attribute__((visibility("protected"))) #endif // ABSL_HAVE_ATTRIBUTE(visibility) && !defined(__APPLE__) #if ABSL_PER_THREAD_TLS -// Prefer __thread to thread_local as benchmarks indicate it is a bit faster. -ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity* thread_identity_ptr = nullptr; + // Prefer __thread to thread_local as benchmarks indicate it is a bit + // faster. + ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity* thread_identity_ptr = nullptr; #elif defined(ABSL_HAVE_THREAD_LOCAL) -thread_local ThreadIdentity* thread_identity_ptr = nullptr; + thread_local ThreadIdentity* thread_identity_ptr = nullptr; #endif // ABSL_PER_THREAD_TLS #endif // TLS or CPP11 -void SetCurrentThreadIdentity( - ThreadIdentity* identity, ThreadIdentityReclaimerFunction reclaimer) { +void SetCurrentThreadIdentity(ThreadIdentity* identity, + ThreadIdentityReclaimerFunction reclaimer) { assert(CurrentThreadIdentityIfPresent() == nullptr); // Associate our destructor. // NOTE: This call to pthread_setspecific is currently the only immovable @@ -79,7 +80,7 @@ void SetCurrentThreadIdentity( absl::call_once(init_thread_identity_key_once, AllocateThreadIdentityKey, reclaimer); -#if defined(__EMSCRIPTEN__) || defined(__MINGW32__) +#if defined(__EMSCRIPTEN__) || defined(__MINGW32__) || defined(__hexagon__) // Emscripten and MinGW pthread implementations does not support signals. // See https://kripken.github.io/emscripten-site/docs/porting/pthreads.html // for more information. @@ -134,7 +135,7 @@ void ClearCurrentThreadIdentity() { ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11 thread_identity_ptr = nullptr; #elif ABSL_THREAD_IDENTITY_MODE == \ - ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC + ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC // pthread_setspecific expected to clear value on destruction assert(CurrentThreadIdentityIfPresent() == nullptr); #endif diff --git a/absl/base/internal/thread_identity.h b/absl/base/internal/thread_identity.h index 463acbc7..b6e917ce 100644 --- a/absl/base/internal/thread_identity.h +++ b/absl/base/internal/thread_identity.h @@ -62,8 +62,8 @@ struct PerThreadSynch { return reinterpret_cast<ThreadIdentity*>(this); } - PerThreadSynch *next; // Circular waiter queue; initialized to 0. - PerThreadSynch *skip; // If non-zero, all entries in Mutex queue + PerThreadSynch* next; // Circular waiter queue; initialized to 0. + PerThreadSynch* skip; // If non-zero, all entries in Mutex queue // up to and including "skip" have same // condition as this, and will be woken later bool may_skip; // if false while on mutex queue, a mutex unlocker @@ -104,10 +104,7 @@ struct PerThreadSynch { // // Transitions from kAvailable to kQueued require no barrier, they // are externally ordered by the Mutex. - enum State { - kAvailable, - kQueued - }; + enum State { kAvailable, kQueued }; std::atomic<State> state; // The wait parameters of the current wait. waitp is null if the @@ -122,14 +119,14 @@ struct PerThreadSynch { // pointer unchanged. SynchWaitParams* waitp; - intptr_t readers; // Number of readers in mutex. + intptr_t readers; // Number of readers in mutex. // When priority will next be read (cycles). int64_t next_priority_read_cycles; // Locks held; used during deadlock detection. // Allocated in Synch_GetAllLocks() and freed in ReclaimThreadIdentity(). - SynchLocksHeld *all_locks; + SynchLocksHeld* all_locks; }; // The instances of this class are allocated in NewThreadIdentity() with an @@ -147,7 +144,7 @@ struct ThreadIdentity { // Private: Reserved for absl::synchronization_internal::Waiter. struct WaiterState { - alignas(void*) char data[128]; + alignas(void*) char data[256]; } waiter_state; // Used by PerThreadSem::{Get,Set}ThreadBlockedCounter(). @@ -170,7 +167,10 @@ struct ThreadIdentity { // // Does not malloc(*), and is async-signal safe. // [*] Technically pthread_setspecific() does malloc on first use; however this -// is handled internally within tcmalloc's initialization already. +// is handled internally within tcmalloc's initialization already. Note that +// darwin does *not* use tcmalloc, so this can catch you if using MallocHooks +// on Apple platforms. Whatever function is calling your MallocHooks will need +// to watch for recursion on Apple platforms. // // New ThreadIdentity objects can be constructed and associated with a thread // by calling GetOrCreateCurrentThreadIdentity() in per-thread-sem.h. @@ -217,7 +217,7 @@ void ClearCurrentThreadIdentity(); #define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11 #elif defined(__APPLE__) && defined(ABSL_HAVE_THREAD_LOCAL) #define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11 -#elif ABSL_PER_THREAD_TLS && defined(__GOOGLE_GRTE_VERSION__) && \ +#elif ABSL_PER_THREAD_TLS && defined(__GOOGLE_GRTE_VERSION__) && \ (__GOOGLE_GRTE_VERSION__ >= 20140228L) // Support for async-safe TLS was specifically added in GRTEv4. It's not // present in the upstream eglibc. diff --git a/absl/base/internal/thread_identity_test.cc b/absl/base/internal/thread_identity_test.cc index 46a6f743..5f17553e 100644 --- a/absl/base/internal/thread_identity_test.cc +++ b/absl/base/internal/thread_identity_test.cc @@ -95,7 +95,7 @@ TEST(ThreadIdentityTest, BasicIdentityWorksThreaded) { } TEST(ThreadIdentityTest, ReusedThreadIdentityMutexTest) { - // This test repeatly creates and joins a series of threads, each of + // This test repeatedly creates and joins a series of threads, each of // which acquires and releases shared Mutex locks. This verifies // Mutex operations work correctly under a reused // ThreadIdentity. Note that the most likely failure mode of this diff --git a/absl/base/internal/throw_delegate.cc b/absl/base/internal/throw_delegate.cc index c260ff1e..337e870c 100644 --- a/absl/base/internal/throw_delegate.cc +++ b/absl/base/internal/throw_delegate.cc @@ -26,22 +26,13 @@ namespace absl { ABSL_NAMESPACE_BEGIN namespace base_internal { -// NOTE: The various STL exception throwing functions are placed within the -// #ifdef blocks so the symbols aren't exposed on platforms that don't support -// them, such as the Android NDK. For example, ANGLE fails to link when building -// within AOSP without them, since the STL functions don't exist. -namespace { -#ifdef ABSL_HAVE_EXCEPTIONS -template <typename T> -[[noreturn]] void Throw(const T& error) { - throw error; -} -#endif -} // namespace +// NOTE: The exception types, like `std::logic_error`, do not exist on all +// platforms. (For example, the Android NDK does not have them.) +// Therefore, their use must be guarded by `#ifdef` or equivalent. void ThrowStdLogicError(const std::string& what_arg) { #ifdef ABSL_HAVE_EXCEPTIONS - Throw(std::logic_error(what_arg)); + throw std::logic_error(what_arg); #else ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str()); std::abort(); @@ -49,7 +40,7 @@ void ThrowStdLogicError(const std::string& what_arg) { } void ThrowStdLogicError(const char* what_arg) { #ifdef ABSL_HAVE_EXCEPTIONS - Throw(std::logic_error(what_arg)); + throw std::logic_error(what_arg); #else ABSL_RAW_LOG(FATAL, "%s", what_arg); std::abort(); @@ -57,7 +48,7 @@ void ThrowStdLogicError(const char* what_arg) { } void ThrowStdInvalidArgument(const std::string& what_arg) { #ifdef ABSL_HAVE_EXCEPTIONS - Throw(std::invalid_argument(what_arg)); + throw std::invalid_argument(what_arg); #else ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str()); std::abort(); @@ -65,7 +56,7 @@ void ThrowStdInvalidArgument(const std::string& what_arg) { } void ThrowStdInvalidArgument(const char* what_arg) { #ifdef ABSL_HAVE_EXCEPTIONS - Throw(std::invalid_argument(what_arg)); + throw std::invalid_argument(what_arg); #else ABSL_RAW_LOG(FATAL, "%s", what_arg); std::abort(); @@ -74,7 +65,7 @@ void ThrowStdInvalidArgument(const char* what_arg) { void ThrowStdDomainError(const std::string& what_arg) { #ifdef ABSL_HAVE_EXCEPTIONS - Throw(std::domain_error(what_arg)); + throw std::domain_error(what_arg); #else ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str()); std::abort(); @@ -82,7 +73,7 @@ void ThrowStdDomainError(const std::string& what_arg) { } void ThrowStdDomainError(const char* what_arg) { #ifdef ABSL_HAVE_EXCEPTIONS - Throw(std::domain_error(what_arg)); + throw std::domain_error(what_arg); #else ABSL_RAW_LOG(FATAL, "%s", what_arg); std::abort(); @@ -91,7 +82,7 @@ void ThrowStdDomainError(const char* what_arg) { void ThrowStdLengthError(const std::string& what_arg) { #ifdef ABSL_HAVE_EXCEPTIONS - Throw(std::length_error(what_arg)); + throw std::length_error(what_arg); #else ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str()); std::abort(); @@ -99,7 +90,7 @@ void ThrowStdLengthError(const std::string& what_arg) { } void ThrowStdLengthError(const char* what_arg) { #ifdef ABSL_HAVE_EXCEPTIONS - Throw(std::length_error(what_arg)); + throw std::length_error(what_arg); #else ABSL_RAW_LOG(FATAL, "%s", what_arg); std::abort(); @@ -108,7 +99,7 @@ void ThrowStdLengthError(const char* what_arg) { void ThrowStdOutOfRange(const std::string& what_arg) { #ifdef ABSL_HAVE_EXCEPTIONS - Throw(std::out_of_range(what_arg)); + throw std::out_of_range(what_arg); #else ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str()); std::abort(); @@ -116,7 +107,7 @@ void ThrowStdOutOfRange(const std::string& what_arg) { } void ThrowStdOutOfRange(const char* what_arg) { #ifdef ABSL_HAVE_EXCEPTIONS - Throw(std::out_of_range(what_arg)); + throw std::out_of_range(what_arg); #else ABSL_RAW_LOG(FATAL, "%s", what_arg); std::abort(); @@ -125,7 +116,7 @@ void ThrowStdOutOfRange(const char* what_arg) { void ThrowStdRuntimeError(const std::string& what_arg) { #ifdef ABSL_HAVE_EXCEPTIONS - Throw(std::runtime_error(what_arg)); + throw std::runtime_error(what_arg); #else ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str()); std::abort(); @@ -133,7 +124,7 @@ void ThrowStdRuntimeError(const std::string& what_arg) { } void ThrowStdRuntimeError(const char* what_arg) { #ifdef ABSL_HAVE_EXCEPTIONS - Throw(std::runtime_error(what_arg)); + throw std::runtime_error(what_arg); #else ABSL_RAW_LOG(FATAL, "%s", what_arg); std::abort(); @@ -142,7 +133,7 @@ void ThrowStdRuntimeError(const char* what_arg) { void ThrowStdRangeError(const std::string& what_arg) { #ifdef ABSL_HAVE_EXCEPTIONS - Throw(std::range_error(what_arg)); + throw std::range_error(what_arg); #else ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str()); std::abort(); @@ -150,7 +141,7 @@ void ThrowStdRangeError(const std::string& what_arg) { } void ThrowStdRangeError(const char* what_arg) { #ifdef ABSL_HAVE_EXCEPTIONS - Throw(std::range_error(what_arg)); + throw std::range_error(what_arg); #else ABSL_RAW_LOG(FATAL, "%s", what_arg); std::abort(); @@ -159,7 +150,7 @@ void ThrowStdRangeError(const char* what_arg) { void ThrowStdOverflowError(const std::string& what_arg) { #ifdef ABSL_HAVE_EXCEPTIONS - Throw(std::overflow_error(what_arg)); + throw std::overflow_error(what_arg); #else ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str()); std::abort(); @@ -167,7 +158,7 @@ void ThrowStdOverflowError(const std::string& what_arg) { } void ThrowStdOverflowError(const char* what_arg) { #ifdef ABSL_HAVE_EXCEPTIONS - Throw(std::overflow_error(what_arg)); + throw std::overflow_error(what_arg); #else ABSL_RAW_LOG(FATAL, "%s", what_arg); std::abort(); @@ -176,7 +167,7 @@ void ThrowStdOverflowError(const char* what_arg) { void ThrowStdUnderflowError(const std::string& what_arg) { #ifdef ABSL_HAVE_EXCEPTIONS - Throw(std::underflow_error(what_arg)); + throw std::underflow_error(what_arg); #else ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str()); std::abort(); @@ -184,7 +175,7 @@ void ThrowStdUnderflowError(const std::string& what_arg) { } void ThrowStdUnderflowError(const char* what_arg) { #ifdef ABSL_HAVE_EXCEPTIONS - Throw(std::underflow_error(what_arg)); + throw std::underflow_error(what_arg); #else ABSL_RAW_LOG(FATAL, "%s", what_arg); std::abort(); @@ -193,7 +184,7 @@ void ThrowStdUnderflowError(const char* what_arg) { void ThrowStdBadFunctionCall() { #ifdef ABSL_HAVE_EXCEPTIONS - Throw(std::bad_function_call()); + throw std::bad_function_call(); #else std::abort(); #endif @@ -201,7 +192,7 @@ void ThrowStdBadFunctionCall() { void ThrowStdBadAlloc() { #ifdef ABSL_HAVE_EXCEPTIONS - Throw(std::bad_alloc()); + throw std::bad_alloc(); #else std::abort(); #endif diff --git a/absl/base/internal/unscaledcycleclock.cc b/absl/base/internal/unscaledcycleclock.cc index b1c396c6..05e0e7ba 100644 --- a/absl/base/internal/unscaledcycleclock.cc +++ b/absl/base/internal/unscaledcycleclock.cc @@ -71,13 +71,12 @@ int64_t UnscaledCycleClock::Now() { #else int32_t tbu, tbl, tmp; asm volatile( - "0:\n" "mftbu %[hi32]\n" "mftb %[lo32]\n" "mftbu %[tmp]\n" "cmpw %[tmp],%[hi32]\n" - "bne 0b\n" - : [ hi32 ] "=r"(tbu), [ lo32 ] "=r"(tbl), [ tmp ] "=r"(tmp)); + "bne $-16\n" // Retry on failure. + : [hi32] "=r"(tbu), [lo32] "=r"(tbl), [tmp] "=r"(tmp)); return (static_cast<int64_t>(tbu) << 32) | tbl; #endif #endif |