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);