1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/tests/TestDeadlockDetectorScalability.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,190 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: sw=4 ts=4 et : 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "TestHarness.h" 1.11 + 1.12 +//#define OLD_API 1.13 + 1.14 +#define PASS() \ 1.15 + do { \ 1.16 + passed(__FUNCTION__); \ 1.17 + return NS_OK; \ 1.18 + } while (0) 1.19 + 1.20 +#define FAIL(why) \ 1.21 + do { \ 1.22 + fail("%s | %s - %s", __FILE__, __FUNCTION__, why); \ 1.23 + return NS_ERROR_FAILURE; \ 1.24 + } while (0) 1.25 + 1.26 +#ifdef OLD_API 1.27 +# include "nsAutoLock.h" 1.28 + typedef PRLock* moz_lock_t; 1.29 +# define NEWLOCK(n) nsAutoLock::NewLock(n) 1.30 +# define DELETELOCK(v) nsAutoLock::DestroyLock(v) 1.31 +# define AUTOLOCK(v, l) nsAutoLock v(l) 1.32 +#else 1.33 +# include "mozilla/Mutex.h" 1.34 + typedef mozilla::Mutex* moz_lock_t; 1.35 +# define NEWLOCK(n) new mozilla::Mutex(n) 1.36 +# define DELETELOCK(v) delete (v) 1.37 +# define AUTOLOCK(v, l) mozilla::MutexAutoLock v(*l) 1.38 +#endif 1.39 + 1.40 +// def/undef these to run particular tests. 1.41 +#undef DD_TEST1 1.42 +#undef DD_TEST2 1.43 +#undef DD_TEST3 1.44 + 1.45 +//----------------------------------------------------------------------------- 1.46 + 1.47 +#ifdef DD_TEST1 1.48 + 1.49 +static void 1.50 +AllocLockRecurseUnlockFree(int i) 1.51 +{ 1.52 + if (0 == i) 1.53 + return; 1.54 + 1.55 + moz_lock_t lock = NEWLOCK("deadlockDetector.scalability.t1"); 1.56 + { 1.57 + AUTOLOCK(_, lock); 1.58 + AllocLockRecurseUnlockFree(i - 1); 1.59 + } 1.60 + DELETELOCK(lock); 1.61 +} 1.62 + 1.63 +// This test creates a resource dependency chain N elements long, then 1.64 +// frees all the resources in the chain. 1.65 +static nsresult 1.66 +LengthNDepChain(int N) 1.67 +{ 1.68 + AllocLockRecurseUnlockFree(N); 1.69 + PASS(); 1.70 +} 1.71 + 1.72 +#endif 1.73 + 1.74 +//----------------------------------------------------------------------------- 1.75 + 1.76 +#ifdef DD_TEST2 1.77 + 1.78 +// This test creates a single lock that is ordered < N resources, then 1.79 +// repeatedly exercises this order k times. 1.80 +static nsresult 1.81 +OneLockNDeps(const int N, const int K) 1.82 +{ 1.83 + moz_lock_t lock = NEWLOCK("deadlockDetector.scalability.t2.master"); 1.84 + moz_lock_t* locks = new moz_lock_t[N]; 1.85 + if (!locks) 1.86 + NS_RUNTIMEABORT("couldn't allocate lock array"); 1.87 + 1.88 + for (int i = 0; i < N; ++i) 1.89 + locks[i] = 1.90 + NEWLOCK("deadlockDetector.scalability.t2.dep"); 1.91 + 1.92 + // establish orders 1.93 + {AUTOLOCK(m, lock); 1.94 + for (int i = 0; i < N; ++i) 1.95 + AUTOLOCK(s, locks[i]); 1.96 + } 1.97 + 1.98 + // exercise order check 1.99 + {AUTOLOCK(m, lock); 1.100 + for (int i = 0; i < K; ++i) 1.101 + for (int j = 0; j < N; ++j) 1.102 + AUTOLOCK(s, locks[i]); 1.103 + } 1.104 + 1.105 + for (int i = 0; i < N; ++i) 1.106 + DELETELOCK(locks[i]); 1.107 + delete[] locks; 1.108 + 1.109 + PASS(); 1.110 +} 1.111 + 1.112 +#endif 1.113 + 1.114 +//----------------------------------------------------------------------------- 1.115 + 1.116 +#ifdef DD_TEST3 1.117 + 1.118 +// This test creates N resources and adds the theoretical maximum number 1.119 +// of dependencies, O(N^2). It then repeats that sequence of 1.120 +// acquisitions k times. Finally, all resources are freed. 1.121 +// 1.122 +// It's very difficult to perform well on this test. It's put forth as a 1.123 +// challenge problem. 1.124 + 1.125 +static nsresult 1.126 +MaxDepsNsq(const int N, const int K) 1.127 +{ 1.128 + moz_lock_t* locks = new moz_lock_t[N]; 1.129 + if (!locks) 1.130 + NS_RUNTIMEABORT("couldn't allocate lock array"); 1.131 + 1.132 + for (int i = 0; i < N; ++i) 1.133 + locks[i] = NEWLOCK("deadlockDetector.scalability.t3"); 1.134 + 1.135 + for (int i = 0; i < N; ++i) { 1.136 + AUTOLOCK(al1, locks[i]); 1.137 + for (int j = i+1; j < N; ++j) 1.138 + AUTOLOCK(al2, locks[j]); 1.139 + } 1.140 + 1.141 + for (int i = 0; i < K; ++i) { 1.142 + for (int j = 0; j < N; ++j) { 1.143 + AUTOLOCK(al1, locks[j]); 1.144 + for (int k = j+1; k < N; ++k) 1.145 + AUTOLOCK(al2, locks[k]); 1.146 + } 1.147 + } 1.148 + 1.149 + for (int i = 0; i < N; ++i) 1.150 + DELETELOCK(locks[i]); 1.151 + delete[] locks; 1.152 + 1.153 + PASS(); 1.154 +} 1.155 + 1.156 +#endif 1.157 + 1.158 +//----------------------------------------------------------------------------- 1.159 + 1.160 +int 1.161 +main(int argc, char** argv) 1.162 +{ 1.163 + ScopedXPCOM xpcom("Deadlock detector scalability (" __FILE__ ")"); 1.164 + if (xpcom.failed()) 1.165 + return 1; 1.166 + 1.167 + int rv = 0; 1.168 + 1.169 + // Uncomment these tests to run them. Not expected to be common. 1.170 + 1.171 +#ifndef DD_TEST1 1.172 + puts("Skipping not-requested LengthNDepChain() test"); 1.173 +#else 1.174 + if (NS_FAILED(LengthNDepChain(1 << 14))) // 16K 1.175 + rv = 1; 1.176 +#endif 1.177 + 1.178 +#ifndef DD_TEST2 1.179 + puts("Skipping not-requested OneLockNDeps() test"); 1.180 +#else 1.181 + if (NS_FAILED(OneLockNDeps(1 << 14, 100))) // 16k 1.182 + rv = 1; 1.183 +#endif 1.184 + 1.185 +#ifndef DD_TEST3 1.186 + puts("Skipping not-requested MaxDepsNsq() test"); 1.187 +#else 1.188 + if (NS_FAILED(MaxDepsNsq(1 << 10, 10))) // 1k 1.189 + rv = 1; 1.190 +#endif 1.191 + 1.192 + return rv; 1.193 +}