1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsThreadUtils.h"
11 #include "nsIServiceManager.h"
14 class nsRunner
: public nsIRunnable
{
19 nsCOMPtr
<nsIThread
> thread
;
20 nsresult rv
= NS_GetCurrentThread(getter_AddRefs(thread
));
22 printf("failed to get current thread\n");
25 printf("running %d on thread %p\n", mNum
, (void *)thread
.get());
27 // if we don't do something slow, we'll never see the other
29 PR_Sleep(PR_MillisecondsToInterval(100));
34 nsRunner(int num
) : mNum(num
) {
41 NS_IMPL_THREADSAFE_ISUPPORTS1(nsRunner
, nsIRunnable
)
48 nsCOMPtr
<nsIRunnable
> event
= new nsRunner(0);
50 return NS_ERROR_OUT_OF_MEMORY
;
52 nsCOMPtr
<nsIThread
> runner
;
53 rv
= NS_NewThread(getter_AddRefs(runner
), event
);
55 printf("failed to create thread\n");
59 nsCOMPtr
<nsIThread
> thread
;
60 rv
= NS_GetCurrentThread(getter_AddRefs(thread
));
62 printf("failed to get current thread\n");
66 rv
= runner
->Shutdown(); // wait for the runner to die before quitting
68 printf("join failed\n");
71 PR_Sleep(PR_MillisecondsToInterval(100)); // hopefully the runner will quit here
76 class nsStressRunner
: public nsIRunnable
{
81 NS_ASSERTION(!mWasRun
, "run twice!");
84 if (!PR_AtomicDecrement(&gNum
)) {
85 printf(" last thread was %d\n", mNum
);
90 nsStressRunner(int num
) : mNum(num
), mWasRun(false) {
91 PR_AtomicIncrement(&gNum
);
94 static int32_t GetGlobalCount() {return gNum
;}
98 NS_ASSERTION(mWasRun
, "never run!");
107 int32_t nsStressRunner::gNum
= 0;
109 NS_IMPL_THREADSAFE_ISUPPORTS1(nsStressRunner
, nsIRunnable
)
111 static int Stress(int loops
, int threads
)
114 for (int i
= 0; i
< loops
; i
++) {
115 printf("Loop %d of %d\n", i
+1, loops
);
118 nsIThread
** array
= new nsIThread
*[threads
];
119 NS_ASSERTION(array
, "out of memory");
121 NS_ASSERTION(!nsStressRunner::GetGlobalCount(), "bad count of runnables");
123 for (k
= 0; k
< threads
; k
++) {
124 nsCOMPtr
<nsIThread
> t
;
125 nsresult rv
= NS_NewThread(getter_AddRefs(t
), new nsStressRunner(k
));
127 NS_ERROR("can't create thread");
130 NS_ADDREF(array
[k
] = t
);
133 for (k
= threads
-1; k
>= 0; k
--) {
134 array
[k
]->Shutdown();
135 NS_RELEASE(array
[k
]);
142 static void threadProc(void *arg
)
144 // printf(" running thread %d\n", (int) arg);
146 PR_ASSERT(PR_JOINABLE_THREAD
== PR_GetThreadState(PR_GetCurrentThread()));
149 static int StressNSPR(int loops
, int threads
)
152 for (int i
= 0; i
< loops
; i
++) {
153 printf("Loop %d of %d\n", i
+1, loops
);
156 PRThread
** array
= new PRThread
*[threads
];
159 for (k
= 0; k
< threads
; k
++) {
160 array
[k
] = PR_CreateThread(PR_USER_THREAD
,
161 threadProc
, (void*) k
,
169 for (k
= 0; k
< threads
; k
++) {
170 PR_ASSERT(PR_JOINABLE_THREAD
== PR_GetThreadState(array
[k
]));
173 for (k
= threads
-1; k
>= 0; k
--) {
174 PR_JoinThread(array
[k
]);
183 main(int argc
, char** argv
)
188 rv
= NS_InitXPCOM2(nullptr, nullptr, nullptr);
189 if (NS_FAILED(rv
)) return -1;
191 if (argc
> 1 && !strcmp(argv
[1], "-stress")) {
194 if (argc
!= 4 || *argv
[2] != '-' || *argv
[3] != '-' ||
195 !(loops
= atoi(argv
[2]+1)) || !(threads
= atoi(argv
[3]+1))) {
196 printf("To use -stress you must pass loop count and thread count...\n"
197 " TestThreads -stress -1000 -50\n");
199 printf("Running stress test with %d loops of %d threads each\n",
201 retval
= Stress(loops
, threads
);
203 } else if (argc
> 1 && !strcmp(argv
[1], "-stress-nspr")) {
206 if (argc
!= 4 || *argv
[2] != '-' || *argv
[3] != '-' ||
207 !(loops
= atoi(argv
[2]+1)) || !(threads
= atoi(argv
[3]+1))) {
208 printf("To use -stress-nspr you must pass loop count and thread count...\n"
209 " TestThreads -stress -1000 -50\n");
211 printf("Running stress test with %d loops of %d threads each\n",
213 retval
= StressNSPR(loops
, threads
);
217 if (NS_FAILED(rv
)) return -1;
220 rv
= NS_ShutdownXPCOM(nullptr);
221 if (NS_FAILED(rv
)) return -1;