Bug Summary

File:pr/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/pr/tests/../../../pr/tests/lock.c
Warning:line 318, column 5
Value stored to 'status' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name lock.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nspr/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/pr/tests -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nspr/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/pr/tests -resource-dir /usr/lib/llvm-18/lib/clang/18 -U NDEBUG -D DEBUG_jenkins -D PACKAGE_NAME="" -D PACKAGE_TARNAME="" -D PACKAGE_VERSION="" -D PACKAGE_STRING="" -D PACKAGE_BUGREPORT="" -D PACKAGE_URL="" -D DEBUG=1 -D HAVE_VISIBILITY_HIDDEN_ATTRIBUTE=1 -D HAVE_VISIBILITY_PRAGMA=1 -D XP_UNIX=1 -D _GNU_SOURCE=1 -D HAVE_FCNTL_FILE_LOCKING=1 -D HAVE_POINTER_LOCALTIME_R=1 -D LINUX=1 -D HAVE_DLADDR=1 -D HAVE_GETTID=1 -D HAVE_LCHOWN=1 -D HAVE_SETPRIORITY=1 -D HAVE_STRERROR=1 -D HAVE_SYSCALL=1 -D HAVE_SECURE_GETENV=1 -D _REENTRANT=1 -D FORCE_PR_LOG -D _PR_PTHREADS -U HAVE_CVAR_BUILT_ON_SEM -I /var/lib/jenkins/workspace/nss-scan-build/nss/../dist/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/include -I ../../../pr/include -I ../../../pr/include/private -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -fno-inline -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-18-082241-28900-1 -x c ../../../pr/tests/lock.c
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
58static PRIntn failed_already=0;
59static PRFileDesc *std_err = NULL((void*)0);
60static PRBool verbosity = PR_FALSE0;
61static PRBool debug_mode = PR_FALSE0;
62
63const static PRIntervalTime contention_interval = 50;
64
65typedef 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
74typedef 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
84static 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*/
98static 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
110static 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
124static 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
139static 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*/
185static 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
197static 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
211static 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
228static 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
272static 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
287static 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);
Value stored to 'status' is never read
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*/
333static 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
344static 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
357static 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);
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
396static 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
435int 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 */