backout 29799f914cab, Bug 917642 - [Helix] Please update the helix blobs
[gecko.git] / nsprpub / pr / tests / switch.c
blob43c5ce562bbbbb715962808a93ca59ca46be67d0
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);
68 if (verbosity) PR_fprintf(debug_out, "+");
69 shared->twiddle = PR_TRUE;
70 shared->next->twiddle = PR_FALSE;
71 PR_NotifyCondVar(shared->next->cv);
72 PR_Unlock(shared->ml);
74 } /* Notified */
76 static Shared home;
77 PRIntn PR_CALLBACK Switch(PRIntn argc, char **argv)
79 PLOptStatus os;
80 PRStatus status;
81 PRBool help = PR_FALSE;
82 PRUintn concurrency = 1;
83 Shared *shared, *link;
84 PRIntervalTime timein, timeout;
85 PRThreadScope thread_scope = PR_LOCAL_THREAD;
86 PRUintn thread_count, inner_count, loop_count, average;
87 PRUintn thread_limit = DEFAULT_THREADS, loop_limit = DEFAULT_LOOPS;
88 PLOptState *opt = PL_CreateOptState(argc, argv, "hdvc:t:C:G");
89 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
91 if (PL_OPT_BAD == os) continue;
92 switch (opt->option)
94 case 'v': /* verbose mode */
95 verbosity = PR_TRUE;
96 case 'd': /* debug mode */
97 debug_mode = PR_TRUE;
98 break;
99 case 'c': /* loop counter */
100 loop_limit = atoi(opt->value);
101 break;
102 case 't': /* thread limit */
103 thread_limit = atoi(opt->value);
104 break;
105 case 'C': /* Concurrency limit */
106 concurrency = atoi(opt->value);
107 break;
108 case 'G': /* global threads only */
109 thread_scope = PR_GLOBAL_THREAD;
110 break;
111 case 'h': /* help message */
112 Help();
113 help = PR_TRUE;
114 break;
115 default:
116 break;
119 PL_DestroyOptState(opt);
121 if (help) return -1;
123 if (PR_TRUE == debug_mode)
125 debug_out = PR_STDOUT;
126 PR_fprintf(debug_out, "Test parameters\n");
127 PR_fprintf(debug_out, "\tThreads involved: %d\n", thread_limit);
128 PR_fprintf(debug_out, "\tIteration limit: %d\n", loop_limit);
129 PR_fprintf(debug_out, "\tConcurrency: %d\n", concurrency);
130 PR_fprintf(
131 debug_out, "\tThread type: %s\n",
132 (PR_GLOBAL_THREAD == thread_scope) ? "GLOBAL" : "LOCAL");
135 PR_SetConcurrency(concurrency);
137 link = &home;
138 home.ml = PR_NewLock();
139 home.cv = PR_NewCondVar(home.ml);
140 home.twiddle = PR_FALSE;
141 home.next = NULL;
143 timeout = 0;
145 for (thread_count = 1; thread_count <= thread_limit; ++thread_count)
147 shared = PR_NEWZAP(Shared);
149 shared->ml = home.ml;
150 shared->cv = PR_NewCondVar(home.ml);
151 shared->twiddle = PR_TRUE;
152 shared->next = link;
153 link = shared;
155 shared->thread = PR_CreateThread(
156 PR_USER_THREAD, Notified, shared,
157 PR_PRIORITY_HIGH, thread_scope,
158 PR_JOINABLE_THREAD, 0);
159 PR_ASSERT(shared->thread != NULL);
160 if (NULL == shared->thread)
161 failed = PR_TRUE;
164 for (loop_count = 1; loop_count <= loop_limit; ++loop_count)
166 timein = PR_IntervalNow();
167 for (inner_count = 0; inner_count < INNER_LOOPS; ++inner_count)
169 PR_Lock(home.ml);
170 home.twiddle = PR_TRUE;
171 shared->twiddle = PR_FALSE;
172 PR_NotifyCondVar(shared->cv);
173 while (home.twiddle)
175 status = PR_WaitCondVar(home.cv, PR_INTERVAL_NO_TIMEOUT);
176 if (PR_FAILURE == status)
177 failed = PR_TRUE;
179 PR_Unlock(home.ml);
181 timeout += (PR_IntervalNow() - timein);
184 if (debug_mode)
186 average = PR_IntervalToMicroseconds(timeout)
187 / (INNER_LOOPS * loop_limit * thread_count);
188 PR_fprintf(
189 debug_out, "Average switch times %d usecs for %d threads\n",
190 average, thread_limit);
193 link = shared;
194 for (thread_count = 1; thread_count <= thread_limit; ++thread_count)
196 if (&home == link) break;
197 status = PR_Interrupt(link->thread);
198 if (PR_SUCCESS != status)
200 failed = PR_TRUE;
201 if (debug_mode)
202 PL_FPrintError(debug_out, "Failed to interrupt");
204 link = link->next;
207 for (thread_count = 1; thread_count <= thread_limit; ++thread_count)
209 link = shared->next;
210 status = PR_JoinThread(shared->thread);
211 if (PR_SUCCESS != status)
213 failed = PR_TRUE;
214 if (debug_mode)
215 PL_FPrintError(debug_out, "Failed to join");
217 PR_DestroyCondVar(shared->cv);
218 PR_DELETE(shared);
219 if (&home == link) break;
220 shared = link;
222 PR_DestroyCondVar(home.cv);
223 PR_DestroyLock(home.ml);
225 PR_fprintf(PR_STDOUT, ((failed) ? "FAILED\n" : "PASSED\n"));
226 return ((failed) ? 1 : 0);
227 } /* Switch */
229 int main(int argc, char **argv)
231 PRIntn result;
232 PR_STDIO_INIT();
233 result = PR_Initialize(Switch, argc, argv, 0);
234 return result;
235 } /* main */
237 /* switch.c */