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
);
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
);
80 PRIntn PR_CALLBACK
Switch(PRIntn argc
, char **argv
)
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
) {
99 case 'v': /* verbose mode */
101 case 'd': /* debug mode */
102 debug_mode
= PR_TRUE
;
104 case 'c': /* loop counter */
105 loop_limit
= atoi(opt
->value
);
107 case 't': /* thread limit */
108 thread_limit
= atoi(opt
->value
);
110 case 'C': /* Concurrency limit */
111 concurrency
= atoi(opt
->value
);
113 case 'G': /* global threads only */
114 thread_scope
= PR_GLOBAL_THREAD
;
116 case 'h': /* help message */
124 PL_DestroyOptState(opt
);
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
);
138 debug_out
, "\tThread type: %s\n",
139 (PR_GLOBAL_THREAD
== thread_scope
) ? "GLOBAL" : "LOCAL");
142 PR_SetConcurrency(concurrency
);
145 home
.ml
= PR_NewLock();
146 home
.cv
= PR_NewCondVar(home
.ml
);
147 home
.twiddle
= PR_FALSE
;
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
;
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
) {
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
)
178 home
.twiddle
= PR_TRUE
;
179 shared
->twiddle
= PR_FALSE
;
180 PR_NotifyCondVar(shared
->cv
);
183 status
= PR_WaitCondVar(home
.cv
, PR_INTERVAL_NO_TIMEOUT
);
184 if (PR_FAILURE
== status
) {
190 timeout
+= (PR_IntervalNow() - timein
);
195 average
= PR_IntervalToMicroseconds(timeout
)
196 / (INNER_LOOPS
* loop_limit
* thread_count
);
198 debug_out
, "Average switch times %d usecs for %d threads\n",
199 average
, thread_limit
);
203 for (thread_count
= 1; thread_count
<= thread_limit
; ++thread_count
)
208 status
= PR_Interrupt(link
->thread
);
209 if (PR_SUCCESS
!= status
)
213 PL_FPrintError(debug_out
, "Failed to interrupt");
219 for (thread_count
= 1; thread_count
<= thread_limit
; ++thread_count
)
222 status
= PR_JoinThread(shared
->thread
);
223 if (PR_SUCCESS
!= status
)
227 PL_FPrintError(debug_out
, "Failed to join");
230 PR_DestroyCondVar(shared
->cv
);
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);
244 int main(int argc
, char **argv
)
248 result
= PR_Initialize(Switch
, argc
, argv
, 0);