Backed out changeset e43e26b7f7b9 (bug 1857101) for causing bc failures on browser_tr...
[gecko.git] / nsprpub / pr / tests / switch.c
blob43db7888fb4938d477480af28f98d5ffc46a1575
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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 /*
7 ** File: switch.c
8 ** Description: trying to time context switches
9 */
11 #include "prinit.h"
12 #include "prcvar.h"
13 #include "prmem.h"
14 #include "prinrval.h"
15 #include "prlock.h"
16 #include "prlog.h"
17 #include "prthread.h"
18 #include "prprf.h"
20 #include "plerror.h"
21 #include "plgetopt.h"
23 #include "private/pprio.h"
25 #include <stdlib.h>
27 #define INNER_LOOPS 100
28 #define DEFAULT_LOOPS 100
29 #define DEFAULT_THREADS 10
31 static PRFileDesc *debug_out = NULL;
32 static PRBool debug_mode = PR_FALSE, verbosity = PR_FALSE, failed = PR_FALSE;
34 typedef struct Shared
36 PRLock *ml;
37 PRCondVar *cv;
38 PRBool twiddle;
39 PRThread *thread;
40 struct Shared *next;
41 } Shared;
43 static void Help(void)
45 debug_out = PR_STDOUT;
47 PR_fprintf(
48 debug_out, "Usage: >./switch [-c n] [-t n] [-d] [-v] [-G] [-C n]\n");
49 PR_fprintf(
50 debug_out, "-c n\tloops at thread level (default: %d)\n", DEFAULT_LOOPS);
51 PR_fprintf(
52 debug_out, "-t n\tnumber of threads (default: %d)\n", DEFAULT_THREADS);
53 PR_fprintf(debug_out, "-d\tturn on debugging output (default: FALSE)\n");
54 PR_fprintf(debug_out, "-v\tturn on verbose output (default: FALSE)\n");
55 PR_fprintf(debug_out, "-G\tglobal threads only (default: FALSE)\n");
56 PR_fprintf(debug_out, "-C n\tconcurrency setting (default: 1)\n");
57 } /* Help */
59 static void PR_CALLBACK Notified(void *arg)
61 Shared *shared = (Shared*)arg;
62 PRStatus status = PR_SUCCESS;
63 while (PR_SUCCESS == status)
65 PR_Lock(shared->ml);
66 while (shared->twiddle && (PR_SUCCESS == status)) {
67 status = PR_WaitCondVar(shared->cv, PR_INTERVAL_NO_TIMEOUT);
69 if (verbosity) {
70 PR_fprintf(debug_out, "+");
72 shared->twiddle = PR_TRUE;
73 shared->next->twiddle = PR_FALSE;
74 PR_NotifyCondVar(shared->next->cv);
75 PR_Unlock(shared->ml);
77 } /* Notified */
79 static Shared home;
80 PRIntn PR_CALLBACK Switch(PRIntn argc, char **argv)
82 PLOptStatus os;
83 PRStatus status;
84 PRBool help = PR_FALSE;
85 PRUintn concurrency = 1;
86 Shared *shared, *link;
87 PRIntervalTime timein, timeout;
88 PRThreadScope thread_scope = PR_LOCAL_THREAD;
89 PRUintn thread_count, inner_count, loop_count, average;
90 PRUintn thread_limit = DEFAULT_THREADS, loop_limit = DEFAULT_LOOPS;
91 PLOptState *opt = PL_CreateOptState(argc, argv, "hdvc:t:C:G");
92 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
94 if (PL_OPT_BAD == os) {
95 continue;
97 switch (opt->option)
99 case 'v': /* verbose mode */
100 verbosity = PR_TRUE;
101 case 'd': /* debug mode */
102 debug_mode = PR_TRUE;
103 break;
104 case 'c': /* loop counter */
105 loop_limit = atoi(opt->value);
106 break;
107 case 't': /* thread limit */
108 thread_limit = atoi(opt->value);
109 break;
110 case 'C': /* Concurrency limit */
111 concurrency = atoi(opt->value);
112 break;
113 case 'G': /* global threads only */
114 thread_scope = PR_GLOBAL_THREAD;
115 break;
116 case 'h': /* help message */
117 Help();
118 help = PR_TRUE;
119 break;
120 default:
121 break;
124 PL_DestroyOptState(opt);
126 if (help) {
127 return -1;
130 if (PR_TRUE == debug_mode)
132 debug_out = PR_STDOUT;
133 PR_fprintf(debug_out, "Test parameters\n");
134 PR_fprintf(debug_out, "\tThreads involved: %d\n", thread_limit);
135 PR_fprintf(debug_out, "\tIteration limit: %d\n", loop_limit);
136 PR_fprintf(debug_out, "\tConcurrency: %d\n", concurrency);
137 PR_fprintf(
138 debug_out, "\tThread type: %s\n",
139 (PR_GLOBAL_THREAD == thread_scope) ? "GLOBAL" : "LOCAL");
142 PR_SetConcurrency(concurrency);
144 link = &home;
145 home.ml = PR_NewLock();
146 home.cv = PR_NewCondVar(home.ml);
147 home.twiddle = PR_FALSE;
148 home.next = NULL;
150 timeout = 0;
152 for (thread_count = 1; thread_count <= thread_limit; ++thread_count)
154 shared = PR_NEWZAP(Shared);
156 shared->ml = home.ml;
157 shared->cv = PR_NewCondVar(home.ml);
158 shared->twiddle = PR_TRUE;
159 shared->next = link;
160 link = shared;
162 shared->thread = PR_CreateThread(
163 PR_USER_THREAD, Notified, shared,
164 PR_PRIORITY_HIGH, thread_scope,
165 PR_JOINABLE_THREAD, 0);
166 PR_ASSERT(shared->thread != NULL);
167 if (NULL == shared->thread) {
168 failed = PR_TRUE;
172 for (loop_count = 1; loop_count <= loop_limit; ++loop_count)
174 timein = PR_IntervalNow();
175 for (inner_count = 0; inner_count < INNER_LOOPS; ++inner_count)
177 PR_Lock(home.ml);
178 home.twiddle = PR_TRUE;
179 shared->twiddle = PR_FALSE;
180 PR_NotifyCondVar(shared->cv);
181 while (home.twiddle)
183 status = PR_WaitCondVar(home.cv, PR_INTERVAL_NO_TIMEOUT);
184 if (PR_FAILURE == status) {
185 failed = PR_TRUE;
188 PR_Unlock(home.ml);
190 timeout += (PR_IntervalNow() - timein);
193 if (debug_mode)
195 average = PR_IntervalToMicroseconds(timeout)
196 / (INNER_LOOPS * loop_limit * thread_count);
197 PR_fprintf(
198 debug_out, "Average switch times %d usecs for %d threads\n",
199 average, thread_limit);
202 link = shared;
203 for (thread_count = 1; thread_count <= thread_limit; ++thread_count)
205 if (&home == link) {
206 break;
208 status = PR_Interrupt(link->thread);
209 if (PR_SUCCESS != status)
211 failed = PR_TRUE;
212 if (debug_mode) {
213 PL_FPrintError(debug_out, "Failed to interrupt");
216 link = link->next;
219 for (thread_count = 1; thread_count <= thread_limit; ++thread_count)
221 link = shared->next;
222 status = PR_JoinThread(shared->thread);
223 if (PR_SUCCESS != status)
225 failed = PR_TRUE;
226 if (debug_mode) {
227 PL_FPrintError(debug_out, "Failed to join");
230 PR_DestroyCondVar(shared->cv);
231 PR_DELETE(shared);
232 if (&home == link) {
233 break;
235 shared = link;
237 PR_DestroyCondVar(home.cv);
238 PR_DestroyLock(home.ml);
240 PR_fprintf(PR_STDOUT, ((failed) ? "FAILED\n" : "PASSED\n"));
241 return ((failed) ? 1 : 0);
242 } /* Switch */
244 int main(int argc, char **argv)
246 PRIntn result;
247 PR_STDIO_INIT();
248 result = PR_Initialize(Switch, argc, argv, 0);
249 return result;
250 } /* main */
252 /* switch.c */