File: | pr/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/pr/tests/../../../pr/tests/lock.c |
Warning: | line 385, column 5 Value stored to 'status' 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 | /* |
7 | ** File: lock.c |
8 | ** Purpose: test basic locking functions |
9 | ** |
10 | ** Modification History: |
11 | ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. |
12 | ** The debug mode will print all of the printfs associated with this test. |
13 | ** The regress mode will be the default mode. Since the regress tool limits |
14 | ** the output to a one line status:PASS or FAIL,all of the printf statements |
15 | ** have been handled with an if (debug_mode) statement. |
16 | ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to |
17 | ** recognize the return code from tha main program. |
18 | ** |
19 | ** 11-Aug-97 LarryH. Win16 port of NSPR. |
20 | ** - Added "PASS", "FAIL" messages on completion. |
21 | ** - Change stack variables to static scope variables |
22 | ** because of shadow-stack use by Win16 |
23 | ** - Added PR_CALLBACK attribute to functions called by NSPR |
24 | ** - Added command line arguments: |
25 | ** - l <num> to control the number of loops |
26 | ** - c <num> to control the number of CPUs. |
27 | ** (was positional argv). |
28 | ** |
29 | ** |
30 | ***********************************************************************/ |
31 | |
32 | /*********************************************************************** |
33 | ** Includes |
34 | ***********************************************************************/ |
35 | /* Used to get the command line option */ |
36 | #include "plgetopt.h" |
37 | |
38 | #include "prio.h" |
39 | #include "prcmon.h" |
40 | #include "prinit.h" |
41 | #include "prinrval.h" |
42 | #include "prprf.h" |
43 | #include "prlock.h" |
44 | #include "prlog.h" |
45 | #include "prmon.h" |
46 | #include "prmem.h" |
47 | #include "prthread.h" |
48 | #include "prtypes.h" |
49 | |
50 | #include "plstr.h" |
51 | |
52 | #include <stdlib.h> |
53 | |
54 | #if defined(XP_UNIX1) |
55 | #include <string.h> |
56 | #endif |
57 | |
58 | static PRIntn failed_already=0; |
59 | static PRFileDesc *std_err = NULL((void*)0); |
60 | static PRBool verbosity = PR_FALSE0; |
61 | static PRBool debug_mode = PR_FALSE0; |
62 | |
63 | const static PRIntervalTime contention_interval = 50; |
64 | |
65 | typedef struct LockContentious_s { |
66 | PRLock *ml; |
67 | PRInt32 loops; |
68 | PRUint32 contender; |
69 | PRUint32 contentious; |
70 | PRIntervalTime overhead; |
71 | PRIntervalTime interval; |
72 | } LockContentious_t; |
73 | |
74 | typedef struct MonitorContentious_s { |
75 | PRMonitor *ml; |
76 | PRInt32 loops; |
77 | PRUint32 contender; |
78 | PRUint32 contentious; |
79 | PRIntervalTime overhead; |
80 | PRIntervalTime interval; |
81 | } MonitorContentious_t; |
82 | |
83 | |
84 | static PRIntervalTime Sleeper(PRUint32 loops) |
85 | { |
86 | PRIntervalTime predicted = 0; |
87 | while (loops-- > 0) |
88 | { |
89 | predicted += contention_interval; |
90 | (void)PR_Sleep(contention_interval); |
91 | } |
92 | return predicted; |
93 | } /* Sleeper */ |
94 | |
95 | /* |
96 | ** BASIC LOCKS |
97 | */ |
98 | static PRIntervalTime MakeLock(PRUint32 loops) |
99 | { |
100 | PRLock *ml = NULL((void*)0); |
101 | while (loops-- > 0) |
102 | { |
103 | ml = PR_NewLock(); |
104 | PR_DestroyLock(ml); |
105 | ml = NULL((void*)0); |
106 | } |
107 | return 0; |
108 | } /* MakeLock */ |
109 | |
110 | static PRIntervalTime NonContentiousLock(PRUint32 loops) |
111 | { |
112 | PRLock *ml = NULL((void*)0); |
113 | ml = PR_NewLock(); |
114 | while (loops-- > 0) |
115 | { |
116 | PR_Lock(ml); |
117 | PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(ml)PR_AssertCurrentThreadOwnsLock(ml); |
118 | PR_Unlock(ml); |
119 | } |
120 | PR_DestroyLock(ml); |
121 | return 0; |
122 | } /* NonContentiousLock */ |
123 | |
124 | static void PR_CALLBACK LockContender(void *arg) |
125 | { |
126 | LockContentious_t *contention = (LockContentious_t*)arg; |
127 | while (contention->loops-- > 0) |
128 | { |
129 | PR_Lock(contention->ml); |
130 | PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(contention->ml)PR_AssertCurrentThreadOwnsLock(contention->ml); |
131 | contention->contender+= 1; |
132 | contention->overhead += contention->interval; |
133 | PR_Sleep(contention->interval); |
134 | PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(contention->ml)PR_AssertCurrentThreadOwnsLock(contention->ml); |
135 | PR_Unlock(contention->ml); |
136 | } |
137 | } /* LockContender */ |
138 | |
139 | static PRIntervalTime ContentiousLock(PRUint32 loops) |
140 | { |
141 | PRStatus status; |
142 | PRThread *thread = NULL((void*)0); |
143 | LockContentious_t * contention; |
144 | PRIntervalTime rv, overhead, timein = PR_IntervalNow(); |
145 | |
146 | contention = PR_NEWZAP(LockContentious_t)((LockContentious_t*)PR_Calloc(1, sizeof(LockContentious_t))); |
147 | contention->loops = loops; |
148 | contention->overhead = 0; |
149 | contention->ml = PR_NewLock(); |
150 | contention->interval = contention_interval; |
151 | thread = PR_CreateThread( |
152 | PR_USER_THREAD, LockContender, contention, |
153 | PR_PRIORITY_LOW, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); |
154 | PR_ASSERT(thread != NULL)((thread != ((void*)0))?((void)0):PR_Assert("thread != NULL", "../../../pr/tests/lock.c",154)); |
155 | |
156 | overhead = PR_IntervalNow() - timein; |
157 | |
158 | while (contention->loops-- > 0) |
159 | { |
160 | PR_Lock(contention->ml); |
161 | PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(contention->ml)PR_AssertCurrentThreadOwnsLock(contention->ml); |
162 | contention->contentious+= 1; |
163 | contention->overhead += contention->interval; |
164 | PR_Sleep(contention->interval); |
165 | PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(contention->ml)PR_AssertCurrentThreadOwnsLock(contention->ml); |
166 | PR_Unlock(contention->ml); |
167 | } |
168 | |
169 | timein = PR_IntervalNow(); |
170 | status = PR_JoinThread(thread); |
171 | PR_DestroyLock(contention->ml); |
172 | overhead += (PR_IntervalNow() - timein); |
173 | rv = overhead + contention->overhead; |
174 | if (verbosity) |
175 | PR_fprintf( |
176 | std_err, "Access ratio: %u to %u\n", |
177 | contention->contentious, contention->contender); |
178 | PR_Free(contention); |
179 | return rv; |
180 | } /* ContentiousLock */ |
181 | |
182 | /* |
183 | ** MONITORS |
184 | */ |
185 | static PRIntervalTime MakeMonitor(PRUint32 loops) |
186 | { |
187 | PRMonitor *ml = NULL((void*)0); |
188 | while (loops-- > 0) |
189 | { |
190 | ml = PR_NewMonitor(); |
191 | PR_DestroyMonitor(ml); |
192 | ml = NULL((void*)0); |
193 | } |
194 | return 0; |
195 | } /* MakeMonitor */ |
196 | |
197 | static PRIntervalTime NonContentiousMonitor(PRUint32 loops) |
198 | { |
199 | PRMonitor *ml = NULL((void*)0); |
200 | ml = PR_NewMonitor(); |
201 | while (loops-- > 0) |
202 | { |
203 | PR_EnterMonitor(ml); |
204 | PR_ASSERT_CURRENT_THREAD_IN_MONITOR(ml)PR_AssertCurrentThreadInMonitor(ml); |
205 | PR_ExitMonitor(ml); |
206 | } |
207 | PR_DestroyMonitor(ml); |
208 | return 0; |
209 | } /* NonContentiousMonitor */ |
210 | |
211 | static void PR_CALLBACK TryEntry(void *arg) |
212 | { |
213 | PRMonitor *ml = (PRMonitor*)arg; |
214 | if (debug_mode) { |
215 | PR_fprintf(std_err, "Reentrant thread created\n"); |
216 | } |
217 | PR_EnterMonitor(ml); |
218 | PR_ASSERT_CURRENT_THREAD_IN_MONITOR(ml)PR_AssertCurrentThreadInMonitor(ml); |
219 | if (debug_mode) { |
220 | PR_fprintf(std_err, "Reentrant thread acquired monitor\n"); |
221 | } |
222 | PR_ExitMonitor(ml); |
223 | if (debug_mode) { |
224 | PR_fprintf(std_err, "Reentrant thread released monitor\n"); |
225 | } |
226 | } /* TryEntry */ |
227 | |
228 | static PRIntervalTime ReentrantMonitor(PRUint32 loops) |
229 | { |
230 | PRStatus status; |
231 | PRThread *thread; |
232 | PRMonitor *ml = PR_NewMonitor(); |
233 | if (debug_mode) { |
234 | PR_fprintf(std_err, "\nMonitor created for reentrant test\n"); |
235 | } |
236 | |
237 | PR_EnterMonitor(ml); |
238 | PR_ASSERT_CURRENT_THREAD_IN_MONITOR(ml)PR_AssertCurrentThreadInMonitor(ml); |
239 | PR_EnterMonitor(ml); |
240 | PR_ASSERT_CURRENT_THREAD_IN_MONITOR(ml)PR_AssertCurrentThreadInMonitor(ml); |
241 | if (debug_mode) { |
242 | PR_fprintf(std_err, "Monitor acquired twice\n"); |
243 | } |
244 | |
245 | thread = PR_CreateThread( |
246 | PR_USER_THREAD, TryEntry, ml, |
247 | PR_PRIORITY_LOW, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); |
248 | PR_ASSERT(thread != NULL)((thread != ((void*)0))?((void)0):PR_Assert("thread != NULL", "../../../pr/tests/lock.c",248)); |
249 | PR_Sleep(PR_SecondsToInterval(1)); |
250 | PR_ASSERT_CURRENT_THREAD_IN_MONITOR(ml)PR_AssertCurrentThreadInMonitor(ml); |
251 | |
252 | PR_ExitMonitor(ml); |
253 | PR_ASSERT_CURRENT_THREAD_IN_MONITOR(ml)PR_AssertCurrentThreadInMonitor(ml); |
254 | if (debug_mode) { |
255 | PR_fprintf(std_err, "Monitor released first time\n"); |
256 | } |
257 | |
258 | PR_ExitMonitor(ml); |
259 | if (debug_mode) { |
260 | PR_fprintf(std_err, "Monitor released second time\n"); |
261 | } |
262 | |
263 | status = PR_JoinThread(thread); |
264 | if (debug_mode) PR_fprintf(std_err, |
265 | "Reentrant thread joined %s\n", |
266 | (status == PR_SUCCESS) ? "successfully" : "in error"); |
267 | |
268 | PR_DestroyMonitor(ml); |
269 | return 0; |
270 | } /* ReentrantMonitor */ |
271 | |
272 | static void PR_CALLBACK MonitorContender(void *arg) |
273 | { |
274 | MonitorContentious_t *contention = (MonitorContentious_t*)arg; |
275 | while (contention->loops-- > 0) |
276 | { |
277 | PR_EnterMonitor(contention->ml); |
278 | PR_ASSERT_CURRENT_THREAD_IN_MONITOR(contention->ml)PR_AssertCurrentThreadInMonitor(contention->ml); |
279 | contention->contender+= 1; |
280 | contention->overhead += contention->interval; |
281 | PR_Sleep(contention->interval); |
282 | PR_ASSERT_CURRENT_THREAD_IN_MONITOR(contention->ml)PR_AssertCurrentThreadInMonitor(contention->ml); |
283 | PR_ExitMonitor(contention->ml); |
284 | } |
285 | } /* MonitorContender */ |
286 | |
287 | static PRUint32 ContentiousMonitor(PRUint32 loops) |
288 | { |
289 | PRStatus status; |
290 | PRThread *thread = NULL((void*)0); |
291 | MonitorContentious_t * contention; |
292 | PRIntervalTime rv, overhead, timein = PR_IntervalNow(); |
293 | |
294 | contention = PR_NEWZAP(MonitorContentious_t)((MonitorContentious_t*)PR_Calloc(1, sizeof(MonitorContentious_t ))); |
295 | contention->loops = loops; |
296 | contention->overhead = 0; |
297 | contention->ml = PR_NewMonitor(); |
298 | contention->interval = contention_interval; |
299 | thread = PR_CreateThread( |
300 | PR_USER_THREAD, MonitorContender, contention, |
301 | PR_PRIORITY_LOW, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); |
302 | PR_ASSERT(thread != NULL)((thread != ((void*)0))?((void)0):PR_Assert("thread != NULL", "../../../pr/tests/lock.c",302)); |
303 | |
304 | overhead = PR_IntervalNow() - timein; |
305 | |
306 | while (contention->loops-- > 0) |
307 | { |
308 | PR_EnterMonitor(contention->ml); |
309 | PR_ASSERT_CURRENT_THREAD_IN_MONITOR(contention->ml)PR_AssertCurrentThreadInMonitor(contention->ml); |
310 | contention->contentious+= 1; |
311 | contention->overhead += contention->interval; |
312 | PR_Sleep(contention->interval); |
313 | PR_ASSERT_CURRENT_THREAD_IN_MONITOR(contention->ml)PR_AssertCurrentThreadInMonitor(contention->ml); |
314 | PR_ExitMonitor(contention->ml); |
315 | } |
316 | |
317 | timein = PR_IntervalNow(); |
318 | status = PR_JoinThread(thread); |
319 | PR_DestroyMonitor(contention->ml); |
320 | overhead += (PR_IntervalNow() - timein); |
321 | rv = overhead + contention->overhead; |
322 | if (verbosity) |
323 | PR_fprintf( |
324 | std_err, "Access ratio: %u to %u\n", |
325 | contention->contentious, contention->contender); |
326 | PR_Free(contention); |
327 | return rv; |
328 | } /* ContentiousMonitor */ |
329 | |
330 | /* |
331 | ** CACHED MONITORS |
332 | */ |
333 | static PRIntervalTime NonContentiousCMonitor(PRUint32 loops) |
334 | { |
335 | MonitorContentious_t contention; |
336 | while (loops-- > 0) |
337 | { |
338 | PR_CEnterMonitor(&contention); |
339 | PR_CExitMonitor(&contention); |
340 | } |
341 | return 0; |
342 | } /* NonContentiousCMonitor */ |
343 | |
344 | static void PR_CALLBACK Contender(void *arg) |
345 | { |
346 | MonitorContentious_t *contention = (MonitorContentious_t*)arg; |
347 | while (contention->loops-- > 0) |
348 | { |
349 | PR_CEnterMonitor(contention); |
350 | contention->contender+= 1; |
351 | contention->overhead += contention->interval; |
352 | PR_Sleep(contention->interval); |
353 | PR_CExitMonitor(contention); |
354 | } |
355 | } /* Contender */ |
356 | |
357 | static PRIntervalTime ContentiousCMonitor(PRUint32 loops) |
358 | { |
359 | PRStatus status; |
360 | PRThread *thread = NULL((void*)0); |
361 | MonitorContentious_t * contention; |
362 | PRIntervalTime overhead, timein = PR_IntervalNow(); |
363 | |
364 | contention = PR_NEWZAP(MonitorContentious_t)((MonitorContentious_t*)PR_Calloc(1, sizeof(MonitorContentious_t ))); |
365 | contention->ml = NULL((void*)0); |
366 | contention->loops = loops; |
367 | contention->interval = contention_interval; |
368 | thread = PR_CreateThread( |
369 | PR_USER_THREAD, Contender, contention, |
370 | PR_PRIORITY_LOW, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); |
371 | PR_ASSERT(thread != NULL)((thread != ((void*)0))?((void)0):PR_Assert("thread != NULL", "../../../pr/tests/lock.c",371)); |
372 | |
373 | overhead = PR_IntervalNow() - timein; |
374 | |
375 | while (contention->loops-- > 0) |
376 | { |
377 | PR_CEnterMonitor(contention); |
378 | contention->contentious+= 1; |
379 | contention->overhead += contention->interval; |
380 | PR_Sleep(contention->interval); |
381 | PR_CExitMonitor(contention); |
382 | } |
383 | |
384 | timein = PR_IntervalNow(); |
385 | status = PR_JoinThread(thread); |
Value stored to 'status' is never read | |
386 | overhead += (PR_IntervalNow() - timein); |
387 | overhead += overhead + contention->overhead; |
388 | if (verbosity) |
389 | PR_fprintf( |
390 | std_err, "Access ratio: %u to %u\n", |
391 | contention->contentious, contention->contender); |
392 | PR_Free(contention); |
393 | return overhead; |
394 | } /* ContentiousCMonitor */ |
395 | |
396 | static PRIntervalTime Test( |
397 | const char* msg, PRUint32 (*test)(PRUint32 loops), |
398 | PRUint32 loops, PRIntervalTime overhead) |
399 | { |
400 | /* |
401 | * overhead - overhead not measured by the test. |
402 | * duration - wall clock time it took to perform test. |
403 | * predicted - extra time test says should not be counted |
404 | * |
405 | * Time accountable to the test is duration - overhead - predicted |
406 | * All times are Intervals and accumulated for all iterations. |
407 | */ |
408 | PRFloat64 elapsed; |
409 | PRIntervalTime accountable, duration; |
410 | PRUintn spaces = PL_strlen(msg); |
411 | PRIntervalTime timeout, timein = PR_IntervalNow(); |
412 | PRIntervalTime predicted = test(loops); |
413 | timeout = PR_IntervalNow(); |
414 | duration = timeout - timein; |
415 | |
416 | if (debug_mode) |
417 | { |
418 | accountable = duration - predicted; |
419 | accountable -= overhead; |
420 | elapsed = (PRFloat64)PR_IntervalToMicroseconds(accountable); |
421 | PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "%s:", msg); |
422 | while (spaces++ < 50) { |
423 | PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), " "); |
424 | } |
425 | if ((PRInt32)accountable < 0) { |
426 | PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "*****.** usecs/iteration\n"); |
427 | } |
428 | else { |
429 | PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "%8.2f usecs/iteration\n", elapsed/loops); |
430 | } |
431 | } |
432 | return duration; |
433 | } /* Test */ |
434 | |
435 | int main(int argc, char **argv) |
436 | { |
437 | PRBool rv = PR_TRUE1; |
438 | PRIntervalTime duration; |
439 | PRUint32 cpu, cpus = 2, loops = 100; |
440 | |
441 | |
442 | PR_STDIO_INIT(); |
443 | PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); |
444 | { |
445 | /* The command line argument: -d is used to determine if the test is being run |
446 | in debug mode. The regress tool requires only one line output:PASS or FAIL. |
447 | All of the printfs associated with this test has been handled with a if (debug_mode) |
448 | test. |
449 | Command line argument -l <num> sets the number of loops. |
450 | Command line argument -c <num> sets the number of cpus. |
451 | Usage: lock [-d] [-l <num>] [-c <num>] |
452 | */ |
453 | PLOptStatus os; |
454 | PLOptState *opt = PL_CreateOptState(argc, argv, "dvl:c:"); |
455 | while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) |
456 | { |
457 | if (PL_OPT_BAD == os) { |
458 | continue; |
459 | } |
460 | switch (opt->option) |
461 | { |
462 | case 'd': /* debug mode */ |
463 | debug_mode = PR_TRUE1; |
464 | break; |
465 | case 'v': /* debug mode */ |
466 | verbosity = PR_TRUE1; |
467 | break; |
468 | case 'l': /* number of loops */ |
469 | loops = atoi(opt->value); |
470 | break; |
471 | case 'c': /* number of cpus */ |
472 | cpus = atoi(opt->value); |
473 | break; |
474 | default: |
475 | break; |
476 | } |
477 | } |
478 | PL_DestroyOptState(opt); |
479 | } |
480 | |
481 | /* main test */ |
482 | PR_SetConcurrency(8); |
483 | |
484 | if (loops == 0) { |
485 | loops = 100; |
486 | } |
487 | if (debug_mode) |
488 | { |
489 | std_err = PR_STDERRPR_GetSpecialFD(PR_StandardError); |
490 | PR_fprintf(std_err, "Lock: Using %d loops\n", loops); |
491 | } |
492 | |
493 | if (cpus == 0) { |
494 | cpus = 2; |
495 | } |
496 | if (debug_mode) { |
497 | PR_fprintf(std_err, "Lock: Using %d cpu(s)\n", cpus); |
498 | } |
499 | |
500 | (void)Sleeper(10); /* try filling in the caches */ |
501 | |
502 | for (cpu = 1; cpu <= cpus; ++cpu) |
503 | { |
504 | if (debug_mode) { |
505 | PR_fprintf(std_err, "\nLock: Using %d CPU(s)\n", cpu); |
506 | } |
507 | PR_SetConcurrency(cpu); |
508 | |
509 | duration = Test("Overhead of PR_Sleep", Sleeper, loops, 0); |
510 | duration = 0; |
511 | |
512 | (void)Test("Lock creation/deletion", MakeLock, loops, 0); |
513 | (void)Test("Lock non-contentious locking/unlocking", NonContentiousLock, loops, 0); |
514 | (void)Test("Lock contentious locking/unlocking", ContentiousLock, loops, duration); |
515 | (void)Test("Monitor creation/deletion", MakeMonitor, loops, 0); |
516 | (void)Test("Monitor non-contentious locking/unlocking", NonContentiousMonitor, loops, 0); |
517 | (void)Test("Monitor contentious locking/unlocking", ContentiousMonitor, loops, duration); |
518 | |
519 | (void)Test("Cached monitor non-contentious locking/unlocking", NonContentiousCMonitor, loops, 0); |
520 | (void)Test("Cached monitor contentious locking/unlocking", ContentiousCMonitor, loops, duration); |
521 | |
522 | (void)ReentrantMonitor(loops); |
523 | } |
524 | |
525 | if (debug_mode) |
526 | PR_fprintf( |
527 | std_err, "%s: test %s\n", "Lock(mutex) test", |
528 | ((rv) ? "passed" : "failed")); |
529 | else { |
530 | if (!rv) { |
531 | failed_already=1; |
532 | } |
533 | } |
534 | |
535 | if(failed_already) |
536 | { |
537 | PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "FAIL\n"); |
538 | return 1; |
539 | } |
540 | else |
541 | { |
542 | PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "PASS\n"); |
543 | return 0; |
544 | } |
545 | |
546 | } /* main */ |
547 | |
548 | /* testlock.c */ |