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 4 : 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 2 : }
22 :
23 : virtual void run() {
24 43914776 : __sync_fetch_and_add(&var_, 1);
25 43914776 : }
26 :
27 : private:
28 : int var_;
29 : };
30 2 : PERF_TEST_DECLARE(TestAtomicIncrement)
31 :
32 : class TestUncontendedMutexLock : public PerfTest {
33 : public:
34 1 : TestUncontendedMutexLock() {
35 5 : ASSERT_EQ(pthread_mutex_init(&mutex_, NULL), 0);
36 2 : }
37 :
38 4 : ~TestUncontendedMutexLock() {
39 5 : ASSERT_EQ(pthread_mutex_destroy(&mutex_), 0);
40 3 : }
41 :
42 : virtual void run() {
43 44151108 : ASSERT_EQ(pthread_mutex_lock(&mutex_), 0);
44 44151108 : ASSERT_EQ(pthread_mutex_unlock(&mutex_), 0);
45 14717036 : }
46 :
47 : private:
48 : pthread_mutex_t mutex_;
49 : };
50 2 : 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 5 : ASSERT_EQ(pthread_cond_init(&condvar_, NULL), 0);
58 2 : }
59 :
60 4 : ~TestCondvarSignalNoOp() {
61 5 : ASSERT_EQ(pthread_cond_destroy(&condvar_), 0);
62 3 : }
63 :
64 : virtual void run() {
65 80480013 : ASSERT_EQ(pthread_cond_signal(&condvar_), 0);
66 26826671 : }
67 :
68 : private:
69 : pthread_cond_t condvar_;
70 : };
71 2 : PERF_TEST_DECLARE(TestCondvarSignalNoOp)
72 :
73 6 : class TestThreadCreateAndJoin : public PerfTest {
74 : public:
75 : virtual void run() {
76 7806 : pthread_t tid;
77 23418 : ASSERT_EQ(pthread_create(&tid, NULL, EmptyThread, NULL), 0);
78 23418 : ASSERT_EQ(pthread_join(tid, NULL), 0);
79 7806 : }
80 :
81 : private:
82 7806 : static void *EmptyThread(void *thread_arg) {
83 15612 : UNREFERENCED_PARAMETER(thread_arg);
84 7806 : return NULL;
85 : }
86 : };
87 1 : PERF_TEST_DECLARE(TestThreadCreateAndJoin)
88 :
89 : class TestThreadWakeup : public PerfTest {
90 : public:
91 1 : TestThreadWakeup() {
92 5 : ASSERT_EQ(pthread_mutex_init(&mutex_, NULL), 0);
93 5 : ASSERT_EQ(pthread_cond_init(&condvar1_, NULL), 0);
94 5 : ASSERT_EQ(pthread_cond_init(&condvar2_, NULL), 0);
95 1 : state_ = WAIT;
96 5 : ASSERT_EQ(pthread_create(&tid_, NULL, Thread, this), 0);
97 2 : }
98 :
99 4 : ~TestThreadWakeup() {
100 5 : ASSERT_EQ(pthread_mutex_lock(&mutex_), 0);
101 1 : state_ = EXIT;
102 5 : ASSERT_EQ(pthread_cond_signal(&condvar1_), 0);
103 5 : ASSERT_EQ(pthread_mutex_unlock(&mutex_), 0);
104 :
105 5 : ASSERT_EQ(pthread_join(tid_, NULL), 0);
106 5 : ASSERT_EQ(pthread_cond_destroy(&condvar2_), 0);
107 5 : ASSERT_EQ(pthread_cond_destroy(&condvar1_), 0);
108 5 : ASSERT_EQ(pthread_mutex_destroy(&mutex_), 0);
109 3 : }
110 :
111 : virtual void run() {
112 72453 : ASSERT_EQ(pthread_mutex_lock(&mutex_), 0);
113 24151 : state_ = WAKE_CHILD;
114 72453 : ASSERT_EQ(pthread_cond_signal(&condvar1_), 0);
115 72453 : while (state_ != REPLY_TO_PARENT)
116 96604 : ASSERT_EQ(pthread_cond_wait(&condvar2_, &mutex_), 0);
117 24151 : state_ = WAIT;
118 72453 : ASSERT_EQ(pthread_mutex_unlock(&mutex_), 0);
119 24151 : }
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 24154 : while (!do_exit) {
126 72456 : ASSERT_EQ(pthread_mutex_lock(&obj->mutex_), 0);
127 24152 : for (;;) {
128 48303 : if (obj->state_ == EXIT) {
129 1 : do_exit = true;
130 1 : break;
131 48302 : } else if (obj->state_ == WAKE_CHILD) {
132 24151 : obj->state_ = REPLY_TO_PARENT;
133 72453 : ASSERT_EQ(pthread_cond_signal(&obj->condvar2_), 0);
134 24151 : break;
135 : }
136 72453 : ASSERT_EQ(pthread_cond_wait(&obj->condvar1_, &obj->mutex_), 0);
137 24151 : }
138 72456 : ASSERT_EQ(pthread_mutex_unlock(&obj->mutex_), 0);
139 24152 : }
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 2 : PERF_TEST_DECLARE(TestThreadWakeup)
|