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, NULL);
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, NULL);
47
48 while (state.KeepRunning()) {
49 pthread_setspecific(key, NULL);
50 }
51
52 pthread_key_delete(key);
53 }
54 BIONIC_BENCHMARK(BM_pthread_setspecific);
55
DummyPthreadOnceInitFunction()56 static void DummyPthreadOnceInitFunction() {
57 }
58
BM_pthread_once(benchmark::State & state)59 static void BM_pthread_once(benchmark::State& state) {
60 static pthread_once_t once = PTHREAD_ONCE_INIT;
61 pthread_once(&once, DummyPthreadOnceInitFunction);
62
63 while (state.KeepRunning()) {
64 pthread_once(&once, DummyPthreadOnceInitFunction);
65 }
66 }
67 BIONIC_BENCHMARK(BM_pthread_once);
68
BM_pthread_mutex_lock(benchmark::State & state)69 static void BM_pthread_mutex_lock(benchmark::State& state) {
70 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
71
72 while (state.KeepRunning()) {
73 pthread_mutex_lock(&mutex);
74 pthread_mutex_unlock(&mutex);
75 }
76 }
77 BIONIC_BENCHMARK(BM_pthread_mutex_lock);
78
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
BM_pthread_mutex_lock_RECURSIVE(benchmark::State & state)89 static void BM_pthread_mutex_lock_RECURSIVE(benchmark::State& state) {
90 pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
91
92 while (state.KeepRunning()) {
93 pthread_mutex_lock(&mutex);
94 pthread_mutex_unlock(&mutex);
95 }
96 }
97 BIONIC_BENCHMARK(BM_pthread_mutex_lock_RECURSIVE);
98
99 namespace {
100 struct PIMutex {
101 pthread_mutex_t mutex;
102
PIMutex__anon5024424f0111::PIMutex103 PIMutex(int type) {
104 pthread_mutexattr_t attr;
105 pthread_mutexattr_init(&attr);
106 pthread_mutexattr_settype(&attr, type);
107 pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
108 pthread_mutex_init(&mutex, &attr);
109 pthread_mutexattr_destroy(&attr);
110 }
111
~PIMutex__anon5024424f0111::PIMutex112 ~PIMutex() {
113 pthread_mutex_destroy(&mutex);
114 }
115 };
116 }
117
BM_pthread_mutex_lock_PI(benchmark::State & state)118 static void BM_pthread_mutex_lock_PI(benchmark::State& state) {
119 PIMutex m(PTHREAD_MUTEX_NORMAL);
120
121 while (state.KeepRunning()) {
122 pthread_mutex_lock(&m.mutex);
123 pthread_mutex_unlock(&m.mutex);
124 }
125 }
126 BIONIC_BENCHMARK(BM_pthread_mutex_lock_PI);
127
BM_pthread_mutex_lock_ERRORCHECK_PI(benchmark::State & state)128 static void BM_pthread_mutex_lock_ERRORCHECK_PI(benchmark::State& state) {
129 PIMutex m(PTHREAD_MUTEX_ERRORCHECK);
130
131 while (state.KeepRunning()) {
132 pthread_mutex_lock(&m.mutex);
133 pthread_mutex_unlock(&m.mutex);
134 }
135 }
136 BIONIC_BENCHMARK(BM_pthread_mutex_lock_ERRORCHECK_PI);
137
BM_pthread_mutex_lock_RECURSIVE_PI(benchmark::State & state)138 static void BM_pthread_mutex_lock_RECURSIVE_PI(benchmark::State& state) {
139 PIMutex m(PTHREAD_MUTEX_RECURSIVE);
140
141 while (state.KeepRunning()) {
142 pthread_mutex_lock(&m.mutex);
143 pthread_mutex_unlock(&m.mutex);
144 }
145 }
146 BIONIC_BENCHMARK(BM_pthread_mutex_lock_RECURSIVE_PI);
147
BM_pthread_rwlock_read(benchmark::State & state)148 static void BM_pthread_rwlock_read(benchmark::State& state) {
149 pthread_rwlock_t lock;
150 pthread_rwlock_init(&lock, NULL);
151
152 while (state.KeepRunning()) {
153 pthread_rwlock_rdlock(&lock);
154 pthread_rwlock_unlock(&lock);
155 }
156
157 pthread_rwlock_destroy(&lock);
158 }
159 BIONIC_BENCHMARK(BM_pthread_rwlock_read);
160
BM_pthread_rwlock_write(benchmark::State & state)161 static void BM_pthread_rwlock_write(benchmark::State& state) {
162 pthread_rwlock_t lock;
163 pthread_rwlock_init(&lock, NULL);
164
165 while (state.KeepRunning()) {
166 pthread_rwlock_wrlock(&lock);
167 pthread_rwlock_unlock(&lock);
168 }
169
170 pthread_rwlock_destroy(&lock);
171 }
172 BIONIC_BENCHMARK(BM_pthread_rwlock_write);
173
IdleThread(void *)174 static void* IdleThread(void*) {
175 return NULL;
176 }
177
BM_pthread_create(benchmark::State & state)178 static void BM_pthread_create(benchmark::State& state) {
179 while (state.KeepRunning()) {
180 pthread_t thread;
181 pthread_create(&thread, NULL, IdleThread, NULL);
182 state.PauseTiming();
183 pthread_join(thread, NULL);
184 state.ResumeTiming();
185 }
186 }
187 BIONIC_BENCHMARK(BM_pthread_create);
188
RunThread(void *)189 static void* RunThread(void*) {
190 return NULL;
191 }
192
BM_pthread_create_and_run(benchmark::State & state)193 static void BM_pthread_create_and_run(benchmark::State& state) {
194 while (state.KeepRunning()) {
195 pthread_t thread;
196 pthread_create(&thread, NULL, RunThread, &state);
197 pthread_join(thread, NULL);
198 }
199 }
200 BIONIC_BENCHMARK(BM_pthread_create_and_run);
201
ExitThread(void *)202 static void* ExitThread(void*) {
203 pthread_exit(NULL);
204 }
205
BM_pthread_exit_and_join(benchmark::State & state)206 static void BM_pthread_exit_and_join(benchmark::State& state) {
207 while (state.KeepRunning()) {
208 pthread_t thread;
209 pthread_create(&thread, NULL, ExitThread, nullptr);
210 pthread_join(thread, NULL);
211 }
212 }
213 BIONIC_BENCHMARK(BM_pthread_exit_and_join);
214
BM_pthread_key_create(benchmark::State & state)215 static void BM_pthread_key_create(benchmark::State& state) {
216 while (state.KeepRunning()) {
217 pthread_key_t key;
218 pthread_key_create(&key, NULL);
219
220 state.PauseTiming();
221 pthread_key_delete(key);
222 state.ResumeTiming();
223 }
224 }
225 BIONIC_BENCHMARK(BM_pthread_key_create);
226
BM_pthread_key_delete(benchmark::State & state)227 static void BM_pthread_key_delete(benchmark::State& state) {
228 while (state.KeepRunning()) {
229 state.PauseTiming();
230 pthread_key_t key;
231 pthread_key_create(&key, NULL);
232 state.ResumeTiming();
233
234 pthread_key_delete(key);
235 }
236 }
237 BIONIC_BENCHMARK(BM_pthread_key_delete);
238