1 : /*
2 : * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can be
4 : * found in the LICENSE file.
5 : */
6 :
7 : #include <pthread.h>
8 :
9 : #include "native_client/src/include/nacl_assert.h"
10 : #include "native_client/tests/performance/perf_test_runner.h"
11 :
12 :
13 : // Measure the speed of an (uncontended) atomic operation so that we
14 : // can compare this with TestUncontendedMutexLock.
15 2 : class TestAtomicIncrement : public PerfTest {
16 : public:
17 1 : TestAtomicIncrement() {
18 : // We don't particularly need to initialize var_, but it might
19 : // stop memory checkers from complaining.
20 1 : var_ = 0;
21 1 : }
22 :
23 45538541 : virtual void run() {
24 45538541 : __sync_fetch_and_add(&var_, 1);
25 45538541 : }
26 :
27 : private:
28 : int var_;
29 : };
30 1 : PERF_TEST_DECLARE(TestAtomicIncrement)
31 :
32 : class TestUncontendedMutexLock : public PerfTest {
33 : public:
34 1 : TestUncontendedMutexLock() {
35 1 : ASSERT_EQ(pthread_mutex_init(&mutex_, NULL), 0);
36 1 : }
37 :
38 3 : ~TestUncontendedMutexLock() {
39 1 : ASSERT_EQ(pthread_mutex_destroy(&mutex_), 0);
40 2 : }
41 :
42 15679601 : virtual void run() {
43 15679601 : ASSERT_EQ(pthread_mutex_lock(&mutex_), 0);
44 15679601 : ASSERT_EQ(pthread_mutex_unlock(&mutex_), 0);
45 15679601 : }
46 :
47 : private:
48 : pthread_mutex_t mutex_;
49 : };
50 1 : PERF_TEST_DECLARE(TestUncontendedMutexLock)
51 :
52 : // Test the overhead of pthread_cond_signal() on a condvar that no
53 : // thread is waiting on.
54 : class TestCondvarSignalNoOp : public PerfTest {
55 : public:
56 1 : TestCondvarSignalNoOp() {
57 1 : ASSERT_EQ(pthread_cond_init(&condvar_, NULL), 0);
58 1 : }
59 :
60 3 : ~TestCondvarSignalNoOp() {
61 1 : ASSERT_EQ(pthread_cond_destroy(&condvar_), 0);
62 2 : }
63 :
64 21465031 : virtual void run() {
65 21465031 : ASSERT_EQ(pthread_cond_signal(&condvar_), 0);
66 21465031 : }
67 :
68 : private:
69 : pthread_cond_t condvar_;
70 : };
71 1 : PERF_TEST_DECLARE(TestCondvarSignalNoOp)
72 :
73 3 : class TestThreadCreateAndJoin : public PerfTest {
74 : public:
75 15311 : virtual void run() {
76 : pthread_t tid;
77 15311 : ASSERT_EQ(pthread_create(&tid, NULL, EmptyThread, NULL), 0);
78 15311 : ASSERT_EQ(pthread_join(tid, NULL), 0);
79 15311 : }
80 :
81 : private:
82 15311 : static void *EmptyThread(void *thread_arg) {
83 : UNREFERENCED_PARAMETER(thread_arg);
84 15311 : return NULL;
85 : }
86 : };
87 1 : PERF_TEST_DECLARE(TestThreadCreateAndJoin)
88 :
89 : class TestThreadWakeup : public PerfTest {
90 : public:
91 1 : TestThreadWakeup() {
92 1 : ASSERT_EQ(pthread_mutex_init(&mutex_, NULL), 0);
93 1 : ASSERT_EQ(pthread_cond_init(&condvar1_, NULL), 0);
94 1 : ASSERT_EQ(pthread_cond_init(&condvar2_, NULL), 0);
95 1 : state_ = WAIT;
96 1 : ASSERT_EQ(pthread_create(&tid_, NULL, Thread, this), 0);
97 1 : }
98 :
99 3 : ~TestThreadWakeup() {
100 1 : ASSERT_EQ(pthread_mutex_lock(&mutex_), 0);
101 1 : state_ = EXIT;
102 1 : ASSERT_EQ(pthread_cond_signal(&condvar1_), 0);
103 1 : ASSERT_EQ(pthread_mutex_unlock(&mutex_), 0);
104 :
105 1 : ASSERT_EQ(pthread_join(tid_, NULL), 0);
106 1 : ASSERT_EQ(pthread_cond_destroy(&condvar2_), 0);
107 1 : ASSERT_EQ(pthread_cond_destroy(&condvar1_), 0);
108 1 : ASSERT_EQ(pthread_mutex_destroy(&mutex_), 0);
109 2 : }
110 :
111 17541 : virtual void run() {
112 17541 : ASSERT_EQ(pthread_mutex_lock(&mutex_), 0);
113 17541 : state_ = WAKE_CHILD;
114 17541 : ASSERT_EQ(pthread_cond_signal(&condvar1_), 0);
115 52623 : while (state_ != REPLY_TO_PARENT)
116 17541 : ASSERT_EQ(pthread_cond_wait(&condvar2_, &mutex_), 0);
117 17541 : state_ = WAIT;
118 17541 : ASSERT_EQ(pthread_mutex_unlock(&mutex_), 0);
119 17541 : }
120 :
121 : private:
122 1 : static void *Thread(void *thread_arg) {
123 1 : TestThreadWakeup *obj = (TestThreadWakeup *) thread_arg;
124 1 : bool do_exit = false;
125 17544 : while (!do_exit) {
126 17542 : ASSERT_EQ(pthread_mutex_lock(&obj->mutex_), 0);
127 17537 : for (;;) {
128 35079 : if (obj->state_ == EXIT) {
129 1 : do_exit = true;
130 1 : break;
131 35078 : } else if (obj->state_ == WAKE_CHILD) {
132 17541 : obj->state_ = REPLY_TO_PARENT;
133 17541 : ASSERT_EQ(pthread_cond_signal(&obj->condvar2_), 0);
134 17541 : break;
135 : }
136 17537 : ASSERT_EQ(pthread_cond_wait(&obj->condvar1_, &obj->mutex_), 0);
137 : }
138 17542 : ASSERT_EQ(pthread_mutex_unlock(&obj->mutex_), 0);
139 : }
140 1 : return NULL;
141 : }
142 :
143 : pthread_t tid_;
144 : pthread_mutex_t mutex_;
145 : pthread_cond_t condvar1_;
146 : pthread_cond_t condvar2_;
147 : enum { WAIT, WAKE_CHILD, REPLY_TO_PARENT, EXIT } state_;
148 : };
149 1 : PERF_TEST_DECLARE(TestThreadWakeup)
|