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
BM_pthread_mutex_lock_ERRORCHECK(benchmark::State & state)78 static void BM_pthread_mutex_lock_ERRORCHECK(benchmark::State& state) {
79 pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
80
81 while (state.KeepRunning()) {
82 pthread_mutex_lock(&mutex);
83 pthread_mutex_unlock(&mutex);
84 }
85 }
86 BIONIC_BENCHMARK(BM_pthread_mutex_lock_ERRORCHECK);
87
BM_pthread_mutex_lock_RECURSIVE(benchmark::State & state)88 static void BM_pthread_mutex_lock_RECURSIVE(benchmark::State& state) {
89 pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
90
91 while (state.KeepRunning()) {
92 pthread_mutex_lock(&mutex);
93 pthread_mutex_unlock(&mutex);
94 }
95 }
96 BIONIC_BENCHMARK(BM_pthread_mutex_lock_RECURSIVE);
97
98 namespace {
99 struct PIMutex {
100 pthread_mutex_t mutex;
101
PIMutex__anon218be1320111::PIMutex102 explicit PIMutex(int type) {
103 pthread_mutexattr_t attr;
104 pthread_mutexattr_init(&attr);
105 pthread_mutexattr_settype(&attr, type);
106 pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
107 pthread_mutex_init(&mutex, &attr);
108 pthread_mutexattr_destroy(&attr);
109 }
110
~PIMutex__anon218be1320111::PIMutex111 ~PIMutex() {
112 pthread_mutex_destroy(&mutex);
113 }
114 };
115 }
116
BM_pthread_mutex_lock_PI(benchmark::State & state)117 static void BM_pthread_mutex_lock_PI(benchmark::State& state) {
118 PIMutex m(PTHREAD_MUTEX_NORMAL);
119
120 while (state.KeepRunning()) {
121 pthread_mutex_lock(&m.mutex);
122 pthread_mutex_unlock(&m.mutex);
123 }
124 }
125 BIONIC_BENCHMARK(BM_pthread_mutex_lock_PI);
126
BM_pthread_mutex_lock_ERRORCHECK_PI(benchmark::State & state)127 static void BM_pthread_mutex_lock_ERRORCHECK_PI(benchmark::State& state) {
128 PIMutex m(PTHREAD_MUTEX_ERRORCHECK);
129
130 while (state.KeepRunning()) {
131 pthread_mutex_lock(&m.mutex);
132 pthread_mutex_unlock(&m.mutex);
133 }
134 }
135 BIONIC_BENCHMARK(BM_pthread_mutex_lock_ERRORCHECK_PI);
136
BM_pthread_mutex_lock_RECURSIVE_PI(benchmark::State & state)137 static void BM_pthread_mutex_lock_RECURSIVE_PI(benchmark::State& state) {
138 PIMutex m(PTHREAD_MUTEX_RECURSIVE);
139
140 while (state.KeepRunning()) {
141 pthread_mutex_lock(&m.mutex);
142 pthread_mutex_unlock(&m.mutex);
143 }
144 }
145 BIONIC_BENCHMARK(BM_pthread_mutex_lock_RECURSIVE_PI);
146
BM_pthread_rwlock_read(benchmark::State & state)147 static void BM_pthread_rwlock_read(benchmark::State& state) {
148 pthread_rwlock_t lock;
149 pthread_rwlock_init(&lock, nullptr);
150
151 while (state.KeepRunning()) {
152 pthread_rwlock_rdlock(&lock);
153 pthread_rwlock_unlock(&lock);
154 }
155
156 pthread_rwlock_destroy(&lock);
157 }
158 BIONIC_BENCHMARK(BM_pthread_rwlock_read);
159
BM_pthread_rwlock_write(benchmark::State & state)160 static void BM_pthread_rwlock_write(benchmark::State& state) {
161 pthread_rwlock_t lock;
162 pthread_rwlock_init(&lock, nullptr);
163
164 while (state.KeepRunning()) {
165 pthread_rwlock_wrlock(&lock);
166 pthread_rwlock_unlock(&lock);
167 }
168
169 pthread_rwlock_destroy(&lock);
170 }
171 BIONIC_BENCHMARK(BM_pthread_rwlock_write);
172
IdleThread(void *)173 static void* IdleThread(void*) {
174 return nullptr;
175 }
176
BM_pthread_create(benchmark::State & state)177 static void BM_pthread_create(benchmark::State& state) {
178 while (state.KeepRunning()) {
179 pthread_t thread;
180 pthread_create(&thread, nullptr, IdleThread, nullptr);
181 state.PauseTiming();
182 pthread_join(thread, nullptr);
183 state.ResumeTiming();
184 }
185 }
186 BIONIC_BENCHMARK(BM_pthread_create);
187
RunThread(void *)188 static void* RunThread(void*) {
189 return nullptr;
190 }
191
BM_pthread_create_and_run(benchmark::State & state)192 static void BM_pthread_create_and_run(benchmark::State& state) {
193 while (state.KeepRunning()) {
194 pthread_t thread;
195 pthread_create(&thread, nullptr, RunThread, &state);
196 pthread_join(thread, nullptr);
197 }
198 }
199 BIONIC_BENCHMARK(BM_pthread_create_and_run);
200
ExitThread(void *)201 static void* ExitThread(void*) {
202 pthread_exit(nullptr);
203 }
204
BM_pthread_exit_and_join(benchmark::State & state)205 static void BM_pthread_exit_and_join(benchmark::State& state) {
206 while (state.KeepRunning()) {
207 pthread_t thread;
208 pthread_create(&thread, nullptr, ExitThread, nullptr);
209 pthread_join(thread, nullptr);
210 }
211 }
212 BIONIC_BENCHMARK(BM_pthread_exit_and_join);
213
BM_pthread_key_create(benchmark::State & state)214 static void BM_pthread_key_create(benchmark::State& state) {
215 while (state.KeepRunning()) {
216 pthread_key_t key;
217 pthread_key_create(&key, nullptr);
218
219 state.PauseTiming();
220 pthread_key_delete(key);
221 state.ResumeTiming();
222 }
223 }
224 BIONIC_BENCHMARK(BM_pthread_key_create);
225
BM_pthread_key_delete(benchmark::State & state)226 static void BM_pthread_key_delete(benchmark::State& state) {
227 while (state.KeepRunning()) {
228 state.PauseTiming();
229 pthread_key_t key;
230 pthread_key_create(&key, nullptr);
231 state.ResumeTiming();
232
233 pthread_key_delete(key);
234 }
235 }
236 BIONIC_BENCHMARK(BM_pthread_key_delete);
237