File: | pr/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/pr/tests/../../../pr/tests/perf.c |
Warning: | line 56, column 9 Value stored to 'time' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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/. */ |
5 | |
6 | #include "nspr.h" |
7 | #include "plgetopt.h" |
8 | |
9 | #include <stdio.h> |
10 | #include <stdlib.h> |
11 | #include <string.h> |
12 | |
13 | int _debug_on = 0; |
14 | #define DPRINTF(arg)if (_debug_on) printf arg if (_debug_on) printf arg |
15 | |
16 | #include "obsolete/prsem.h" |
17 | |
18 | PRLock *lock; |
19 | PRMonitor *mon; |
20 | PRMonitor *mon2; |
21 | |
22 | #define DEFAULT_COUNT1000 1000 |
23 | |
24 | PRInt32 count; |
25 | |
26 | static void nop(int a, int b, int c) |
27 | { |
28 | } |
29 | |
30 | static void LocalProcedureCall(void) |
31 | { |
32 | PRInt32 i; |
33 | |
34 | for (i = 0; i < count; i++) { |
35 | nop(i, i, 5); |
36 | } |
37 | } |
38 | |
39 | static void DLLProcedureCall(void) |
40 | { |
41 | PRInt32 i; |
42 | PRThreadState state; |
43 | PRThread *self = PR_GetCurrentThread(); |
44 | |
45 | for (i = 0; i < count; i++) { |
46 | state = PR_GetThreadState(self); |
47 | } |
48 | } |
49 | |
50 | static void Now(void) |
51 | { |
52 | PRInt32 i; |
53 | PRTime time; |
54 | |
55 | for (i = 0; i < count; i++) { |
56 | time = PR_Now(); |
Value stored to 'time' is never read | |
57 | } |
58 | } |
59 | |
60 | static void Interval(void) |
61 | { |
62 | PRInt32 i; |
63 | PRIntervalTime time; |
64 | |
65 | for (i = 0; i < count; i++) { |
66 | time = PR_IntervalNow(); |
67 | } |
68 | } |
69 | |
70 | static void IdleLock(void) |
71 | { |
72 | PRInt32 i; |
73 | |
74 | for (i = 0; i < count; i++) { |
75 | PR_Lock(lock); |
76 | PR_Unlock(lock); |
77 | } |
78 | } |
79 | |
80 | static void IdleMonitor(void) |
81 | { |
82 | PRInt32 i; |
83 | |
84 | for (i = 0; i < count; i++) { |
85 | PR_EnterMonitor(mon); |
86 | PR_ExitMonitor(mon); |
87 | } |
88 | } |
89 | |
90 | static void IdleCMonitor(void) |
91 | { |
92 | PRInt32 i; |
93 | |
94 | for (i = 0; i < count; i++) { |
95 | PR_CEnterMonitor((void*)7); |
96 | PR_CExitMonitor((void*)7); |
97 | } |
98 | } |
99 | |
100 | /************************************************************************/ |
101 | |
102 | static void PR_CALLBACK dull(void *arg) |
103 | { |
104 | } |
105 | |
106 | static void CDThread(void) |
107 | { |
108 | PRInt32 i; |
109 | int num_threads = count; |
110 | |
111 | /* |
112 | * Cannot create too many threads |
113 | */ |
114 | if (num_threads > 1000) { |
115 | num_threads = 1000; |
116 | } |
117 | |
118 | for (i = 0; i < num_threads; i++) { |
119 | PRThread *t = PR_CreateThread(PR_USER_THREAD, |
120 | dull, 0, |
121 | PR_PRIORITY_NORMAL, |
122 | PR_LOCAL_THREAD, |
123 | PR_UNJOINABLE_THREAD, |
124 | 0); |
125 | if (NULL((void*)0) == t) { |
126 | fprintf(stderrstderr, "CDThread: cannot create thread %3d\n", i); |
127 | } else { |
128 | DPRINTF(("CDThread: created thread %3d \n",i))if (_debug_on) printf ("CDThread: created thread %3d \n",i); |
129 | } |
130 | PR_Sleep(0); |
131 | } |
132 | } |
133 | |
134 | static int alive; |
135 | static int cxq; |
136 | |
137 | static void PR_CALLBACK CXReader(void *arg) |
138 | { |
139 | PRInt32 i, n; |
140 | |
141 | PR_EnterMonitor(mon); |
142 | n = count / 2; |
143 | for (i = 0; i < n; i++) { |
144 | while (cxq == 0) { |
145 | DPRINTF(("CXReader: thread = 0x%lx waiting\n",if (_debug_on) printf ("CXReader: thread = 0x%lx waiting\n", PR_GetCurrentThread ()) |
146 | PR_GetCurrentThread()))if (_debug_on) printf ("CXReader: thread = 0x%lx waiting\n", PR_GetCurrentThread ()); |
147 | PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT0xffffffffUL); |
148 | } |
149 | --cxq; |
150 | PR_Notify(mon); |
151 | } |
152 | PR_ExitMonitor(mon); |
153 | |
154 | PR_EnterMonitor(mon2); |
155 | --alive; |
156 | PR_Notify(mon2); |
157 | PR_ExitMonitor(mon2); |
158 | DPRINTF(("CXReader: thread = 0x%lx exiting\n", PR_GetCurrentThread()))if (_debug_on) printf ("CXReader: thread = 0x%lx exiting\n", PR_GetCurrentThread ()); |
159 | } |
160 | |
161 | static void PR_CALLBACK CXWriter(void *arg) |
162 | { |
163 | PRInt32 i, n; |
164 | |
165 | PR_EnterMonitor(mon); |
166 | n = count / 2; |
167 | for (i = 0; i < n; i++) { |
168 | while (cxq == 1) { |
169 | DPRINTF(("CXWriter: thread = 0x%lx waiting\n",if (_debug_on) printf ("CXWriter: thread = 0x%lx waiting\n", PR_GetCurrentThread ()) |
170 | PR_GetCurrentThread()))if (_debug_on) printf ("CXWriter: thread = 0x%lx waiting\n", PR_GetCurrentThread ()); |
171 | PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT0xffffffffUL); |
172 | } |
173 | ++cxq; |
174 | PR_Notify(mon); |
175 | } |
176 | PR_ExitMonitor(mon); |
177 | |
178 | PR_EnterMonitor(mon2); |
179 | --alive; |
180 | PR_Notify(mon2); |
181 | PR_ExitMonitor(mon2); |
182 | DPRINTF(("CXWriter: thread = 0x%lx exiting\n", PR_GetCurrentThread()))if (_debug_on) printf ("CXWriter: thread = 0x%lx exiting\n", PR_GetCurrentThread ()); |
183 | } |
184 | |
185 | static void ContextSwitch(PRThreadScope scope1, PRThreadScope scope2) |
186 | { |
187 | PRThread *t1, *t2; |
188 | |
189 | PR_EnterMonitor(mon2); |
190 | alive = 2; |
191 | cxq = 0; |
192 | |
193 | t1 = PR_CreateThread(PR_USER_THREAD, |
194 | CXReader, 0, |
195 | PR_PRIORITY_NORMAL, |
196 | scope1, |
197 | PR_UNJOINABLE_THREAD, |
198 | 0); |
199 | if (NULL((void*)0) == t1) { |
200 | fprintf(stderrstderr, "ContextSwitch: cannot create thread\n"); |
201 | } else { |
202 | DPRINTF(("ContextSwitch: created %s thread = 0x%lx\n",if (_debug_on) printf ("ContextSwitch: created %s thread = 0x%lx\n" , (scope1 == PR_GLOBAL_THREAD ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD" ), t1) |
203 | (scope1 == PR_GLOBAL_THREAD ?if (_debug_on) printf ("ContextSwitch: created %s thread = 0x%lx\n" , (scope1 == PR_GLOBAL_THREAD ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD" ), t1) |
204 | "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD"),if (_debug_on) printf ("ContextSwitch: created %s thread = 0x%lx\n" , (scope1 == PR_GLOBAL_THREAD ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD" ), t1) |
205 | t1))if (_debug_on) printf ("ContextSwitch: created %s thread = 0x%lx\n" , (scope1 == PR_GLOBAL_THREAD ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD" ), t1); |
206 | } |
207 | t2 = PR_CreateThread(PR_USER_THREAD, |
208 | CXWriter, 0, |
209 | PR_PRIORITY_NORMAL, |
210 | scope2, |
211 | PR_UNJOINABLE_THREAD, |
212 | 0); |
213 | if (NULL((void*)0) == t2) { |
214 | fprintf(stderrstderr, "ContextSwitch: cannot create thread\n"); |
215 | } else { |
216 | DPRINTF(("ContextSwitch: created %s thread = 0x%lx\n",if (_debug_on) printf ("ContextSwitch: created %s thread = 0x%lx\n" , (scope2 == PR_GLOBAL_THREAD ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD" ), t2) |
217 | (scope2 == PR_GLOBAL_THREAD ?if (_debug_on) printf ("ContextSwitch: created %s thread = 0x%lx\n" , (scope2 == PR_GLOBAL_THREAD ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD" ), t2) |
218 | "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD"),if (_debug_on) printf ("ContextSwitch: created %s thread = 0x%lx\n" , (scope2 == PR_GLOBAL_THREAD ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD" ), t2) |
219 | t2))if (_debug_on) printf ("ContextSwitch: created %s thread = 0x%lx\n" , (scope2 == PR_GLOBAL_THREAD ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD" ), t2); |
220 | } |
221 | |
222 | /* Wait for both of the threads to exit */ |
223 | while (alive) { |
224 | PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT0xffffffffUL); |
225 | } |
226 | PR_ExitMonitor(mon2); |
227 | } |
228 | |
229 | static void ContextSwitchUU(void) |
230 | { |
231 | ContextSwitch(PR_LOCAL_THREAD, PR_LOCAL_THREAD); |
232 | } |
233 | |
234 | static void ContextSwitchUK(void) |
235 | { |
236 | ContextSwitch(PR_LOCAL_THREAD, PR_GLOBAL_THREAD); |
237 | } |
238 | |
239 | static void ContextSwitchKU(void) |
240 | { |
241 | ContextSwitch(PR_GLOBAL_THREAD, PR_LOCAL_THREAD); |
242 | } |
243 | |
244 | static void ContextSwitchKK(void) |
245 | { |
246 | ContextSwitch(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD); |
247 | } |
248 | |
249 | /************************************************************************/ |
250 | |
251 | static void PR_CALLBACK SemaThread(void *argSema) |
252 | { |
253 | PRSemaphore **sem = (PRSemaphore **)argSema; |
254 | PRInt32 i, n; |
255 | |
256 | n = count / 2; |
257 | for (i = 0; i < n; i++) { |
258 | DPRINTF(("SemaThread: thread = 0x%lx waiting on sem = 0x%lx\n",if (_debug_on) printf ("SemaThread: thread = 0x%lx waiting on sem = 0x%lx\n" , PR_GetCurrentThread(), sem[0]) |
259 | PR_GetCurrentThread(), sem[0]))if (_debug_on) printf ("SemaThread: thread = 0x%lx waiting on sem = 0x%lx\n" , PR_GetCurrentThread(), sem[0]); |
260 | PR_WaitSem(sem[0]); |
261 | DPRINTF(("SemaThread: thread = 0x%lx posting on sem = 0x%lx\n",if (_debug_on) printf ("SemaThread: thread = 0x%lx posting on sem = 0x%lx\n" , PR_GetCurrentThread(), sem[1]) |
262 | PR_GetCurrentThread(), sem[1]))if (_debug_on) printf ("SemaThread: thread = 0x%lx posting on sem = 0x%lx\n" , PR_GetCurrentThread(), sem[1]); |
263 | PR_PostSem(sem[1]); |
264 | } |
265 | |
266 | PR_EnterMonitor(mon2); |
267 | --alive; |
268 | PR_Notify(mon2); |
269 | PR_ExitMonitor(mon2); |
270 | DPRINTF(("SemaThread: thread = 0x%lx exiting\n", PR_GetCurrentThread()))if (_debug_on) printf ("SemaThread: thread = 0x%lx exiting\n" , PR_GetCurrentThread()); |
271 | } |
272 | |
273 | static PRSemaphore *sem_set1[2]; |
274 | static PRSemaphore *sem_set2[2]; |
275 | |
276 | static void SemaContextSwitch(PRThreadScope scope1, PRThreadScope scope2) |
277 | { |
278 | PRThread *t1, *t2; |
279 | sem_set1[0] = PR_NewSem(1); |
280 | sem_set1[1] = PR_NewSem(0); |
281 | sem_set2[0] = sem_set1[1]; |
282 | sem_set2[1] = sem_set1[0]; |
283 | |
284 | PR_EnterMonitor(mon2); |
285 | alive = 2; |
286 | cxq = 0; |
287 | |
288 | t1 = PR_CreateThread(PR_USER_THREAD, |
289 | SemaThread, |
290 | sem_set1, |
291 | PR_PRIORITY_NORMAL, |
292 | scope1, |
293 | PR_UNJOINABLE_THREAD, |
294 | 0); |
295 | if (NULL((void*)0) == t1) { |
296 | fprintf(stderrstderr, "SemaContextSwitch: cannot create thread\n"); |
297 | } else { |
298 | DPRINTF(("SemaContextSwitch: created %s thread = 0x%lx\n",if (_debug_on) printf ("SemaContextSwitch: created %s thread = 0x%lx\n" , (scope1 == PR_GLOBAL_THREAD ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD" ), t1) |
299 | (scope1 == PR_GLOBAL_THREAD ?if (_debug_on) printf ("SemaContextSwitch: created %s thread = 0x%lx\n" , (scope1 == PR_GLOBAL_THREAD ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD" ), t1) |
300 | "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD"),if (_debug_on) printf ("SemaContextSwitch: created %s thread = 0x%lx\n" , (scope1 == PR_GLOBAL_THREAD ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD" ), t1) |
301 | t1))if (_debug_on) printf ("SemaContextSwitch: created %s thread = 0x%lx\n" , (scope1 == PR_GLOBAL_THREAD ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD" ), t1); |
302 | } |
303 | t2 = PR_CreateThread(PR_USER_THREAD, |
304 | SemaThread, |
305 | sem_set2, |
306 | PR_PRIORITY_NORMAL, |
307 | scope2, |
308 | PR_UNJOINABLE_THREAD, |
309 | 0); |
310 | if (NULL((void*)0) == t2) { |
311 | fprintf(stderrstderr, "SemaContextSwitch: cannot create thread\n"); |
312 | } else { |
313 | DPRINTF(("SemaContextSwitch: created %s thread = 0x%lx\n",if (_debug_on) printf ("SemaContextSwitch: created %s thread = 0x%lx\n" , (scope2 == PR_GLOBAL_THREAD ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD" ), t2) |
314 | (scope2 == PR_GLOBAL_THREAD ?if (_debug_on) printf ("SemaContextSwitch: created %s thread = 0x%lx\n" , (scope2 == PR_GLOBAL_THREAD ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD" ), t2) |
315 | "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD"),if (_debug_on) printf ("SemaContextSwitch: created %s thread = 0x%lx\n" , (scope2 == PR_GLOBAL_THREAD ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD" ), t2) |
316 | t2))if (_debug_on) printf ("SemaContextSwitch: created %s thread = 0x%lx\n" , (scope2 == PR_GLOBAL_THREAD ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD" ), t2); |
317 | } |
318 | |
319 | /* Wait for both of the threads to exit */ |
320 | while (alive) { |
321 | PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT0xffffffffUL); |
322 | } |
323 | PR_ExitMonitor(mon2); |
324 | |
325 | PR_DestroySem(sem_set1[0]); |
326 | PR_DestroySem(sem_set1[1]); |
327 | } |
328 | |
329 | static void SemaContextSwitchUU(void) |
330 | { |
331 | SemaContextSwitch(PR_LOCAL_THREAD, PR_LOCAL_THREAD); |
332 | } |
333 | |
334 | static void SemaContextSwitchUK(void) |
335 | { |
336 | SemaContextSwitch(PR_LOCAL_THREAD, PR_GLOBAL_THREAD); |
337 | } |
338 | |
339 | static void SemaContextSwitchKU(void) |
340 | { |
341 | SemaContextSwitch(PR_GLOBAL_THREAD, PR_LOCAL_THREAD); |
342 | } |
343 | |
344 | static void SemaContextSwitchKK(void) |
345 | { |
346 | SemaContextSwitch(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD); |
347 | } |
348 | |
349 | |
350 | /************************************************************************/ |
351 | |
352 | static void Measure(void (*func)(void), const char *msg) |
353 | { |
354 | PRIntervalTime start, stop; |
355 | double d; |
356 | |
357 | start = PR_IntervalNow(); |
358 | (*func)(); |
359 | stop = PR_IntervalNow() - start; |
360 | d = (double)PR_IntervalToMicroseconds(stop); |
361 | |
362 | printf("%40s: %6.2f usec\n", msg, d / count); |
363 | } |
364 | |
365 | int main(int argc, char **argv) |
366 | { |
367 | PLOptStatus os; |
368 | PLOptState *opt = PL_CreateOptState(argc, argv, "dc:"); |
369 | while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) |
370 | { |
371 | if (PL_OPT_BAD == os) { |
372 | continue; |
373 | } |
374 | switch (opt->option) |
375 | { |
376 | case 'd': /* debug mode */ |
377 | _debug_on = 1; |
378 | break; |
379 | case 'c': /* loop count */ |
380 | count = atoi(opt->value); |
381 | break; |
382 | default: |
383 | break; |
384 | } |
385 | } |
386 | PL_DestroyOptState(opt); |
387 | |
388 | if (0 == count) { |
389 | count = DEFAULT_COUNT1000; |
390 | } |
391 | |
392 | PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); |
393 | PR_BlockClockInterrupts(); |
394 | PR_UnblockClockInterrupts(); |
395 | PR_STDIO_INIT(); |
396 | |
397 | lock = PR_NewLock(); |
398 | mon = PR_NewMonitor(); |
399 | mon2 = PR_NewMonitor(); |
400 | |
401 | Measure(LocalProcedureCall, "local procedure call overhead"); |
402 | Measure(DLLProcedureCall, "DLL procedure call overhead"); |
403 | Measure(Now, "current calendar time"); |
404 | Measure(Interval, "interval time"); |
405 | Measure(IdleLock, "idle lock lock/unlock pair"); |
406 | Measure(IdleMonitor, "idle monitor entry/exit pair"); |
407 | Measure(IdleCMonitor, "idle cache monitor entry/exit pair"); |
408 | Measure(CDThread, "create/destroy thread pair"); |
409 | Measure(ContextSwitchUU, "context switch - user/user"); |
410 | Measure(ContextSwitchUK, "context switch - user/kernel"); |
411 | Measure(ContextSwitchKU, "context switch - kernel/user"); |
412 | Measure(ContextSwitchKK, "context switch - kernel/kernel"); |
413 | Measure(SemaContextSwitchUU, "sema context switch - user/user"); |
414 | Measure(SemaContextSwitchUK, "sema context switch - user/kernel"); |
415 | Measure(SemaContextSwitchKU, "sema context switch - kernel/user"); |
416 | Measure(SemaContextSwitchKK, "sema context switch - kernel/kernel"); |
417 | |
418 | printf("--------------\n"); |
419 | printf("Adding 7 additional CPUs\n"); |
420 | |
421 | PR_SetConcurrency(8); |
422 | printf("--------------\n"); |
423 | |
424 | Measure(LocalProcedureCall, "local procedure call overhead"); |
425 | Measure(DLLProcedureCall, "DLL procedure call overhead"); |
426 | Measure(Now, "current calendar time"); |
427 | Measure(Interval, "interval time"); |
428 | Measure(IdleLock, "idle lock lock/unlock pair"); |
429 | Measure(IdleMonitor, "idle monitor entry/exit pair"); |
430 | Measure(IdleCMonitor, "idle cache monitor entry/exit pair"); |
431 | Measure(CDThread, "create/destroy thread pair"); |
432 | Measure(ContextSwitchUU, "context switch - user/user"); |
433 | Measure(ContextSwitchUK, "context switch - user/kernel"); |
434 | Measure(ContextSwitchKU, "context switch - kernel/user"); |
435 | Measure(ContextSwitchKK, "context switch - kernel/kernel"); |
436 | Measure(SemaContextSwitchUU, "sema context switch - user/user"); |
437 | Measure(SemaContextSwitchUK, "sema context switch - user/kernel"); |
438 | Measure(SemaContextSwitchKU, "sema context switch - kernel/user"); |
439 | Measure(SemaContextSwitchKK, "sema context switch - kernel/kernel"); |
440 | |
441 | PR_DestroyLock(lock); |
442 | PR_DestroyMonitor(mon); |
443 | PR_DestroyMonitor(mon2); |
444 | |
445 | PR_Cleanup(); |
446 | return 0; |
447 | } |