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
21// Stop GCC optimizing out our pure function.
22/* Must not be static! */ pthread_t (*pthread_self_fp)() = pthread_self;
23
24static void BM_pthread_self(benchmark::State& state) {
25  while (state.KeepRunning()) {
26    pthread_self_fp();
27  }
28}
29BENCHMARK(BM_pthread_self);
30
31static void BM_pthread_getspecific(benchmark::State& state) {
32  pthread_key_t key;
33  pthread_key_create(&key, NULL);
34
35  while (state.KeepRunning()) {
36    pthread_getspecific(key);
37  }
38
39  pthread_key_delete(key);
40}
41BENCHMARK(BM_pthread_getspecific);
42
43static void BM_pthread_setspecific(benchmark::State& state) {
44  pthread_key_t key;
45  pthread_key_create(&key, NULL);
46
47  while (state.KeepRunning()) {
48    pthread_setspecific(key, NULL);
49  }
50
51  pthread_key_delete(key);
52}
53BENCHMARK(BM_pthread_setspecific);
54
55static void DummyPthreadOnceInitFunction() {
56}
57
58static void BM_pthread_once(benchmark::State& state) {
59  pthread_once_t once = PTHREAD_ONCE_INIT;
60  pthread_once(&once, DummyPthreadOnceInitFunction);
61
62  while (state.KeepRunning()) {
63    pthread_once(&once, DummyPthreadOnceInitFunction);
64  }
65}
66BENCHMARK(BM_pthread_once);
67
68static 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}
76BENCHMARK(BM_pthread_mutex_lock);
77
78static 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}
86BENCHMARK(BM_pthread_mutex_lock_ERRORCHECK);
87
88static 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}
96BENCHMARK(BM_pthread_mutex_lock_RECURSIVE);
97
98static void BM_pthread_rwlock_read(benchmark::State& state) {
99  pthread_rwlock_t lock;
100  pthread_rwlock_init(&lock, NULL);
101
102  while (state.KeepRunning()) {
103    pthread_rwlock_rdlock(&lock);
104    pthread_rwlock_unlock(&lock);
105  }
106
107  pthread_rwlock_destroy(&lock);
108}
109BENCHMARK(BM_pthread_rwlock_read);
110
111static void BM_pthread_rwlock_write(benchmark::State& state) {
112  pthread_rwlock_t lock;
113  pthread_rwlock_init(&lock, NULL);
114
115  while (state.KeepRunning()) {
116    pthread_rwlock_wrlock(&lock);
117    pthread_rwlock_unlock(&lock);
118  }
119
120  pthread_rwlock_destroy(&lock);
121}
122BENCHMARK(BM_pthread_rwlock_write);
123
124static void* IdleThread(void*) {
125  return NULL;
126}
127
128static void BM_pthread_create(benchmark::State& state) {
129  while (state.KeepRunning()) {
130    pthread_t thread;
131    pthread_create(&thread, NULL, IdleThread, NULL);
132    state.PauseTiming();
133    pthread_join(thread, NULL);
134    state.ResumeTiming();
135  }
136}
137BENCHMARK(BM_pthread_create);
138
139static void* RunThread(void* arg) {
140  benchmark::State& state = *reinterpret_cast<benchmark::State*>(arg);
141  state.PauseTiming();
142  return NULL;
143}
144
145static void BM_pthread_create_and_run(benchmark::State& state) {
146  while (state.KeepRunning()) {
147    pthread_t thread;
148    pthread_create(&thread, NULL, RunThread, &state);
149    pthread_join(thread, NULL);
150    state.ResumeTiming();
151  }
152}
153BENCHMARK(BM_pthread_create_and_run);
154
155static void* ExitThread(void* arg) {
156  benchmark::State& state = *reinterpret_cast<benchmark::State*>(arg);
157  state.ResumeTiming();
158  pthread_exit(NULL);
159}
160
161static void BM_pthread_exit_and_join(benchmark::State& state) {
162  while (state.KeepRunning()) {
163    state.PauseTiming();
164    pthread_t thread;
165    pthread_create(&thread, NULL, ExitThread, &state);
166    pthread_join(thread, NULL);
167  }
168}
169BENCHMARK(BM_pthread_exit_and_join);
170
171static void BM_pthread_key_create(benchmark::State& state) {
172  while (state.KeepRunning()) {
173    pthread_key_t key;
174    pthread_key_create(&key, NULL);
175
176    state.PauseTiming();
177    pthread_key_delete(key);
178    state.ResumeTiming();
179  }
180}
181BENCHMARK(BM_pthread_key_create);
182
183static void BM_pthread_key_delete(benchmark::State& state) {
184  while (state.KeepRunning()) {
185    state.PauseTiming();
186    pthread_key_t key;
187    pthread_key_create(&key, NULL);
188    state.ResumeTiming();
189
190    pthread_key_delete(key);
191  }
192}
193BENCHMARK(BM_pthread_key_delete);
194