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
25static void BM_pthread_self(benchmark::State& state) {
26  while (state.KeepRunning()) {
27    pthread_self_fp();
28  }
29}
30BIONIC_BENCHMARK(BM_pthread_self);
31
32static 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}
42BIONIC_BENCHMARK(BM_pthread_getspecific);
43
44static 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}
54BIONIC_BENCHMARK(BM_pthread_setspecific);
55
56static void DummyPthreadOnceInitFunction() {
57}
58
59static 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}
67BIONIC_BENCHMARK(BM_pthread_once);
68
69static 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}
77BIONIC_BENCHMARK(BM_pthread_mutex_lock);
78
79static 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}
87BIONIC_BENCHMARK(BM_pthread_mutex_lock_ERRORCHECK);
88
89static 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}
97BIONIC_BENCHMARK(BM_pthread_mutex_lock_RECURSIVE);
98
99namespace {
100struct PIMutex {
101  pthread_mutex_t mutex;
102
103  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
112  ~PIMutex() {
113    pthread_mutex_destroy(&mutex);
114  }
115};
116}
117
118static 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}
126BIONIC_BENCHMARK(BM_pthread_mutex_lock_PI);
127
128static 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}
136BIONIC_BENCHMARK(BM_pthread_mutex_lock_ERRORCHECK_PI);
137
138static 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}
146BIONIC_BENCHMARK(BM_pthread_mutex_lock_RECURSIVE_PI);
147
148static 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}
159BIONIC_BENCHMARK(BM_pthread_rwlock_read);
160
161static 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}
172BIONIC_BENCHMARK(BM_pthread_rwlock_write);
173
174static void* IdleThread(void*) {
175  return NULL;
176}
177
178static 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}
187BIONIC_BENCHMARK(BM_pthread_create);
188
189static void* RunThread(void*) {
190  return NULL;
191}
192
193static 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}
200BIONIC_BENCHMARK(BM_pthread_create_and_run);
201
202static void* ExitThread(void*) {
203  pthread_exit(NULL);
204}
205
206static 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}
213BIONIC_BENCHMARK(BM_pthread_exit_and_join);
214
215static 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}
225BIONIC_BENCHMARK(BM_pthread_key_create);
226
227static 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}
237BIONIC_BENCHMARK(BM_pthread_key_delete);
238