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 ** Purpose: test basic locking functions
9 ** Just because this times stuff, don't think its a perforamnce
12 ** Modification History:
13 ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
14 ** The debug mode will print all of the printfs associated with this test.
15 ** The regress mode will be the default mode. Since the regress tool limits
16 ** the output to a one line status:PASS or FAIL,all of the printf statements
17 ** have been handled with an if (debug_mode) statement.
18 ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
19 ** recognize the return code from tha main program.
20 ***********************************************************************/
21 /***********************************************************************
23 ***********************************************************************/
24 /* Used to get the command line option */
37 #include "private/pprio.h"
43 PRIntn failed_already
=0;
46 const static PRIntervalTime contention_interval
= 50;
48 typedef struct LockContentious_s
{
51 PRIntervalTime overhead
;
52 PRIntervalTime interval
;
55 #define LOCKFILE "prlock.fil"
59 static PRIntervalTime
NonContentiousLock(PRInt32 loops
)
61 PRFileDesc
*_lockfile
;
64 _lockfile
= PR_Open(LOCKFILE
, PR_CREATE_FILE
|PR_RDWR
, 0666);
66 if (debug_mode
) printf(
67 "could not create lockfile: %d [%d]\n",
68 PR_GetError(), PR_GetOSError());
69 return PR_INTERVAL_NO_TIMEOUT
;
71 PR_LockFile(_lockfile
);
72 PR_UnlockFile(_lockfile
);
76 } /* NonContentiousLock */
78 static void PR_CALLBACK
LockContender(void *arg
)
80 LockContentious_t
*contention
= (LockContentious_t
*)arg
;
81 PRFileDesc
*_lockfile
;
82 while (contention
->loops
-- > 0)
84 _lockfile
= PR_Open(LOCKFILE
, PR_CREATE_FILE
|PR_RDWR
, 0666);
86 if (debug_mode
) printf(
87 "could not create lockfile: %d [%d]\n",
88 PR_GetError(), PR_GetOSError());
91 PR_LockFile(_lockfile
);
92 PR_Sleep(contention
->interval
);
93 PR_UnlockFile(_lockfile
);
100 ** Win16 requires things passed to Threads not be on the stack
102 static LockContentious_t contention
;
104 static PRIntervalTime
ContentiousLock(PRInt32 loops
)
107 PRThread
*thread
= NULL
;
108 PRIntervalTime overhead
, timein
= PR_IntervalNow();
110 contention
.loops
= loops
;
111 contention
.overhead
= 0;
112 contention
.ml
= PR_NewLock();
113 contention
.interval
= contention_interval
;
114 thread
= PR_CreateThread(
115 PR_USER_THREAD
, LockContender
, &contention
,
116 PR_PRIORITY_LOW
, PR_LOCAL_THREAD
, PR_JOINABLE_THREAD
, 0);
117 PR_ASSERT(thread
!= NULL
);
119 overhead
= PR_IntervalNow() - timein
;
121 while (contention
.loops
> 0)
123 PR_Lock(contention
.ml
);
124 contention
.overhead
+= contention
.interval
;
125 PR_Sleep(contention
.interval
);
126 PR_Unlock(contention
.ml
);
129 timein
= PR_IntervalNow();
130 status
= PR_JoinThread(thread
);
131 PR_DestroyLock(contention
.ml
);
132 overhead
+= (PR_IntervalNow() - timein
);
133 return overhead
+ contention
.overhead
;
134 } /* ContentiousLock */
136 static PRIntervalTime
Test(
137 const char* msg
, PRIntervalTime (*test
)(PRInt32 loops
),
138 PRInt32 loops
, PRIntervalTime overhead
)
141 * overhead - overhead not measured by the test.
142 * duration - wall clock time it took to perform test.
143 * predicted - extra time test says should not be counted
145 * Time accountable to the test is duration - overhead - predicted
146 * All times are Intervals and accumulated for all iterations.
149 PRIntervalTime accountable
, duration
;
150 PRUintn spaces
= strlen(msg
);
151 PRIntervalTime timeout
, timein
= PR_IntervalNow();
152 PRIntervalTime predicted
= test(loops
);
153 timeout
= PR_IntervalNow();
154 duration
= timeout
- timein
;
155 accountable
= duration
- predicted
;
156 accountable
-= overhead
;
157 elapsed
= (PRFloat64
)PR_IntervalToMicroseconds(accountable
);
161 while (spaces
++ < 50) if (debug_mode
) {
164 if ((PRInt32
)accountable
< 0) {
166 printf("*****.** usecs/iteration\n");
170 printf("%8.2f usecs/iteration\n", elapsed
/loops
);
176 int main(int argc
, char **argv
)
178 PRIntervalTime duration
;
179 PRUint32 cpu
, cpus
= 2;
183 /* The command line argument: -d is used to determine if the test is being run
184 in debug mode. The regress tool requires only one line output:PASS or FAIL.
185 All of the printfs associated with this test has been handled with a if (debug_mode)
190 PLOptState
*opt
= PL_CreateOptState(argc
, argv
, "d:");
191 while (PL_OPT_EOL
!= (os
= PL_GetNextOpt(opt
)))
193 if (PL_OPT_BAD
== os
) {
198 case 'd': /* debug mode */
205 PL_DestroyOptState(opt
);
209 PR_Init(PR_USER_THREAD
, PR_PRIORITY_NORMAL
, 0);
213 loops
= atoi(argv
[1]);
219 printf("Lock: Using %d loops\n", loops
);
222 cpus
= (argc
< 3) ? 2 : atoi(argv
[2]);
227 printf("Lock: Using %d cpu(s)\n", cpus
);
231 for (cpu
= 1; cpu
<= cpus
; ++cpu
)
234 printf("\nLockFile: Using %d CPU(s)\n", cpu
);
236 PR_SetConcurrency(cpu
);
238 duration
= Test("LockFile non-contentious locking/unlocking", NonContentiousLock
, loops
, 0);
239 (void)Test("LockFile contentious locking/unlocking", ContentiousLock
, loops
, duration
);
242 PR_Delete(LOCKFILE
); /* try to get rid of evidence */
245 printf("%s: test %s\n", "Lock(mutex) test", ((failed_already
) ? "failed" : "passed"));