backout 29799f914cab, Bug 917642 - [Helix] Please update the helix blobs
[gecko.git] / nsprpub / pr / tests / bug1test.c
bloba8df97f70c0246117ab95208ae88af16ae4451d3
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 Attached is a test program that uses the nspr1 to demonstrate a bug
8 under NT4.0. The fix has already been mentioned (add a ResetEvent just
9 before leaving the critical section in _PR_CondWait in hwmon.c).
12 #include "prthread.h"
13 #include "prtypes.h"
14 #include "prinit.h"
15 #include "prmon.h"
16 #include "prlog.h"
18 typedef struct Arg_s
20 PRInt32 a, b;
21 } Arg_t;
23 PRMonitor* gMonitor; // the monitor
24 PRInt32 gReading; // number of read locks
25 PRInt32 gWriteWaiting; // number of threads waiting for write lock
26 PRInt32 gReadWaiting; // number of threads waiting for read lock
28 PRInt32 gCounter; // a counter
30 // stats
31 PRInt32 gReads; // number of successful reads
32 PRInt32 gMaxReads; // max number of simultaneous reads
33 PRInt32 gMaxWriteWaits; // max number of writes that waited for read
34 PRInt32 gMaxReadWaits; // max number of reads that waited for write wait
37 void spin (PRInt32 aDelay)
39 PRInt32 index;
40 PRInt32 delay = aDelay * 1000;
42 PR_Sleep(0);
44 // randomize delay a bit
45 delay = (delay / 2) + (PRInt32)((float)delay *
46 ((float)rand () / (float)RAND_MAX));
48 for (index = 0; index < delay * 10; index++)
49 // consume a bunch of cpu cycles
51 PR_Sleep(0);
54 void doWriteThread (void* arg)
56 PRInt32 last;
57 Arg_t *args = (Arg_t*)arg;
58 PRInt32 aWorkDelay = args->a, aWaitDelay = args->b;
59 PR_Sleep(0);
61 while (1)
63 // -- enter write lock
64 PR_EnterMonitor (gMonitor);
66 if (0 < gReading) // wait for read locks to go away
68 PRIntervalTime fiveSecs = PR_SecondsToInterval(5);
70 gWriteWaiting++;
71 if (gWriteWaiting > gMaxWriteWaits) // stats
72 gMaxWriteWaits = gWriteWaiting;
73 while (0 < gReading)
74 PR_Wait (gMonitor, fiveSecs);
75 gWriteWaiting--;
77 // -- write lock entered
79 last = gCounter;
80 gCounter++;
82 spin (aWorkDelay);
84 PR_ASSERT (gCounter == (last + 1)); // test invariance
86 // -- exit write lock
87 // if (0 < gReadWaiting) // notify waiting reads (do it anyway to show off the CondWait bug)
88 PR_NotifyAll (gMonitor);
90 PR_ExitMonitor (gMonitor);
91 // -- write lock exited
93 spin (aWaitDelay);
97 void doReadThread (void* arg)
99 PRInt32 last;
100 Arg_t *args = (Arg_t*)arg;
101 PRInt32 aWorkDelay = args->a, aWaitDelay = args->b;
102 PR_Sleep(0);
104 while (1)
106 // -- enter read lock
107 PR_EnterMonitor (gMonitor);
109 if (0 < gWriteWaiting) // give up the monitor to waiting writes
111 PRIntervalTime fiveSecs = PR_SecondsToInterval(5);
113 gReadWaiting++;
114 if (gReadWaiting > gMaxReadWaits) // stats
115 gMaxReadWaits = gReadWaiting;
116 while (0 < gWriteWaiting)
117 PR_Wait (gMonitor, fiveSecs);
118 gReadWaiting--;
121 gReading++;
123 gReads++; // stats
124 if (gReading > gMaxReads) // stats
125 gMaxReads = gReading;
127 PR_ExitMonitor (gMonitor);
128 // -- read lock entered
130 last = gCounter;
132 spin (aWorkDelay);
134 PR_ASSERT (gCounter == last); // test invariance
136 // -- exit read lock
137 PR_EnterMonitor (gMonitor); // read unlock
138 gReading--;
140 // if ((0 == gReading) && (0 < gWriteWaiting)) // notify waiting writes (do it anyway to show off the CondWait bug)
141 PR_NotifyAll (gMonitor);
142 PR_ExitMonitor (gMonitor);
143 // -- read lock exited
145 spin (aWaitDelay);
150 void fireThread (
151 char* aName, void (*aProc)(void *arg), Arg_t *aArg)
153 PRThread *thread = PR_CreateThread(
154 PR_USER_THREAD, aProc, aArg, PR_PRIORITY_NORMAL,
155 PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0);
158 int pseudoMain (int argc, char** argv, char *pad)
160 PRInt32 lastWriteCount = gCounter;
161 PRInt32 lastReadCount = gReads;
162 Arg_t a1 = {500, 250};
163 Arg_t a2 = {500, 500};
164 Arg_t a3 = {250, 500};
165 Arg_t a4 = {750, 250};
166 Arg_t a5 = {100, 750};
167 Arg_t a6 = {100, 500};
168 Arg_t a7 = {100, 750};
170 gMonitor = PR_NewMonitor ();
172 fireThread ("R1", doReadThread, &a1);
173 fireThread ("R2", doReadThread, &a2);
174 fireThread ("R3", doReadThread, &a3);
175 fireThread ("R4", doReadThread, &a4);
177 fireThread ("W1", doWriteThread, &a5);
178 fireThread ("W2", doWriteThread, &a6);
179 fireThread ("W3", doWriteThread, &a7);
181 fireThread ("R5", doReadThread, &a1);
182 fireThread ("R6", doReadThread, &a2);
183 fireThread ("R7", doReadThread, &a3);
184 fireThread ("R8", doReadThread, &a4);
186 fireThread ("W4", doWriteThread, &a5);
187 fireThread ("W5", doWriteThread, &a6);
188 fireThread ("W6", doWriteThread, &a7);
190 while (1)
192 PRInt32 writeCount, readCount;
193 PRIntervalTime fiveSecs = PR_SecondsToInterval(5);
194 PR_Sleep (fiveSecs); // get out of the way
196 // print some stats, not threadsafe, informative only
197 writeCount = gCounter;
198 readCount = gReads;
199 printf ("\ntick %d writes (+%d), %d reads (+%d) [max %d, %d, %d]",
200 writeCount, writeCount - lastWriteCount,
201 readCount, readCount - lastReadCount,
202 gMaxReads, gMaxWriteWaits, gMaxReadWaits);
203 lastWriteCount = writeCount;
204 lastReadCount = readCount;
205 gMaxReads = gMaxWriteWaits = gMaxReadWaits = 0;
207 return 0;
211 static void padStack (int argc, char** argv)
213 char pad[512]; /* Work around bug in nspr on windoze */
214 pseudoMain (argc, argv, pad);
217 int main(int argc, char **argv)
219 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
220 PR_STDIO_INIT();
221 padStack (argc, argv);
225 /* bug1test.c */