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