1 /*
2 * Copyright (C) 2014 The Android Open Source Project
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 <pthread.h>
18
19 #include <benchmark/benchmark.h>
20 #include "util.h"
21
22 // Stop GCC optimizing out our pure function.
23 /* Must not be static! */ pthread_t (*pthread_self_fp)() = pthread_self;
24
BM_pthread_self(benchmark::State & state)25 static void BM_pthread_self(benchmark::State& state) {
26 while (state.KeepRunning()) {
27 pthread_self_fp();
28 }
29 }
30 BIONIC_BENCHMARK(BM_pthread_self);
31
BM_pthread_getspecific(benchmark::State & state)32 static void BM_pthread_getspecific(benchmark::State& state) {
33 pthread_key_t key;
34 pthread_key_create(&key, nullptr);
35
36 while (state.KeepRunning()) {
37 pthread_getspecific(key);
38 }
39
40 pthread_key_delete(key);
41 }
42 BIONIC_BENCHMARK(BM_pthread_getspecific);
43
BM_pthread_setspecific(benchmark::State & state)44 static void BM_pthread_setspecific(benchmark::State& state) {
45 pthread_key_t key;
46 pthread_key_create(&key, nullptr);
47
48 while (state.KeepRunning()) {
49 pthread_setspecific(key, nullptr);
50 }
51
52 pthread_key_delete(key);
53 }
54 BIONIC_BENCHMARK(BM_pthread_setspecific);
55
NoOpPthreadOnceInitFunction()56 static void NoOpPthreadOnceInitFunction() {}
57
BM_pthread_once(benchmark::State & state)58 static void BM_pthread_once(benchmark::State& state) {
59 static pthread_once_t once = PTHREAD_ONCE_INIT;
60 pthread_once(&once, NoOpPthreadOnceInitFunction);
61
62 while (state.KeepRunning()) {
63 pthread_once(&once, NoOpPthreadOnceInitFunction);
64 }
65 }
66 BIONIC_BENCHMARK(BM_pthread_once);
67
BM_pthread_mutex_lock(benchmark::State & state)68 static void BM_pthread_mutex_lock(benchmark::State& state) {
69 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
70
71 while (state.KeepRunning()) {
72 pthread_mutex_lock(&mutex);
73 pthread_mutex_unlock(&mutex);
74 }
75 }
76 BIONIC_BENCHMARK(BM_pthread_mutex_lock);
77
78 #if !defined(ANDROID_HOST_MUSL)
BM_pthread_mutex_lock_ERRORCHECK(benchmark::State & state)79 static void BM_pthread_mutex_lock_ERRORCHECK(benchmark::State& state) {
80 pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
81
82 while (state.KeepRunning()) {
83 pthread_mutex_lock(&mutex);
84 pthread_mutex_unlock(&mutex);
85 }
86 }
87 BIONIC_BENCHMARK(BM_pthread_mutex_lock_ERRORCHECK);
88 #endif
89
90 #if !defined(ANDROID_HOST_MUSL)
BM_pthread_mutex_lock_RECURSIVE(benchmark::State & state)91 static void BM_pthread_mutex_lock_RECURSIVE(benchmark::State& state) {
92 pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
93
94 while (state.KeepRunning()) {
95 pthread_mutex_lock(&mutex);
96 pthread_mutex_unlock(&mutex);
97 }
98 }
99 BIONIC_BENCHMARK(BM_pthread_mutex_lock_RECURSIVE);
100 #endif
101
102 namespace {
103 struct PIMutex {
104 pthread_mutex_t mutex;
105
PIMutex__anon5e5547460111::PIMutex106 explicit PIMutex(int type) {
107 pthread_mutexattr_t attr;
108 pthread_mutexattr_init(&attr);
109 pthread_mutexattr_settype(&attr, type);
110 pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
111 pthread_mutex_init(&mutex, &attr);
112 pthread_mutexattr_destroy(&attr);
113 }
114
~PIMutex__anon5e5547460111::PIMutex115 ~PIMutex() {
116 pthread_mutex_destroy(&mutex);
117 }
118 };
119 }
120
BM_pthread_mutex_lock_PI(benchmark::State & state)121 static void BM_pthread_mutex_lock_PI(benchmark::State& state) {
122 PIMutex m(PTHREAD_MUTEX_NORMAL);
123
124 while (state.KeepRunning()) {
125 pthread_mutex_lock(&m.mutex);
126 pthread_mutex_unlock(&m.mutex);
127 }
128 }
129 BIONIC_BENCHMARK(BM_pthread_mutex_lock_PI);
130
BM_pthread_mutex_lock_ERRORCHECK_PI(benchmark::State & state)131 static void BM_pthread_mutex_lock_ERRORCHECK_PI(benchmark::State& state) {
132 PIMutex m(PTHREAD_MUTEX_ERRORCHECK);
133
134 while (state.KeepRunning()) {
135 pthread_mutex_lock(&m.mutex);
136 pthread_mutex_unlock(&m.mutex);
137 }
138 }
139 BIONIC_BENCHMARK(BM_pthread_mutex_lock_ERRORCHECK_PI);
140
BM_pthread_mutex_lock_RECURSIVE_PI(benchmark::State & state)141 static void BM_pthread_mutex_lock_RECURSIVE_PI(benchmark::State& state) {
142 PIMutex m(PTHREAD_MUTEX_RECURSIVE);
143
144 while (state.KeepRunning()) {
145 pthread_mutex_lock(&m.mutex);
146 pthread_mutex_unlock(&m.mutex);
147 }
148 }
149 BIONIC_BENCHMARK(BM_pthread_mutex_lock_RECURSIVE_PI);
150
BM_pthread_rwlock_read(benchmark::State & state)151 static void BM_pthread_rwlock_read(benchmark::State& state) {
152 pthread_rwlock_t lock;
153 pthread_rwlock_init(&lock, nullptr);
154
155 while (state.KeepRunning()) {
156 pthread_rwlock_rdlock(&lock);
157 pthread_rwlock_unlock(&lock);
158 }
159
160 pthread_rwlock_destroy(&lock);
161 }
162 BIONIC_BENCHMARK(BM_pthread_rwlock_read);
163
BM_pthread_rwlock_write(benchmark::State & state)164 static void BM_pthread_rwlock_write(benchmark::State& state) {
165 pthread_rwlock_t lock;
166 pthread_rwlock_init(&lock, nullptr);
167
168 while (state.KeepRunning()) {
169 pthread_rwlock_wrlock(&lock);
170 pthread_rwlock_unlock(&lock);
171 }
172
173 pthread_rwlock_destroy(&lock);
174 }
175 BIONIC_BENCHMARK(BM_pthread_rwlock_write);
176
IdleThread(void *)177 static void* IdleThread(void*) {
178 return nullptr;
179 }
180
BM_pthread_create(benchmark::State & state)181 static void BM_pthread_create(benchmark::State& state) {
182 while (state.KeepRunning()) {
183 pthread_t thread;
184 pthread_create(&thread, nullptr, IdleThread, nullptr);
185 state.PauseTiming();
186 pthread_join(thread, nullptr);
187 state.ResumeTiming();
188 }
189 }
190 BIONIC_BENCHMARK(BM_pthread_create);
191
RunThread(void *)192 static void* RunThread(void*) {
193 return nullptr;
194 }
195
BM_pthread_create_and_run(benchmark::State & state)196 static void BM_pthread_create_and_run(benchmark::State& state) {
197 while (state.KeepRunning()) {
198 pthread_t thread;
199 pthread_create(&thread, nullptr, RunThread, &state);
200 pthread_join(thread, nullptr);
201 }
202 }
203 BIONIC_BENCHMARK(BM_pthread_create_and_run);
204
ExitThread(void *)205 static void* ExitThread(void*) {
206 pthread_exit(nullptr);
207 }
208
BM_pthread_exit_and_join(benchmark::State & state)209 static void BM_pthread_exit_and_join(benchmark::State& state) {
210 while (state.KeepRunning()) {
211 pthread_t thread;
212 pthread_create(&thread, nullptr, ExitThread, nullptr);
213 pthread_join(thread, nullptr);
214 }
215 }
216 BIONIC_BENCHMARK(BM_pthread_exit_and_join);
217
BM_pthread_key_create(benchmark::State & state)218 static void BM_pthread_key_create(benchmark::State& state) {
219 while (state.KeepRunning()) {
220 pthread_key_t key;
221 pthread_key_create(&key, nullptr);
222
223 state.PauseTiming();
224 pthread_key_delete(key);
225 state.ResumeTiming();
226 }
227 }
228 BIONIC_BENCHMARK(BM_pthread_key_create);
229
BM_pthread_key_delete(benchmark::State & state)230 static void BM_pthread_key_delete(benchmark::State& state) {
231 while (state.KeepRunning()) {
232 state.PauseTiming();
233 pthread_key_t key;
234 pthread_key_create(&key, nullptr);
235 state.ResumeTiming();
236
237 pthread_key_delete(key);
238 }
239 }
240 BIONIC_BENCHMARK(BM_pthread_key_delete);
241