Bug 548621 - Create suite of tests for JS parsing speed. r=jorendorff.
[mozilla-central.git] / xpcom / tests / TestSynchronization.cpp
blob1f5b6b02140e7fefa8e6489625b4fe244053848e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: sw=4 ts=4 et :
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is mozilla.org code.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 1998
21 * the Initial Developer. All Rights Reserved.
23 * Contributor(s):
24 * Chris Jones <jones.chris.g@gmail.com>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #include "TestHarness.h"
42 #include "mozilla/CondVar.h"
43 #include "mozilla/Monitor.h"
44 #include "mozilla/Mutex.h"
45 #include "nsAutoLock.h"
47 using namespace mozilla;
49 static PRThread*
50 spawn(void (*run)(void*), void* arg)
52 return PR_CreateThread(PR_SYSTEM_THREAD,
53 run,
54 arg,
55 PR_PRIORITY_NORMAL,
56 PR_GLOBAL_THREAD,
57 PR_JOINABLE_THREAD,
58 0);
62 #define PASS() \
63 do { \
64 passed(__FUNCTION__); \
65 return NS_OK; \
66 } while (0);
69 #define FAIL(why) \
70 do { \
71 fail(why); \
72 return NS_ERROR_FAILURE; \
73 } while (0);
75 //-----------------------------------------------------------------------------
76 // Sanity check: tests that can be done on a single thread
78 static nsresult
79 Sanity()
81 Mutex lock("sanity::lock");
82 lock.Lock();
83 lock.AssertCurrentThreadOwns();
84 lock.Unlock();
87 MutexAutoLock autolock(lock);
88 lock.AssertCurrentThreadOwns();
91 lock.Lock();
92 lock.AssertCurrentThreadOwns();
94 MutexAutoUnlock autounlock(lock);
96 lock.AssertCurrentThreadOwns();
97 lock.Unlock();
99 Monitor mon("sanity::monitor");
100 mon.Enter();
101 mon.AssertCurrentThreadIn();
102 mon.Enter();
103 mon.AssertCurrentThreadIn();
104 mon.Exit();
105 mon.AssertCurrentThreadIn();
106 mon.Exit();
109 MonitorAutoEnter automon(mon);
110 mon.AssertCurrentThreadIn();
113 PASS();
116 //-----------------------------------------------------------------------------
117 // Mutex contention tests
119 static Mutex* gLock1;
121 static void
122 MutexContention_thread(void* /*arg*/)
124 for (int i = 0; i < 100000; ++i) {
125 gLock1->Lock();
126 gLock1->AssertCurrentThreadOwns();
127 gLock1->Unlock();
131 static nsresult
132 MutexContention()
134 gLock1 = new Mutex("lock1");
135 // PURPOSELY not checking for OOM. YAY!
137 PRThread* t1 = spawn(MutexContention_thread, nsnull);
138 PRThread* t2 = spawn(MutexContention_thread, nsnull);
139 PRThread* t3 = spawn(MutexContention_thread, nsnull);
141 PR_JoinThread(t1);
142 PR_JoinThread(t2);
143 PR_JoinThread(t3);
145 delete gLock1;
147 PASS();
150 //-----------------------------------------------------------------------------
151 // Monitor tests
153 static Monitor* gMon1;
155 static void
156 MonitorContention_thread(void* /*arg*/)
158 for (int i = 0; i < 100000; ++i) {
159 gMon1->Enter();
160 gMon1->AssertCurrentThreadIn();
161 gMon1->Exit();
165 static nsresult
166 MonitorContention()
168 gMon1 = new Monitor("mon1");
170 PRThread* t1 = spawn(MonitorContention_thread, nsnull);
171 PRThread* t2 = spawn(MonitorContention_thread, nsnull);
172 PRThread* t3 = spawn(MonitorContention_thread, nsnull);
174 PR_JoinThread(t1);
175 PR_JoinThread(t2);
176 PR_JoinThread(t3);
178 delete gMon1;
180 PASS();
184 static Monitor* gMon2;
186 static void
187 MonitorContention2_thread(void* /*arg*/)
189 for (int i = 0; i < 100000; ++i) {
190 gMon2->Enter();
191 gMon2->AssertCurrentThreadIn();
193 gMon2->Enter();
194 gMon2->AssertCurrentThreadIn();
195 gMon2->Exit();
197 gMon2->AssertCurrentThreadIn();
198 gMon2->Exit();
202 static nsresult
203 MonitorContention2()
205 gMon2 = new Monitor("mon1");
207 PRThread* t1 = spawn(MonitorContention2_thread, nsnull);
208 PRThread* t2 = spawn(MonitorContention2_thread, nsnull);
209 PRThread* t3 = spawn(MonitorContention2_thread, nsnull);
211 PR_JoinThread(t1);
212 PR_JoinThread(t2);
213 PR_JoinThread(t3);
215 delete gMon2;
217 PASS();
221 static Monitor* gMon3;
222 static PRInt32 gMonFirst;
224 static void
225 MonitorSyncSanity_thread(void* /*arg*/)
227 gMon3->Enter();
228 gMon3->AssertCurrentThreadIn();
229 if (gMonFirst) {
230 gMonFirst = 0;
231 gMon3->Wait();
232 gMon3->Enter();
233 } else {
234 gMon3->Notify();
235 gMon3->Enter();
237 gMon3->AssertCurrentThreadIn();
238 gMon3->Exit();
239 gMon3->AssertCurrentThreadIn();
240 gMon3->Exit();
243 static nsresult
244 MonitorSyncSanity()
246 gMon3 = new Monitor("monitor::syncsanity");
248 for (PRInt32 i = 0; i < 10000; ++i) {
249 gMonFirst = 1;
250 PRThread* ping = spawn(MonitorSyncSanity_thread, nsnull);
251 PRThread* pong = spawn(MonitorSyncSanity_thread, nsnull);
252 PR_JoinThread(ping);
253 PR_JoinThread(pong);
256 delete gMon3;
258 PASS();
261 //-----------------------------------------------------------------------------
262 // Condvar tests
264 static Mutex* gCvlock1;
265 static CondVar* gCv1;
266 static PRInt32 gCvFirst;
268 static void
269 CondVarSanity_thread(void* /*arg*/)
271 gCvlock1->Lock();
272 gCvlock1->AssertCurrentThreadOwns();
273 if (gCvFirst) {
274 gCvFirst = 0;
275 gCv1->Wait();
276 } else {
277 gCv1->Notify();
279 gCvlock1->AssertCurrentThreadOwns();
280 gCvlock1->Unlock();
283 static nsresult
284 CondVarSanity()
286 gCvlock1 = new Mutex("cvlock1");
287 gCv1 = new CondVar(*gCvlock1, "cvlock1");
289 for (PRInt32 i = 0; i < 10000; ++i) {
290 gCvFirst = 1;
291 PRThread* ping = spawn(CondVarSanity_thread, nsnull);
292 PRThread* pong = spawn(CondVarSanity_thread, nsnull);
293 PR_JoinThread(ping);
294 PR_JoinThread(pong);
297 delete gCv1;
298 delete gCvlock1;
300 PASS();
303 //-----------------------------------------------------------------------------
304 // AutoLock tests
306 static nsresult
307 AutoLock()
309 Mutex l1("autolock");
310 MutexAutoLock autol1(l1);
312 l1.AssertCurrentThreadOwns();
315 Mutex l2("autolock2");
316 MutexAutoLock autol2(l2);
318 l1.AssertCurrentThreadOwns();
319 l2.AssertCurrentThreadOwns();
322 l1.AssertCurrentThreadOwns();
324 PASS();
327 //-----------------------------------------------------------------------------
328 // AutoUnlock tests
330 static nsresult
331 AutoUnlock()
333 Mutex l1("autounlock");
334 Mutex l2("autounlock2");
336 l1.Lock();
337 l1.AssertCurrentThreadOwns();
340 MutexAutoUnlock autol1(l1);
342 l2.Lock();
343 l2.AssertCurrentThreadOwns();
345 MutexAutoUnlock autol2(l2);
347 l2.AssertCurrentThreadOwns();
348 l2.Unlock();
350 l1.AssertCurrentThreadOwns();
352 l1.Unlock();
354 PASS();
357 //-----------------------------------------------------------------------------
358 // AutoMonitor tests
360 static nsresult
361 AutoMonitor()
363 Monitor m1("automonitor");
364 Monitor m2("automonitor2");
366 m1.Enter();
367 m1.AssertCurrentThreadIn();
369 MonitorAutoEnter autom1(m1);
370 m1.AssertCurrentThreadIn();
372 m2.Enter();
373 m2.AssertCurrentThreadIn();
375 MonitorAutoEnter autom2(m2);
376 m1.AssertCurrentThreadIn();
377 m2.AssertCurrentThreadIn();
379 m2.AssertCurrentThreadIn();
380 m2.Exit();
382 m1.AssertCurrentThreadIn();
384 m1.AssertCurrentThreadIn();
385 m1.Exit();
387 PASS();
390 //-----------------------------------------------------------------------------
393 main(int argc, char** argv)
395 ScopedXPCOM xpcom("Synchronization");
396 if (xpcom.failed())
397 return 1;
399 int rv = 0;
401 if (NS_FAILED(Sanity()))
402 rv = 1;
403 if (NS_FAILED(MutexContention()))
404 rv = 1;
405 if (NS_FAILED(MonitorContention()))
406 rv = 1;
407 if (NS_FAILED(MonitorContention2()))
408 rv = 1;
409 if (NS_FAILED(MonitorSyncSanity()))
410 rv = 1;
411 if (NS_FAILED(CondVarSanity()))
412 rv = 1;
413 if (NS_FAILED(AutoLock()))
414 rv = 1;
415 if (NS_FAILED(AutoUnlock()))
416 rv = 1;
417 if (NS_FAILED(AutoMonitor()))
418 rv = 1;
420 return rv;