| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you 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. |
| |
| #include "kudu/util/thread_restrictions.h" |
| |
| #include <ostream> |
| |
| #include <glog/logging.h> |
| |
| #include "kudu/util/debug/leakcheck_disabler.h" |
| #include "kudu/util/thread.h" |
| #include "kudu/util/threadlocal.h" |
| |
| #ifdef ENABLE_THREAD_RESTRICTIONS |
| |
| namespace kudu { |
| |
| namespace { |
| |
| struct LocalThreadRestrictions { |
| LocalThreadRestrictions() |
| : io_allowed(true), |
| wait_allowed(true), |
| singleton_allowed(true) { |
| } |
| |
| bool io_allowed; |
| bool wait_allowed; |
| bool singleton_allowed; |
| }; |
| |
| LocalThreadRestrictions* LoadTLS() { |
| // Disable leak check. LSAN sometimes gets false positives on thread locals. |
| // See: https://github.com/google/sanitizers/issues/757 |
| debug::ScopedLeakCheckDisabler d; |
| BLOCK_STATIC_THREAD_LOCAL(LocalThreadRestrictions, local_thread_restrictions); |
| return local_thread_restrictions; |
| } |
| |
| } // anonymous namespace |
| |
| bool ThreadRestrictions::SetIOAllowed(bool allowed) { |
| bool previous_allowed = LoadTLS()->io_allowed; |
| LoadTLS()->io_allowed = allowed; |
| return previous_allowed; |
| } |
| |
| void ThreadRestrictions::AssertIOAllowed() { |
| CHECK(LoadTLS()->io_allowed) |
| << "Function marked as IO-only was called from a thread that " |
| << "disallows IO! If this thread really should be allowed to " |
| << "make IO calls, adjust the call to " |
| << "kudu::ThreadRestrictions::SetIOAllowed() in this thread's " |
| << "startup. " |
| << (Thread::current_thread() ? Thread::current_thread()->ToString() : "(not a kudu::Thread)"); |
| } |
| |
| bool ThreadRestrictions::SetWaitAllowed(bool allowed) { |
| bool previous_allowed = LoadTLS()->wait_allowed; |
| LoadTLS()->wait_allowed = allowed; |
| return previous_allowed; |
| } |
| |
| void ThreadRestrictions::AssertWaitAllowed() { |
| CHECK(LoadTLS()->wait_allowed) |
| << "Waiting is not allowed to be used on this thread to prevent " |
| << "server-wide latency aberrations and deadlocks. " |
| << (Thread::current_thread() ? Thread::current_thread()->ToString() : "(not a kudu::Thread)"); |
| } |
| |
| } // namespace kudu |
| |
| #endif |