Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:40:42

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 // Core interfaces and definitions used by by low-level interfaces such as
0016 // SpinLock.
0017 
0018 #ifndef ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
0019 #define ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
0020 
0021 #include "absl/base/internal/raw_logging.h"
0022 #include "absl/base/internal/scheduling_mode.h"
0023 #include "absl/base/macros.h"
0024 
0025 // The following two declarations exist so SchedulingGuard may friend them with
0026 // the appropriate language linkage.  These callbacks allow libc internals, such
0027 // as function level statics, to schedule cooperatively when locking.
0028 extern "C" bool __google_disable_rescheduling(void);
0029 extern "C" void __google_enable_rescheduling(bool disable_result);
0030 
0031 namespace absl {
0032 ABSL_NAMESPACE_BEGIN
0033 class CondVar;
0034 class Mutex;
0035 
0036 namespace synchronization_internal {
0037 int MutexDelay(int32_t c, int mode);
0038 }  // namespace synchronization_internal
0039 
0040 namespace base_internal {
0041 
0042 class SchedulingHelper;  // To allow use of SchedulingGuard.
0043 class SpinLock;          // To allow use of SchedulingGuard.
0044 
0045 // SchedulingGuard
0046 // Provides guard semantics that may be used to disable cooperative rescheduling
0047 // of the calling thread within specific program blocks.  This is used to
0048 // protect resources (e.g. low-level SpinLocks or Domain code) that cooperative
0049 // scheduling depends on.
0050 //
0051 // Domain implementations capable of rescheduling in reaction to involuntary
0052 // kernel thread actions (e.g blocking due to a pagefault or syscall) must
0053 // guarantee that an annotated thread is not allowed to (cooperatively)
0054 // reschedule until the annotated region is complete.
0055 //
0056 // It is an error to attempt to use a cooperatively scheduled resource (e.g.
0057 // Mutex) within a rescheduling-disabled region.
0058 //
0059 // All methods are async-signal safe.
0060 class SchedulingGuard {
0061  public:
0062   // Returns true iff the calling thread may be cooperatively rescheduled.
0063   static bool ReschedulingIsAllowed();
0064   SchedulingGuard(const SchedulingGuard&) = delete;
0065   SchedulingGuard& operator=(const SchedulingGuard&) = delete;
0066 
0067  private:
0068   // Disable cooperative rescheduling of the calling thread.  It may still
0069   // initiate scheduling operations (e.g. wake-ups), however, it may not itself
0070   // reschedule.  Nestable.  The returned result is opaque, clients should not
0071   // attempt to interpret it.
0072   // REQUIRES: Result must be passed to a pairing EnableScheduling().
0073   static bool DisableRescheduling();
0074 
0075   // Marks the end of a rescheduling disabled region, previously started by
0076   // DisableRescheduling().
0077   // REQUIRES: Pairs with innermost call (and result) of DisableRescheduling().
0078   static void EnableRescheduling(bool disable_result);
0079 
0080   // A scoped helper for {Disable, Enable}Rescheduling().
0081   // REQUIRES: destructor must run in same thread as constructor.
0082   struct ScopedDisable {
0083     ScopedDisable() { disabled = SchedulingGuard::DisableRescheduling(); }
0084     ~ScopedDisable() { SchedulingGuard::EnableRescheduling(disabled); }
0085 
0086     bool disabled;
0087   };
0088 
0089   // A scoped helper to enable rescheduling temporarily.
0090   // REQUIRES: destructor must run in same thread as constructor.
0091   class ScopedEnable {
0092    public:
0093     ScopedEnable();
0094     ~ScopedEnable();
0095 
0096    private:
0097     int scheduling_disabled_depth_;
0098   };
0099 
0100   // Access to SchedulingGuard is explicitly permitted.
0101   friend class absl::CondVar;
0102   friend class absl::Mutex;
0103   friend class SchedulingHelper;
0104   friend class SpinLock;
0105   friend int absl::synchronization_internal::MutexDelay(int32_t c, int mode);
0106 };
0107 
0108 //------------------------------------------------------------------------------
0109 // End of public interfaces.
0110 //------------------------------------------------------------------------------
0111 
0112 inline bool SchedulingGuard::ReschedulingIsAllowed() {
0113   return false;
0114 }
0115 
0116 inline bool SchedulingGuard::DisableRescheduling() {
0117   return false;
0118 }
0119 
0120 inline void SchedulingGuard::EnableRescheduling(bool /* disable_result */) {
0121   return;
0122 }
0123 
0124 inline SchedulingGuard::ScopedEnable::ScopedEnable()
0125     : scheduling_disabled_depth_(0) {}
0126 inline SchedulingGuard::ScopedEnable::~ScopedEnable() {
0127   ABSL_RAW_CHECK(scheduling_disabled_depth_ == 0, "disable unused warning");
0128 }
0129 
0130 }  // namespace base_internal
0131 ABSL_NAMESPACE_END
0132 }  // namespace absl
0133 
0134 #endif  // ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_