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/. */
8 ** Description: trying to time context switches
23 #include "private/pprio.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;
43 static void Help(void)
45 debug_out = PR_STDOUT;
48 debug_out, "Usage: >./switch [-c n] [-t n] [-d] [-v] [-G] [-C n]\n");
50 debug_out, "-c n\tloops at thread level (default: %d)\n", DEFAULT_LOOPS);
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");
59 static void PR_CALLBACK Notified(void *arg)
61 Shared *shared = (Shared*)arg;
62 PRStatus status = PR_SUCCESS;
63 while (PR_SUCCESS == status)
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);
77 PRIntn PR_CALLBACK Switch(PRIntn argc, char **argv)
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;
94 case 'v': /* verbose mode */
96 case 'd': /* debug mode */
99 case 'c': /* loop counter */
100 loop_limit = atoi(opt->value);
102 case 't': /* thread limit */
103 thread_limit = atoi(opt->value);
105 case 'C': /* Concurrency limit */
106 concurrency = atoi(opt->value);
108 case 'G': /* global threads only */
109 thread_scope = PR_GLOBAL_THREAD;
111 case 'h': /* help message */
119 PL_DestroyOptState(opt);
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);
131 debug_out, "\tThread type: %s\n",
132 (PR_GLOBAL_THREAD == thread_scope) ? "GLOBAL" : "LOCAL");
135 PR_SetConcurrency(concurrency);
138 home.ml = PR_NewLock();
139 home.cv = PR_NewCondVar(home.ml);
140 home.twiddle = PR_FALSE;
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;
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)
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)
170 home.twiddle = PR_TRUE;
171 shared->twiddle = PR_FALSE;
172 PR_NotifyCondVar(shared->cv);
175 status = PR_WaitCondVar(home.cv, PR_INTERVAL_NO_TIMEOUT);
176 if (PR_FAILURE == status)
181 timeout += (PR_IntervalNow() - timein);
186 average = PR_IntervalToMicroseconds(timeout)
187 / (INNER_LOOPS * loop_limit * thread_count);
189 debug_out, "Average switch times %d usecs for %d threads\n",
190 average, thread_limit);
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)
202 PL_FPrintError(debug_out, "Failed to interrupt");
207 for (thread_count = 1; thread_count <= thread_limit; ++thread_count)
210 status = PR_JoinThread(shared->thread);
211 if (PR_SUCCESS != status)
215 PL_FPrintError(debug_out, "Failed to join");
217 PR_DestroyCondVar(shared->cv);
219 if (&home == link) break;
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);
229 int main(int argc, char **argv)
233 result = PR_Initialize(Switch, argc, argv, 0);