Changes imported from Abseil "staging" branch:
- fbff677ef850865ea67ed6771a8ed348be181e8e Modify sysinfo.cc to support GetTID on Akaros. by Abseil Team <absl-team@google.com> - f1c2929e08a3d4181e08cb5014c4a569306fd922 Two functions that did not refer to their arguments unles... by Abseil Team <absl-team@google.com> - ee43cc3bfdb4d84d40eee31fb25ecdc1aa060f47 Support Akaros (https://akaros.org) in the ABSL spinlock_... by Abseil Team <absl-team@google.com> - 6869c8c5253126459d6c7f0aa708d8612c8e5963 Make sure vdso_base_ is constant-intialized. by Abseil Team <absl-team@google.com> - d54e0366efc8d44cd5da5fd157734da966dc45e8 Add missing include for assert used by ABSL_ASSERT. by Derek Mauro <dmauro@google.com> - a5139775f3917bb5201e7fc838135766daa05b8d When building against GLIBC-2.16 or newer, use getauxval(... by Abseil Team <absl-team@google.com> GitOrigin-RevId: fbff677ef850865ea67ed6771a8ed348be181e8e Change-Id: Ie3549f6ef054783dd104304d2faf8d9800c16b83
This commit is contained in:
		
							parent
							
								
									5fcbe86e7b
								
							
						
					
					
						commit
						dedb4eec6c
					
				
					 9 changed files with 120 additions and 34 deletions
				
			
		|  | @ -28,6 +28,7 @@ licenses(["notice"])  # Apache 2.0 | |||
| cc_library( | ||||
|     name = "spinlock_wait", | ||||
|     srcs = [ | ||||
|         "internal/spinlock_akaros.inc", | ||||
|         "internal/spinlock_posix.inc", | ||||
|         "internal/spinlock_wait.cc", | ||||
|         "internal/spinlock_win32.inc", | ||||
|  |  | |||
							
								
								
									
										35
									
								
								absl/base/internal/spinlock_akaros.inc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								absl/base/internal/spinlock_akaros.inc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | |||
| // Copyright 2017 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
 | ||||
| //
 | ||||
| //      http://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.
 | ||||
| //
 | ||||
| // This file is an Akaros-specific part of spinlock_wait.cc
 | ||||
| 
 | ||||
| #include <atomic>
 | ||||
| 
 | ||||
| #include "absl/base/internal/scheduling_mode.h"
 | ||||
| 
 | ||||
| extern "C" { | ||||
| 
 | ||||
| ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay( | ||||
|     std::atomic<uint32_t>* /* lock_word */, uint32_t /* value */, | ||||
|     int /* loop */, absl::base_internal::SchedulingMode /* mode */) { | ||||
|   // In Akaros, one must take care not to call anything that could cause a
 | ||||
|   // malloc(), a blocking system call, or a uthread_yield() while holding a
 | ||||
|   // spinlock. Our callers assume will not call into libraries or other
 | ||||
|   // arbitrary code.
 | ||||
| } | ||||
| 
 | ||||
| ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockWake( | ||||
|     std::atomic<uint32_t>* /* lock_word */, bool /* all */) {} | ||||
| 
 | ||||
| }  // extern "C"
 | ||||
|  | @ -23,6 +23,8 @@ | |||
| 
 | ||||
| #if defined(_WIN32) | ||||
| #include "absl/base/internal/spinlock_win32.inc" | ||||
| #elif defined(__akaros__) | ||||
| #include "absl/base/internal/spinlock_akaros.inc" | ||||
| #else | ||||
| #include "absl/base/internal/spinlock_posix.inc" | ||||
| #endif | ||||
|  |  | |||
|  | @ -284,6 +284,30 @@ pid_t GetTID() { | |||
|   return syscall(SYS_gettid); | ||||
| } | ||||
| 
 | ||||
| #elif defined(__akaros__) | ||||
| 
 | ||||
| pid_t GetTID() { | ||||
|   // Akaros has a concept of "vcore context", which is the state the program
 | ||||
|   // is forced into when we need to make a user-level scheduling decision, or
 | ||||
|   // run a signal handler.  This is analogous to the interrupt context that a
 | ||||
|   // CPU might enter if it encounters some kind of exception.
 | ||||
|   //
 | ||||
|   // There is no current thread context in vcore context, but we need to give
 | ||||
|   // a reasonable answer if asked for a thread ID (e.g., in a signal handler).
 | ||||
|   // Thread 0 always exists, so if we are in vcore context, we return that.
 | ||||
|   //
 | ||||
|   // Otherwise, we know (since we are using pthreads) that the uthread struct
 | ||||
|   // current_uthread is pointing to is the first element of a
 | ||||
|   // struct pthread_tcb, so we extract and return the thread ID from that.
 | ||||
|   //
 | ||||
|   // TODO(dcross): Akaros anticipates moving the thread ID to the uthread
 | ||||
|   // structure at some point. We should modify this code to remove the cast
 | ||||
|   // when that happens.
 | ||||
|   if (in_vcore_context()) | ||||
|     return 0; | ||||
|   return reinterpret_cast<struct pthread_tcb *>(current_uthread)->id; | ||||
| } | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
| // Fallback implementation of GetTID using pthread_getspecific.
 | ||||
|  |  | |||
|  | @ -29,6 +29,7 @@ | |||
| #ifndef ABSL_BASE_MACROS_H_ | ||||
| #define ABSL_BASE_MACROS_H_ | ||||
| 
 | ||||
| #include <cassert> | ||||
| #include <cstddef> | ||||
| 
 | ||||
| #include "absl/base/port.h" | ||||
|  |  | |||
|  | @ -75,8 +75,9 @@ const T *GetTableElement(const ElfW(Ehdr) * ehdr, ElfW(Off) table_offset, | |||
| 
 | ||||
| }  // namespace
 | ||||
| 
 | ||||
| const void *const ElfMemImage::kInvalidBase = | ||||
|     reinterpret_cast<const void *>(~0L); | ||||
| // The value of this variable doesn't matter; it's used only for its
 | ||||
| // unique address.
 | ||||
| const int ElfMemImage::kInvalidBaseSentinel = 0; | ||||
| 
 | ||||
| ElfMemImage::ElfMemImage(const void *base) { | ||||
|   ABSL_RAW_CHECK(base != kInvalidBase, "bad pointer"); | ||||
|  |  | |||
|  | @ -43,9 +43,14 @@ namespace debug_internal { | |||
| 
 | ||||
| // An in-memory ELF image (may not exist on disk).
 | ||||
| class ElfMemImage { | ||||
|  private: | ||||
|   // Sentinel: there could never be an elf image at &kInvalidBaseSentinel.
 | ||||
|   static const int kInvalidBaseSentinel; | ||||
| 
 | ||||
|  public: | ||||
|   // Sentinel: there could never be an elf image at this address.
 | ||||
|   static const void *const kInvalidBase; | ||||
|   static constexpr const void *const kInvalidBase = | ||||
|     static_cast<const void*>(&kInvalidBaseSentinel); | ||||
| 
 | ||||
|   // Information about a single vdso symbol.
 | ||||
|   // All pointers are into .dynsym, .dynstr, or .text of the VDSO.
 | ||||
|  |  | |||
|  | @ -114,7 +114,9 @@ static const int kMaxFrameBytes = 100000; | |||
| // vuc is a ucontext_t *.  We use void* to avoid the use
 | ||||
| // of ucontext_t on non-POSIX systems.
 | ||||
| static uintptr_t GetFP(const void *vuc) { | ||||
| #if defined(__linux__)
 | ||||
| #if !defined(__linux__)
 | ||||
|   static_cast<void>(vuc);  // Avoid an unused argument compiler warning.
 | ||||
| #else
 | ||||
|   if (vuc != nullptr) { | ||||
|     auto *uc = reinterpret_cast<const ucontext_t *>(vuc); | ||||
| #if defined(__i386__)
 | ||||
|  |  | |||
|  | @ -20,10 +20,15 @@ | |||
| 
 | ||||
| #ifdef ABSL_HAVE_VDSO_SUPPORT     // defined in vdso_support.h
 | ||||
| 
 | ||||
| #include <errno.h> | ||||
| #include <fcntl.h> | ||||
| #include <sys/syscall.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| #if __GLIBC_PREREQ(2, 16)  // GLIBC-2.16 implements getauxval.
 | ||||
| #include <sys/auxv.h> | ||||
| #endif | ||||
| 
 | ||||
| #include "absl/base/dynamic_annotations.h" | ||||
| #include "absl/base/internal/raw_logging.h" | ||||
| #include "absl/base/port.h" | ||||
|  | @ -35,8 +40,10 @@ | |||
| namespace absl { | ||||
| namespace debug_internal { | ||||
| 
 | ||||
| ABSL_CONST_INIT | ||||
| std::atomic<const void *> VDSOSupport::vdso_base_( | ||||
|     debug_internal::ElfMemImage::kInvalidBase); | ||||
| 
 | ||||
| std::atomic<VDSOSupport::GetCpuFn> VDSOSupport::getcpu_fn_(&InitAndGetCPU); | ||||
| VDSOSupport::VDSOSupport() | ||||
|     // If vdso_base_ is still set to kInvalidBase, we got here
 | ||||
|  | @ -56,9 +63,18 @@ VDSOSupport::VDSOSupport() | |||
| // Finally, even if there is a race here, it is harmless, because
 | ||||
| // the operation should be idempotent.
 | ||||
| const void *VDSOSupport::Init() { | ||||
|   if (vdso_base_.load(std::memory_order_relaxed) == | ||||
|       debug_internal::ElfMemImage::kInvalidBase) { | ||||
|     { | ||||
|   const auto kInvalidBase = debug_internal::ElfMemImage::kInvalidBase; | ||||
| #if __GLIBC_PREREQ(2, 16) | ||||
|   if (vdso_base_.load(std::memory_order_relaxed) == kInvalidBase) { | ||||
|     errno = 0; | ||||
|     const void *const sysinfo_ehdr = | ||||
|         reinterpret_cast<const void *>(getauxval(AT_SYSINFO_EHDR)); | ||||
|     if (errno == 0) { | ||||
|       vdso_base_.store(sysinfo_ehdr, std::memory_order_relaxed); | ||||
|     } | ||||
|   } | ||||
| #endif  // __GLIBC_PREREQ(2, 16)
 | ||||
|   if (vdso_base_.load(std::memory_order_relaxed) == kInvalidBase) { | ||||
|     // Valgrind zaps AT_SYSINFO_EHDR and friends from the auxv[]
 | ||||
|     // on stack, and so glibc works as if VDSO was not present.
 | ||||
|     // But going directly to kernel via /proc/self/auxv below bypasses
 | ||||
|  | @ -84,9 +100,7 @@ const void *VDSOSupport::Init() { | |||
|       } | ||||
|     } | ||||
|     close(fd); | ||||
|     } | ||||
|     if (vdso_base_.load(std::memory_order_relaxed) == | ||||
|         debug_internal::ElfMemImage::kInvalidBase) { | ||||
|     if (vdso_base_.load(std::memory_order_relaxed) == kInvalidBase) { | ||||
|       // Didn't find AT_SYSINFO_EHDR in auxv[].
 | ||||
|       vdso_base_.store(nullptr, std::memory_order_relaxed); | ||||
|     } | ||||
|  | @ -135,6 +149,7 @@ long VDSOSupport::GetCPUViaSyscall(unsigned *cpu,  // NOLINT(runtime/int) | |||
|   return syscall(SYS_getcpu, cpu, nullptr, nullptr); | ||||
| #else | ||||
|   // x86_64 never implemented sys_getcpu(), except as a VDSO call.
 | ||||
|   static_cast<void>(cpu);  // Avoid an unused argument compiler warning.
 | ||||
|   errno = ENOSYS; | ||||
|   return -1; | ||||
| #endif | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue