/Users/deen/code/yugabyte-db/src/yb/rocksdb/port/port_posix.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
2 | | // This source code is licensed under the BSD-style license found in the |
3 | | // LICENSE file in the root directory of this source tree. An additional grant |
4 | | // of patent rights can be found in the PATENTS file in the same directory. |
5 | | // |
6 | | // The following only applies to changes made to this file as part of YugaByte development. |
7 | | // |
8 | | // Portions Copyright (c) YugaByte, Inc. |
9 | | // |
10 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
11 | | // in compliance with the License. You may obtain a copy of the License at |
12 | | // |
13 | | // http://www.apache.org/licenses/LICENSE-2.0 |
14 | | // |
15 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
16 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
17 | | // or implied. See the License for the specific language governing permissions and limitations |
18 | | // under the License. |
19 | | // |
20 | | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. |
21 | | // Use of this source code is governed by a BSD-style license that can be |
22 | | // found in the LICENSE file. See the AUTHORS file for names of contributors. |
23 | | |
24 | | #include "yb/rocksdb/port/port_posix.h" |
25 | | |
26 | | #include <assert.h> |
27 | | #if defined(__i386__) || defined(__x86_64__) |
28 | | #include <cpuid.h> |
29 | | #endif |
30 | | #include <signal.h> |
31 | | #include <stdio.h> |
32 | | #include <string.h> |
33 | | |
34 | | #include <glog/logging.h> |
35 | | |
36 | | #include "yb/rocksdb/util/logging.h" |
37 | | #include "yb/util/status_log.h" |
38 | | |
39 | | #if defined(RLIMIT_NOFILE) |
40 | | #include "yb/util/std_util.h" |
41 | | #endif |
42 | | |
43 | | namespace rocksdb { |
44 | | namespace port { |
45 | | |
46 | 995M | static int PthreadCall(const char* label, int result) { |
47 | 995M | if (result != 0 && result != ETIMEDOUT) { |
48 | 0 | fprintf(stderr, "pthread %s: %s\n", label, strerror(result)); |
49 | 0 | abort(); |
50 | 0 | } |
51 | 995M | return result; |
52 | 995M | } |
53 | | |
54 | 116M | Mutex::Mutex(bool adaptive) { |
55 | | #ifdef __linux__ |
56 | | if (!adaptive) { |
57 | | PthreadCall("init mutex", pthread_mutex_init(&mu_, nullptr)); |
58 | | } else { |
59 | | pthread_mutexattr_t mutex_attr; |
60 | | PthreadCall("init mutex attr", pthread_mutexattr_init(&mutex_attr)); |
61 | | PthreadCall("set mutex attr", |
62 | | pthread_mutexattr_settype(&mutex_attr, |
63 | | PTHREAD_MUTEX_ADAPTIVE_NP)); |
64 | | PthreadCall("init mutex", pthread_mutex_init(&mu_, &mutex_attr)); |
65 | | PthreadCall("destroy mutex attr", |
66 | | pthread_mutexattr_destroy(&mutex_attr)); |
67 | | } |
68 | | #else // ignore adaptive for non-linux platform |
69 | 116M | PthreadCall("init mutex", pthread_mutex_init(&mu_, nullptr)); |
70 | 116M | #endif // __linux__ |
71 | 116M | } |
72 | | |
73 | 115M | Mutex::~Mutex() { PthreadCall("destroy mutex", pthread_mutex_destroy(&mu_)); } |
74 | | |
75 | 380M | void Mutex::Lock() { |
76 | 380M | PthreadCall("lock", pthread_mutex_lock(&mu_)); |
77 | 380M | #ifndef NDEBUG |
78 | 380M | locked_ = true; |
79 | 380M | #endif |
80 | 380M | } |
81 | | |
82 | 380M | void Mutex::Unlock() { |
83 | 380M | #ifndef NDEBUG |
84 | 380M | locked_ = false; |
85 | 380M | #endif |
86 | 380M | PthreadCall("unlock", pthread_mutex_unlock(&mu_)); |
87 | 380M | } |
88 | | |
89 | 9.29M | void Mutex::AssertHeld() { |
90 | 9.29M | #ifndef NDEBUG |
91 | 9.29M | DCHECK(locked_); |
92 | 9.29M | #endif |
93 | 9.29M | } |
94 | | |
95 | | CondVar::CondVar(Mutex* mu) |
96 | 1.06M | : mu_(mu) { |
97 | 1.06M | PthreadCall("init cv", pthread_cond_init(&cv_, nullptr)); |
98 | 1.06M | } |
99 | | |
100 | 1.01M | CondVar::~CondVar() { PthreadCall("destroy cv", pthread_cond_destroy(&cv_)); } |
101 | | |
102 | 46.2k | void CondVar::Wait() { |
103 | 46.2k | #ifndef NDEBUG |
104 | 46.2k | mu_->locked_ = false; |
105 | 46.2k | #endif |
106 | 46.2k | PthreadCall("wait", pthread_cond_wait(&cv_, &mu_->mu_)); |
107 | 46.2k | #ifndef NDEBUG |
108 | 46.2k | mu_->locked_ = true; |
109 | 46.2k | #endif |
110 | 46.2k | } |
111 | | |
112 | 2.31k | bool CondVar::TimedWait(uint64_t abs_time_us) { |
113 | 2.31k | struct timespec ts; |
114 | 2.31k | ts.tv_sec = static_cast<time_t>(abs_time_us / 1000000); |
115 | 2.31k | ts.tv_nsec = static_cast<suseconds_t>((abs_time_us % 1000000) * 1000); |
116 | | |
117 | 2.31k | #ifndef NDEBUG |
118 | 2.31k | mu_->locked_ = false; |
119 | 2.31k | #endif |
120 | 2.31k | int err = pthread_cond_timedwait(&cv_, &mu_->mu_, &ts); |
121 | 2.31k | #ifndef NDEBUG |
122 | 2.31k | mu_->locked_ = true; |
123 | 2.31k | #endif |
124 | 2.31k | if (err == ETIMEDOUT) { |
125 | 2.07k | return true; |
126 | 2.07k | } |
127 | 232 | if (err != 0) { |
128 | 0 | PthreadCall("timedwait", err); |
129 | 0 | } |
130 | 232 | return false; |
131 | 232 | } |
132 | | |
133 | 11.6k | void CondVar::Signal() { |
134 | 11.6k | PthreadCall("signal", pthread_cond_signal(&cv_)); |
135 | 11.6k | } |
136 | | |
137 | 501k | void CondVar::SignalAll() { |
138 | 501k | PthreadCall("broadcast", pthread_cond_broadcast(&cv_)); |
139 | 501k | } |
140 | | |
141 | 900k | RWMutex::RWMutex() { |
142 | 900k | PthreadCall("init mutex", pthread_rwlock_init(&mu_, nullptr)); |
143 | 900k | } |
144 | | |
145 | 900k | RWMutex::~RWMutex() { PthreadCall("destroy mutex", pthread_rwlock_destroy(&mu_)); } |
146 | | |
147 | 32.1k | void RWMutex::ReadLock() { PthreadCall("read lock", pthread_rwlock_rdlock(&mu_)); } |
148 | | |
149 | 45.2k | void RWMutex::WriteLock() { PthreadCall("write lock", pthread_rwlock_wrlock(&mu_)); } |
150 | | |
151 | 32.1k | void RWMutex::ReadUnlock() { PthreadCall("read unlock", pthread_rwlock_unlock(&mu_)); } |
152 | | |
153 | 45.2k | void RWMutex::WriteUnlock() { PthreadCall("write unlock", pthread_rwlock_unlock(&mu_)); } |
154 | | |
155 | 8.03k | int PhysicalCoreID() { |
156 | | #if defined(__i386__) || defined(__x86_64__) |
157 | | // if you ever find that this function is hot on Linux, you can go from |
158 | | // ~200 nanos to ~20 nanos by adding the machinery to use __vdso_getcpu |
159 | | unsigned eax, ebx = 0, ecx, edx; |
160 | | __get_cpuid(1, &eax, &ebx, &ecx, &edx); |
161 | | return ebx >> 24; |
162 | | #else |
163 | | // getcpu or sched_getcpu could work here |
164 | 8.03k | return -1; |
165 | 8.03k | #endif |
166 | 8.03k | } |
167 | | |
168 | 0 | void InitOnce(OnceType* once, void (*initializer)()) { |
169 | 0 | PthreadCall("once", pthread_once(once, initializer)); |
170 | 0 | } |
171 | | |
172 | 0 | void Crash(const std::string& srcfile, int srcline) { |
173 | 0 | fprintf(stdout, "Crashing at %s:%d\n", srcfile.c_str(), srcline); |
174 | 0 | fflush(stdout); |
175 | 0 | kill(getpid(), SIGTERM); |
176 | 0 | } |
177 | | |
178 | 688k | int GetMaxOpenFiles() { |
179 | 688k | #if defined(RLIMIT_NOFILE) |
180 | 688k | struct rlimit no_files_limit; |
181 | 688k | if (getrlimit(RLIMIT_NOFILE, &no_files_limit) != 0) { |
182 | 0 | return -1; |
183 | 0 | } |
184 | | // protect against overflow |
185 | 688k | if (yb::std_util::cmp_greater_equal(no_files_limit.rlim_cur, std::numeric_limits<int>::max())) { |
186 | 0 | return std::numeric_limits<int>::max(); |
187 | 0 | } |
188 | 688k | return static_cast<int>(no_files_limit.rlim_cur); |
189 | 688k | #endif |
190 | 0 | return -1; |
191 | 688k | } |
192 | | |
193 | | } // namespace port |
194 | | } // namespace rocksdb |