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 
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__anon218be1320111::PIMutex103   explicit 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__anon218be1320111::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, nullptr);
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, nullptr);
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 nullptr;
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, nullptr, IdleThread, nullptr);
182     state.PauseTiming();
183     pthread_join(thread, nullptr);
184     state.ResumeTiming();
185   }
186 }
187 BIONIC_BENCHMARK(BM_pthread_create);
188 
RunThread(void *)189 static void* RunThread(void*) {
190   return nullptr;
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, nullptr, RunThread, &state);
197     pthread_join(thread, nullptr);
198   }
199 }
200 BIONIC_BENCHMARK(BM_pthread_create_and_run);
201 
ExitThread(void *)202 static void* ExitThread(void*) {
203   pthread_exit(nullptr);
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, nullptr, ExitThread, nullptr);
210     pthread_join(thread, nullptr);
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, nullptr);
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, nullptr);
232     state.ResumeTiming();
233 
234     pthread_key_delete(key);
235   }
236 }
237 BIONIC_BENCHMARK(BM_pthread_key_delete);
238