Bug 1845715 - Check for failure when getting RegExp match result template r=iain
[gecko.git] / nsprpub / pr / tests / cvar.c
blob4dc891d3f9cdb8af05c2577ba75cdaca2bf684ce
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/. */
6 /***********************************************************************
7 ** 1996 - Netscape Communications Corporation
8 **
9 ** Name: cvar.c
11 ** Description: Tests Condition Variable Operations
13 ** Modification History:
14 ** 13-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
15 ** The debug mode will print all of the printfs associated with this test.
16 ** The regress mode will be the default mode. Since the regress tool limits
17 ** the output to a one line status:PASS or FAIL,all of the printf statements
18 ** have been handled with an if (debug_mode) statement.
19 ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
20 ** recognize the return code from tha main program.
21 ** 12-June-97 Revert to return code 0 and 1.
22 ***********************************************************************/
24 /***********************************************************************
25 ** Includes
26 ***********************************************************************/
28 #include "nspr.h"
30 /* Used to get the command line option */
31 #include "plgetopt.h"
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
37 PRMonitor *mon;
38 #define DEFAULT_COUNT 1000
39 PRInt32 count = 0;
40 PRIntn debug_mode;
42 #define kQSIZE 1
44 typedef struct {
45 PRLock *bufLock;
46 int startIdx;
47 int numFull;
48 PRCondVar *notFull;
49 PRCondVar *notEmpty;
50 void *data[kQSIZE];
51 } CircBuf;
53 static PRBool failed = PR_FALSE;
56 ** NewCB creates and initializes a new circular buffer.
58 static CircBuf* NewCB(void)
60 CircBuf *cbp;
62 cbp = PR_NEW(CircBuf);
63 if (cbp == NULL) {
64 return (NULL);
67 cbp->bufLock = PR_NewLock();
68 cbp->startIdx = 0;
69 cbp->numFull = 0;
70 cbp->notFull = PR_NewCondVar(cbp->bufLock);
71 cbp->notEmpty = PR_NewCondVar(cbp->bufLock);
73 return (cbp);
77 ** DeleteCB frees a circular buffer.
79 static void DeleteCB(CircBuf *cbp)
81 PR_DestroyLock(cbp->bufLock);
82 PR_DestroyCondVar(cbp->notFull);
83 PR_DestroyCondVar(cbp->notEmpty);
84 PR_DELETE(cbp);
89 ** PutCBData puts new data on the queue. If the queue is full, it waits
90 ** until there is room.
92 static void PutCBData(CircBuf *cbp, void *data)
94 PR_Lock(cbp->bufLock);
95 /* wait while the buffer is full */
96 while (cbp->numFull == kQSIZE) {
97 PR_WaitCondVar(cbp->notFull,PR_INTERVAL_NO_TIMEOUT);
99 cbp->data[(cbp->startIdx + cbp->numFull) % kQSIZE] = data;
100 cbp->numFull += 1;
102 /* let a waiting reader know that there is data */
103 PR_NotifyCondVar(cbp->notEmpty);
104 PR_Unlock(cbp->bufLock);
110 ** GetCBData gets the oldest data on the queue. If the queue is empty, it waits
111 ** until new data appears.
113 static void* GetCBData(CircBuf *cbp)
115 void *data;
117 PR_Lock(cbp->bufLock);
118 /* wait while the buffer is empty */
119 while (cbp->numFull == 0) {
120 PR_WaitCondVar(cbp->notEmpty,PR_INTERVAL_NO_TIMEOUT);
122 data = cbp->data[cbp->startIdx];
123 cbp->startIdx =(cbp->startIdx + 1) % kQSIZE;
124 cbp->numFull -= 1;
126 /* let a waiting writer know that there is room */
127 PR_NotifyCondVar(cbp->notFull);
128 PR_Unlock(cbp->bufLock);
130 return (data);
134 /************************************************************************/
136 static int alive;
138 static void PR_CALLBACK CXReader(void *arg)
140 CircBuf *cbp = (CircBuf *)arg;
141 PRInt32 i, n;
142 void *data;
144 n = count / 2;
145 for (i = 0; i < n; i++) {
146 data = GetCBData(cbp);
147 if ((int)data != i)
148 if (debug_mode) {
149 printf("data mismatch at for i = %d usec\n", i);
153 PR_EnterMonitor(mon);
154 --alive;
155 PR_Notify(mon);
156 PR_ExitMonitor(mon);
159 static void PR_CALLBACK CXWriter(void *arg)
161 CircBuf *cbp = (CircBuf *)arg;
162 PRInt32 i, n;
164 n = count / 2;
165 for (i = 0; i < n; i++) {
166 PutCBData(cbp, (void *)i);
169 PR_EnterMonitor(mon);
170 --alive;
171 PR_Notify(mon);
172 PR_ExitMonitor(mon);
175 static void CondWaitContextSwitch(PRThreadScope scope1, PRThreadScope scope2)
177 PRThread *t1, *t2;
178 CircBuf *cbp;
180 PR_EnterMonitor(mon);
182 alive = 2;
184 cbp = NewCB();
186 t1 = PR_CreateThread(PR_USER_THREAD,
187 CXReader, cbp,
188 PR_PRIORITY_NORMAL,
189 scope1,
190 PR_UNJOINABLE_THREAD,
192 PR_ASSERT(t1);
193 t2 = PR_CreateThread(PR_USER_THREAD,
194 CXWriter, cbp,
195 PR_PRIORITY_NORMAL,
196 scope2,
197 PR_UNJOINABLE_THREAD,
199 PR_ASSERT(t2);
201 /* Wait for both of the threads to exit */
202 while (alive) {
203 PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
206 DeleteCB(cbp);
208 PR_ExitMonitor(mon);
211 static void CondWaitContextSwitchUU(void)
213 CondWaitContextSwitch(PR_LOCAL_THREAD, PR_LOCAL_THREAD);
216 static void CondWaitContextSwitchUK(void)
218 CondWaitContextSwitch(PR_LOCAL_THREAD, PR_GLOBAL_THREAD);
221 static void CondWaitContextSwitchKK(void)
223 CondWaitContextSwitch(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD);
226 /************************************************************************/
228 static void Measure(void (*func)(void), const char *msg)
230 PRIntervalTime start, stop;
231 double d;
233 start = PR_IntervalNow();
234 (*func)();
235 stop = PR_IntervalNow();
237 d = (double)PR_IntervalToMicroseconds(stop - start);
239 if (debug_mode) {
240 printf("%40s: %6.2f usec\n", msg, d / count);
243 if (0 == d) {
244 failed = PR_TRUE;
248 static PRIntn PR_CALLBACK RealMain(int argc, char **argv)
250 /* The command line argument: -d is used to determine if the test is being run
251 in debug mode. The regress tool requires only one line output:PASS or FAIL.
252 All of the printfs associated with this test has been handled with a if (debug_mode)
253 test.
254 Usage: test_name [-d] [-c n]
256 PLOptStatus os;
257 PLOptState *opt = PL_CreateOptState(argc, argv, "dc:");
258 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
260 if (PL_OPT_BAD == os) {
261 continue;
263 switch (opt->option)
265 case 'd': /* debug mode */
266 debug_mode = 1;
267 break;
268 case 'c': /* loop count */
269 count = atoi(opt->value);
270 break;
271 default:
272 break;
275 PL_DestroyOptState(opt);
277 if (0 == count) {
278 count = DEFAULT_COUNT;
281 mon = PR_NewMonitor();
283 Measure(CondWaitContextSwitchUU, "cond var wait context switch- user/user");
284 Measure(CondWaitContextSwitchUK, "cond var wait context switch- user/kernel");
285 Measure(CondWaitContextSwitchKK, "cond var wait context switch- kernel/kernel");
287 PR_DestroyMonitor(mon);
289 if (debug_mode) {
290 printf("%s\n", (failed) ? "FAILED" : "PASSED");
293 if(failed) {
294 return 1;
296 else {
297 return 0;
302 int main(int argc, char *argv[])
304 PRIntn rv;
306 PR_STDIO_INIT();
307 rv = PR_Initialize(RealMain, argc, argv, 0);
308 return rv;
309 } /* main */