xpcom/tests/TestSynchronization.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: sw=4 ts=4 et :
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "TestHarness.h"
michael@0 8
michael@0 9 #include "mozilla/CondVar.h"
michael@0 10 #include "mozilla/Monitor.h"
michael@0 11 #include "mozilla/Mutex.h"
michael@0 12 #include "nsAutoLock.h"
michael@0 13
michael@0 14 using namespace mozilla;
michael@0 15
michael@0 16 static PRThread*
michael@0 17 spawn(void (*run)(void*), void* arg)
michael@0 18 {
michael@0 19 return PR_CreateThread(PR_SYSTEM_THREAD,
michael@0 20 run,
michael@0 21 arg,
michael@0 22 PR_PRIORITY_NORMAL,
michael@0 23 PR_GLOBAL_THREAD,
michael@0 24 PR_JOINABLE_THREAD,
michael@0 25 0);
michael@0 26 }
michael@0 27
michael@0 28
michael@0 29 #define PASS() \
michael@0 30 do { \
michael@0 31 passed(__FUNCTION__); \
michael@0 32 return NS_OK; \
michael@0 33 } while (0)
michael@0 34
michael@0 35 #define FAIL(why) \
michael@0 36 do { \
michael@0 37 fail("%s | %s - %s", __FILE__, __FUNCTION__, why); \
michael@0 38 return NS_ERROR_FAILURE; \
michael@0 39 } while (0)
michael@0 40
michael@0 41 //-----------------------------------------------------------------------------
michael@0 42 // Sanity check: tests that can be done on a single thread
michael@0 43 //
michael@0 44 static nsresult
michael@0 45 Sanity()
michael@0 46 {
michael@0 47 Mutex lock("sanity::lock");
michael@0 48 lock.Lock();
michael@0 49 lock.AssertCurrentThreadOwns();
michael@0 50 lock.Unlock();
michael@0 51
michael@0 52 {
michael@0 53 MutexAutoLock autolock(lock);
michael@0 54 lock.AssertCurrentThreadOwns();
michael@0 55 }
michael@0 56
michael@0 57 lock.Lock();
michael@0 58 lock.AssertCurrentThreadOwns();
michael@0 59 {
michael@0 60 MutexAutoUnlock autounlock(lock);
michael@0 61 }
michael@0 62 lock.AssertCurrentThreadOwns();
michael@0 63 lock.Unlock();
michael@0 64
michael@0 65 Monitor mon("sanity::monitor");
michael@0 66 mon.Enter();
michael@0 67 mon.AssertCurrentThreadIn();
michael@0 68 mon.Enter();
michael@0 69 mon.AssertCurrentThreadIn();
michael@0 70 mon.Exit();
michael@0 71 mon.AssertCurrentThreadIn();
michael@0 72 mon.Exit();
michael@0 73
michael@0 74 {
michael@0 75 MonitorAutoEnter automon(mon);
michael@0 76 mon.AssertCurrentThreadIn();
michael@0 77 }
michael@0 78
michael@0 79 PASS();
michael@0 80 }
michael@0 81
michael@0 82 //-----------------------------------------------------------------------------
michael@0 83 // Mutex contention tests
michael@0 84 //
michael@0 85 static Mutex* gLock1;
michael@0 86
michael@0 87 static void
michael@0 88 MutexContention_thread(void* /*arg*/)
michael@0 89 {
michael@0 90 for (int i = 0; i < 100000; ++i) {
michael@0 91 gLock1->Lock();
michael@0 92 gLock1->AssertCurrentThreadOwns();
michael@0 93 gLock1->Unlock();
michael@0 94 }
michael@0 95 }
michael@0 96
michael@0 97 static nsresult
michael@0 98 MutexContention()
michael@0 99 {
michael@0 100 gLock1 = new Mutex("lock1");
michael@0 101 // PURPOSELY not checking for OOM. YAY!
michael@0 102
michael@0 103 PRThread* t1 = spawn(MutexContention_thread, nullptr);
michael@0 104 PRThread* t2 = spawn(MutexContention_thread, nullptr);
michael@0 105 PRThread* t3 = spawn(MutexContention_thread, nullptr);
michael@0 106
michael@0 107 PR_JoinThread(t1);
michael@0 108 PR_JoinThread(t2);
michael@0 109 PR_JoinThread(t3);
michael@0 110
michael@0 111 delete gLock1;
michael@0 112
michael@0 113 PASS();
michael@0 114 }
michael@0 115
michael@0 116 //-----------------------------------------------------------------------------
michael@0 117 // Monitor tests
michael@0 118 //
michael@0 119 static Monitor* gMon1;
michael@0 120
michael@0 121 static void
michael@0 122 MonitorContention_thread(void* /*arg*/)
michael@0 123 {
michael@0 124 for (int i = 0; i < 100000; ++i) {
michael@0 125 gMon1->Enter();
michael@0 126 gMon1->AssertCurrentThreadIn();
michael@0 127 gMon1->Exit();
michael@0 128 }
michael@0 129 }
michael@0 130
michael@0 131 static nsresult
michael@0 132 MonitorContention()
michael@0 133 {
michael@0 134 gMon1 = new Monitor("mon1");
michael@0 135
michael@0 136 PRThread* t1 = spawn(MonitorContention_thread, nullptr);
michael@0 137 PRThread* t2 = spawn(MonitorContention_thread, nullptr);
michael@0 138 PRThread* t3 = spawn(MonitorContention_thread, nullptr);
michael@0 139
michael@0 140 PR_JoinThread(t1);
michael@0 141 PR_JoinThread(t2);
michael@0 142 PR_JoinThread(t3);
michael@0 143
michael@0 144 delete gMon1;
michael@0 145
michael@0 146 PASS();
michael@0 147 }
michael@0 148
michael@0 149
michael@0 150 static Monitor* gMon2;
michael@0 151
michael@0 152 static void
michael@0 153 MonitorContention2_thread(void* /*arg*/)
michael@0 154 {
michael@0 155 for (int i = 0; i < 100000; ++i) {
michael@0 156 gMon2->Enter();
michael@0 157 gMon2->AssertCurrentThreadIn();
michael@0 158 {
michael@0 159 gMon2->Enter();
michael@0 160 gMon2->AssertCurrentThreadIn();
michael@0 161 gMon2->Exit();
michael@0 162 }
michael@0 163 gMon2->AssertCurrentThreadIn();
michael@0 164 gMon2->Exit();
michael@0 165 }
michael@0 166 }
michael@0 167
michael@0 168 static nsresult
michael@0 169 MonitorContention2()
michael@0 170 {
michael@0 171 gMon2 = new Monitor("mon1");
michael@0 172
michael@0 173 PRThread* t1 = spawn(MonitorContention2_thread, nullptr);
michael@0 174 PRThread* t2 = spawn(MonitorContention2_thread, nullptr);
michael@0 175 PRThread* t3 = spawn(MonitorContention2_thread, nullptr);
michael@0 176
michael@0 177 PR_JoinThread(t1);
michael@0 178 PR_JoinThread(t2);
michael@0 179 PR_JoinThread(t3);
michael@0 180
michael@0 181 delete gMon2;
michael@0 182
michael@0 183 PASS();
michael@0 184 }
michael@0 185
michael@0 186
michael@0 187 static Monitor* gMon3;
michael@0 188 static int32_t gMonFirst;
michael@0 189
michael@0 190 static void
michael@0 191 MonitorSyncSanity_thread(void* /*arg*/)
michael@0 192 {
michael@0 193 gMon3->Enter();
michael@0 194 gMon3->AssertCurrentThreadIn();
michael@0 195 if (gMonFirst) {
michael@0 196 gMonFirst = 0;
michael@0 197 gMon3->Wait();
michael@0 198 gMon3->Enter();
michael@0 199 } else {
michael@0 200 gMon3->Notify();
michael@0 201 gMon3->Enter();
michael@0 202 }
michael@0 203 gMon3->AssertCurrentThreadIn();
michael@0 204 gMon3->Exit();
michael@0 205 gMon3->AssertCurrentThreadIn();
michael@0 206 gMon3->Exit();
michael@0 207 }
michael@0 208
michael@0 209 static nsresult
michael@0 210 MonitorSyncSanity()
michael@0 211 {
michael@0 212 gMon3 = new Monitor("monitor::syncsanity");
michael@0 213
michael@0 214 for (int32_t i = 0; i < 10000; ++i) {
michael@0 215 gMonFirst = 1;
michael@0 216 PRThread* ping = spawn(MonitorSyncSanity_thread, nullptr);
michael@0 217 PRThread* pong = spawn(MonitorSyncSanity_thread, nullptr);
michael@0 218 PR_JoinThread(ping);
michael@0 219 PR_JoinThread(pong);
michael@0 220 }
michael@0 221
michael@0 222 delete gMon3;
michael@0 223
michael@0 224 PASS();
michael@0 225 }
michael@0 226
michael@0 227 //-----------------------------------------------------------------------------
michael@0 228 // Condvar tests
michael@0 229 //
michael@0 230 static Mutex* gCvlock1;
michael@0 231 static CondVar* gCv1;
michael@0 232 static int32_t gCvFirst;
michael@0 233
michael@0 234 static void
michael@0 235 CondVarSanity_thread(void* /*arg*/)
michael@0 236 {
michael@0 237 gCvlock1->Lock();
michael@0 238 gCvlock1->AssertCurrentThreadOwns();
michael@0 239 if (gCvFirst) {
michael@0 240 gCvFirst = 0;
michael@0 241 gCv1->Wait();
michael@0 242 } else {
michael@0 243 gCv1->Notify();
michael@0 244 }
michael@0 245 gCvlock1->AssertCurrentThreadOwns();
michael@0 246 gCvlock1->Unlock();
michael@0 247 }
michael@0 248
michael@0 249 static nsresult
michael@0 250 CondVarSanity()
michael@0 251 {
michael@0 252 gCvlock1 = new Mutex("cvlock1");
michael@0 253 gCv1 = new CondVar(*gCvlock1, "cvlock1");
michael@0 254
michael@0 255 for (int32_t i = 0; i < 10000; ++i) {
michael@0 256 gCvFirst = 1;
michael@0 257 PRThread* ping = spawn(CondVarSanity_thread, nullptr);
michael@0 258 PRThread* pong = spawn(CondVarSanity_thread, nullptr);
michael@0 259 PR_JoinThread(ping);
michael@0 260 PR_JoinThread(pong);
michael@0 261 }
michael@0 262
michael@0 263 delete gCv1;
michael@0 264 delete gCvlock1;
michael@0 265
michael@0 266 PASS();
michael@0 267 }
michael@0 268
michael@0 269 //-----------------------------------------------------------------------------
michael@0 270 // AutoLock tests
michael@0 271 //
michael@0 272 static nsresult
michael@0 273 AutoLock()
michael@0 274 {
michael@0 275 Mutex l1("autolock");
michael@0 276 MutexAutoLock autol1(l1);
michael@0 277
michael@0 278 l1.AssertCurrentThreadOwns();
michael@0 279
michael@0 280 {
michael@0 281 Mutex l2("autolock2");
michael@0 282 MutexAutoLock autol2(l2);
michael@0 283
michael@0 284 l1.AssertCurrentThreadOwns();
michael@0 285 l2.AssertCurrentThreadOwns();
michael@0 286 }
michael@0 287
michael@0 288 l1.AssertCurrentThreadOwns();
michael@0 289
michael@0 290 PASS();
michael@0 291 }
michael@0 292
michael@0 293 //-----------------------------------------------------------------------------
michael@0 294 // AutoUnlock tests
michael@0 295 //
michael@0 296 static nsresult
michael@0 297 AutoUnlock()
michael@0 298 {
michael@0 299 Mutex l1("autounlock");
michael@0 300 Mutex l2("autounlock2");
michael@0 301
michael@0 302 l1.Lock();
michael@0 303 l1.AssertCurrentThreadOwns();
michael@0 304
michael@0 305 {
michael@0 306 MutexAutoUnlock autol1(l1);
michael@0 307 {
michael@0 308 l2.Lock();
michael@0 309 l2.AssertCurrentThreadOwns();
michael@0 310
michael@0 311 MutexAutoUnlock autol2(l2);
michael@0 312 }
michael@0 313 l2.AssertCurrentThreadOwns();
michael@0 314 l2.Unlock();
michael@0 315 }
michael@0 316 l1.AssertCurrentThreadOwns();
michael@0 317
michael@0 318 l1.Unlock();
michael@0 319
michael@0 320 PASS();
michael@0 321 }
michael@0 322
michael@0 323 //-----------------------------------------------------------------------------
michael@0 324 // AutoMonitor tests
michael@0 325 //
michael@0 326 static nsresult
michael@0 327 AutoMonitor()
michael@0 328 {
michael@0 329 Monitor m1("automonitor");
michael@0 330 Monitor m2("automonitor2");
michael@0 331
michael@0 332 m1.Enter();
michael@0 333 m1.AssertCurrentThreadIn();
michael@0 334 {
michael@0 335 MonitorAutoEnter autom1(m1);
michael@0 336 m1.AssertCurrentThreadIn();
michael@0 337
michael@0 338 m2.Enter();
michael@0 339 m2.AssertCurrentThreadIn();
michael@0 340 {
michael@0 341 MonitorAutoEnter autom2(m2);
michael@0 342 m1.AssertCurrentThreadIn();
michael@0 343 m2.AssertCurrentThreadIn();
michael@0 344 }
michael@0 345 m2.AssertCurrentThreadIn();
michael@0 346 m2.Exit();
michael@0 347
michael@0 348 m1.AssertCurrentThreadIn();
michael@0 349 }
michael@0 350 m1.AssertCurrentThreadIn();
michael@0 351 m1.Exit();
michael@0 352
michael@0 353 PASS();
michael@0 354 }
michael@0 355
michael@0 356 //-----------------------------------------------------------------------------
michael@0 357
michael@0 358 int
michael@0 359 main(int argc, char** argv)
michael@0 360 {
michael@0 361 ScopedXPCOM xpcom("Synchronization (" __FILE__ ")");
michael@0 362 if (xpcom.failed())
michael@0 363 return 1;
michael@0 364
michael@0 365 int rv = 0;
michael@0 366
michael@0 367 if (NS_FAILED(Sanity()))
michael@0 368 rv = 1;
michael@0 369 if (NS_FAILED(MutexContention()))
michael@0 370 rv = 1;
michael@0 371 if (NS_FAILED(MonitorContention()))
michael@0 372 rv = 1;
michael@0 373 if (NS_FAILED(MonitorContention2()))
michael@0 374 rv = 1;
michael@0 375 if (NS_FAILED(MonitorSyncSanity()))
michael@0 376 rv = 1;
michael@0 377 if (NS_FAILED(CondVarSanity()))
michael@0 378 rv = 1;
michael@0 379 if (NS_FAILED(AutoLock()))
michael@0 380 rv = 1;
michael@0 381 if (NS_FAILED(AutoUnlock()))
michael@0 382 rv = 1;
michael@0 383 if (NS_FAILED(AutoMonitor()))
michael@0 384 rv = 1;
michael@0 385
michael@0 386 return rv;
michael@0 387 }

mercurial