1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <folly/SharedMutex.h>
18 
19 #include <folly/Indestructible.h>
20 
21 namespace folly {
22 // Explicitly instantiate SharedMutex here:
23 template class SharedMutexImpl<true>;
24 template class SharedMutexImpl<false>;
25 
26 namespace shared_mutex_detail {
annotationGuard(void * ptr)27 std::unique_lock<std::mutex> annotationGuard(void* ptr) {
28   if (folly::kIsSanitizeThread) {
29     // On TSAN builds, we have an array of mutexes and index into them based on
30     // the address. If the array is of prime size things will work out okay
31     // without a complicated hash function.
32     static constexpr std::size_t kNumAnnotationMutexes = 251;
33     static Indestructible<std::array<std::mutex, kNumAnnotationMutexes>>
34         kAnnotationMutexes;
35     auto index = reinterpret_cast<uintptr_t>(ptr) % kNumAnnotationMutexes;
36     return std::unique_lock<std::mutex>((*kAnnotationMutexes)[index]);
37   } else {
38     return std::unique_lock<std::mutex>();
39   }
40 }
41 
getMaxDeferredReadersSlow(std::atomic<uint32_t> & cache)42 uint32_t getMaxDeferredReadersSlow(std::atomic<uint32_t>& cache) {
43   uint32_t maxDeferredReaders = std::min(
44       static_cast<uint32_t>(
45           folly::nextPowTwo(CacheLocality::system().numCpus) << 1),
46       shared_mutex_detail::kMaxDeferredReadersAllocated);
47   // maxDeferredReaders must be a power of 2
48   assert(!(maxDeferredReaders & (maxDeferredReaders - 1)));
49   cache.store(maxDeferredReaders, std::memory_order_release);
50   return maxDeferredReaders;
51 }
52 } // namespace shared_mutex_detail
53 } // namespace folly
54