Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:00:52

0001 // Copyright 2017 The Abseil Authors.
0002 //
0003 // Licensed under the Apache License, Version 2.0 (the "License");
0004 // you may not use this file except in compliance with the License.
0005 // You may obtain a copy of the License at
0006 //
0007 //      https://www.apache.org/licenses/LICENSE-2.0
0008 //
0009 // Unless required by applicable law or agreed to in writing, software
0010 // distributed under the License is distributed on an "AS IS" BASIS,
0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012 // See the License for the specific language governing permissions and
0013 // limitations under the License.
0014 
0015 #ifndef ABSL_BASE_INTERNAL_SPINLOCK_WAIT_H_
0016 #define ABSL_BASE_INTERNAL_SPINLOCK_WAIT_H_
0017 
0018 // Operations to make atomic transitions on a word, and to allow
0019 // waiting for those transitions to become possible.
0020 
0021 #include <stdint.h>
0022 #include <atomic>
0023 
0024 #include "absl/base/internal/scheduling_mode.h"
0025 
0026 namespace absl {
0027 ABSL_NAMESPACE_BEGIN
0028 namespace base_internal {
0029 
0030 // SpinLockWait() waits until it can perform one of several transitions from
0031 // "from" to "to".  It returns when it performs a transition where done==true.
0032 struct SpinLockWaitTransition {
0033   uint32_t from;
0034   uint32_t to;
0035   bool done;
0036 };
0037 
0038 // Wait until *w can transition from trans[i].from to trans[i].to for some i
0039 // satisfying 0<=i<n && trans[i].done, atomically make the transition,
0040 // then return the old value of *w.   Make any other atomic transitions
0041 // where !trans[i].done, but continue waiting.
0042 //
0043 // Wakeups for threads blocked on SpinLockWait do not respect priorities.
0044 uint32_t SpinLockWait(std::atomic<uint32_t> *w, int n,
0045                       const SpinLockWaitTransition trans[],
0046                       SchedulingMode scheduling_mode);
0047 
0048 // If possible, wake some thread that has called SpinLockDelay(w, ...). If `all`
0049 // is true, wake all such threads. On some systems, this may be a no-op; on
0050 // those systems, threads calling SpinLockDelay() will always wake eventually
0051 // even if SpinLockWake() is never called.
0052 void SpinLockWake(std::atomic<uint32_t> *w, bool all);
0053 
0054 // Wait for an appropriate spin delay on iteration "loop" of a
0055 // spin loop on location *w, whose previously observed value was "value".
0056 // SpinLockDelay() may do nothing, may yield the CPU, may sleep a clock tick,
0057 // or may wait for a call to SpinLockWake(w).
0058 void SpinLockDelay(std::atomic<uint32_t> *w, uint32_t value, int loop,
0059                    base_internal::SchedulingMode scheduling_mode);
0060 
0061 // Helper used by AbslInternalSpinLockDelay.
0062 // Returns a suggested delay in nanoseconds for iteration number "loop".
0063 int SpinLockSuggestedDelayNS(int loop);
0064 
0065 }  // namespace base_internal
0066 ABSL_NAMESPACE_END
0067 }  // namespace absl
0068 
0069 // In some build configurations we pass --detect-odr-violations to the
0070 // gold linker.  This causes it to flag weak symbol overrides as ODR
0071 // violations.  Because ODR only applies to C++ and not C,
0072 // --detect-odr-violations ignores symbols not mangled with C++ names.
0073 // By changing our extension points to be extern "C", we dodge this
0074 // check.
0075 extern "C" {
0076 void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(std::atomic<uint32_t> *w,
0077                                                       bool all);
0078 void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
0079     std::atomic<uint32_t> *w, uint32_t value, int loop,
0080     absl::base_internal::SchedulingMode scheduling_mode);
0081 }
0082 
0083 inline void absl::base_internal::SpinLockWake(std::atomic<uint32_t> *w,
0084                                               bool all) {
0085   ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(w, all);
0086 }
0087 
0088 inline void absl::base_internal::SpinLockDelay(
0089     std::atomic<uint32_t> *w, uint32_t value, int loop,
0090     absl::base_internal::SchedulingMode scheduling_mode) {
0091   ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)
0092   (w, value, loop, scheduling_mode);
0093 }
0094 
0095 #endif  // ABSL_BASE_INTERNAL_SPINLOCK_WAIT_H_