Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 #include "plerror.h"
7 #include "plgetopt.h"
9 #include "prinit.h"
10 #include "prprf.h"
11 #include "prio.h"
12 #include "prcvar.h"
13 #include "prmon.h"
14 #include "prcmon.h"
15 #include "prlock.h"
16 #include "prerror.h"
17 #include "prinit.h"
18 #include "prinrval.h"
19 #include "prthread.h"
21 static PRLock *ml = NULL;
22 static PRIntervalTime base;
23 static PRFileDesc *err = NULL;
25 typedef struct CMonShared
26 {
27 PRInt32 o1, o2;
28 } CMonShared;
30 typedef struct MonShared
31 {
32 PRMonitor *o1, *o2;
33 } MonShared;
35 typedef struct LockShared
36 {
37 PRLock *o1, *o2;
38 PRCondVar *cv1, *cv2;
39 } LockShared;
41 static void LogNow(const char *msg, PRStatus rv)
42 {
43 PRIntervalTime now = PR_IntervalNow();
44 PR_Lock(ml);
45 PR_fprintf(err, "%6ld: %s", (now - base), msg);
46 if (PR_FAILURE == rv) PL_FPrintError(err, " ");
47 else PR_fprintf(err, "\n");
48 PR_Unlock(ml);
49 } /* LogNow */
51 static void Help(void)
52 {
53 PR_fprintf(err, "Usage: [-[d][l][m][c]] [-h]\n");
54 PR_fprintf(err, "\t-d debug mode (default: FALSE)\n");
55 PR_fprintf(err, "\t-l test with locks (default: FALSE)\n");
56 PR_fprintf(err, "\t-m tests with monitors (default: FALSE)\n");
57 PR_fprintf(err, "\t-c tests with cmonitors (default: FALSE)\n");
58 PR_fprintf(err, "\t-h help\n");
59 } /* Help */
61 static void PR_CALLBACK T2CMon(void *arg)
62 {
63 PRStatus rv;
64 CMonShared *shared = (CMonShared*)arg;
66 PR_CEnterMonitor(&shared->o1);
67 LogNow("T2 waiting 5 seconds on o1", PR_SUCCESS);
68 rv = PR_CWait(&shared->o1, PR_SecondsToInterval(5));
69 if (PR_SUCCESS == rv) LogNow("T2 resuming on o1", rv);
70 else LogNow("T2 wait failed on o1", rv);
72 rv = PR_CNotify(&shared->o1);
73 if (PR_SUCCESS == rv) LogNow("T2 notified o1", rv);
74 else LogNow("T2 notify on o1 failed", rv);
76 PR_CExitMonitor(&shared->o1);
77 } /* T2CMon */
79 static void PR_CALLBACK T3CMon(void *arg)
80 {
81 PRStatus rv;
82 CMonShared *shared = (CMonShared*)arg;
84 PR_CEnterMonitor(&shared->o2);
85 LogNow("T3 waiting 5 seconds on o2", PR_SUCCESS);
86 rv = PR_CWait(&shared->o2, PR_SecondsToInterval(5));
87 if (PR_SUCCESS == rv) LogNow("T3 resuming on o2", rv);
88 else LogNow("T3 wait failed on o2", rv);
89 rv = PR_CNotify(&shared->o2);
90 LogNow("T3 notify on o2", rv);
91 PR_CExitMonitor(&shared->o2);
93 } /* T3CMon */
95 static CMonShared sharedCM;
97 static void T1CMon(void)
98 {
99 PRStatus rv;
100 PRThread *t2, *t3;
102 PR_fprintf(err, "\n**********************************\n");
103 PR_fprintf(err, " CACHED MONITORS\n");
104 PR_fprintf(err, "**********************************\n");
106 base = PR_IntervalNow();
108 PR_CEnterMonitor(&sharedCM.o1);
109 LogNow("T1 waiting 3 seconds on o1", PR_SUCCESS);
110 rv = PR_CWait(&sharedCM.o1, PR_SecondsToInterval(3));
111 if (PR_SUCCESS == rv) LogNow("T1 resuming on o1", rv);
112 else LogNow("T1 wait on o1 failed", rv);
113 PR_CExitMonitor(&sharedCM.o1);
115 LogNow("T1 creating T2", PR_SUCCESS);
116 t2 = PR_CreateThread(
117 PR_USER_THREAD, T2CMon, &sharedCM, PR_PRIORITY_NORMAL,
118 PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
120 LogNow("T1 creating T3", PR_SUCCESS);
121 t3 = PR_CreateThread(
122 PR_USER_THREAD, T3CMon, &sharedCM, PR_PRIORITY_NORMAL,
123 PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
125 PR_CEnterMonitor(&sharedCM.o2);
126 LogNow("T1 waiting forever on o2", PR_SUCCESS);
127 rv = PR_CWait(&sharedCM.o2, PR_INTERVAL_NO_TIMEOUT);
128 if (PR_SUCCESS == rv) LogNow("T1 resuming on o2", rv);
129 else LogNow("T1 wait on o2 failed", rv);
130 PR_CExitMonitor(&sharedCM.o2);
132 (void)PR_JoinThread(t2);
133 (void)PR_JoinThread(t3);
135 } /* T1CMon */
137 static void PR_CALLBACK T2Mon(void *arg)
138 {
139 PRStatus rv;
140 MonShared *shared = (MonShared*)arg;
142 PR_EnterMonitor(shared->o1);
143 LogNow("T2 waiting 5 seconds on o1", PR_SUCCESS);
144 rv = PR_Wait(shared->o1, PR_SecondsToInterval(5));
145 if (PR_SUCCESS == rv) LogNow("T2 resuming on o1", rv);
146 else LogNow("T2 wait failed on o1", rv);
148 rv = PR_Notify(shared->o1);
149 if (PR_SUCCESS == rv) LogNow("T2 notified o1", rv);
150 else LogNow("T2 notify on o1 failed", rv);
152 PR_ExitMonitor(shared->o1);
153 } /* T2Mon */
155 static void PR_CALLBACK T3Mon(void *arg)
156 {
157 PRStatus rv;
158 MonShared *shared = (MonShared*)arg;
160 PR_EnterMonitor(shared->o2);
161 LogNow("T3 waiting 5 seconds on o2", PR_SUCCESS);
162 rv = PR_Wait(shared->o2, PR_SecondsToInterval(5));
163 if (PR_SUCCESS == rv) LogNow("T3 resuming on o2", rv);
164 else LogNow("T3 wait failed on o2", rv);
165 rv = PR_Notify(shared->o2);
166 LogNow("T3 notify on o2", rv);
167 PR_ExitMonitor(shared->o2);
169 } /* T3Mon */
171 static MonShared sharedM;
172 static void T1Mon(void)
173 {
174 PRStatus rv;
175 PRThread *t2, *t3;
177 PR_fprintf(err, "\n**********************************\n");
178 PR_fprintf(err, " MONITORS\n");
179 PR_fprintf(err, "**********************************\n");
181 sharedM.o1 = PR_NewMonitor();
182 sharedM.o2 = PR_NewMonitor();
184 base = PR_IntervalNow();
186 PR_EnterMonitor(sharedM.o1);
187 LogNow("T1 waiting 3 seconds on o1", PR_SUCCESS);
188 rv = PR_Wait(sharedM.o1, PR_SecondsToInterval(3));
189 if (PR_SUCCESS == rv) LogNow("T1 resuming on o1", rv);
190 else LogNow("T1 wait on o1 failed", rv);
191 PR_ExitMonitor(sharedM.o1);
193 LogNow("T1 creating T2", PR_SUCCESS);
194 t2 = PR_CreateThread(
195 PR_USER_THREAD, T2Mon, &sharedM, PR_PRIORITY_NORMAL,
196 PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
198 LogNow("T1 creating T3", PR_SUCCESS);
199 t3 = PR_CreateThread(
200 PR_USER_THREAD, T3Mon, &sharedM, PR_PRIORITY_NORMAL,
201 PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
203 PR_EnterMonitor(sharedM.o2);
204 LogNow("T1 waiting forever on o2", PR_SUCCESS);
205 rv = PR_Wait(sharedM.o2, PR_INTERVAL_NO_TIMEOUT);
206 if (PR_SUCCESS == rv) LogNow("T1 resuming on o2", rv);
207 else LogNow("T1 wait on o2 failed", rv);
208 PR_ExitMonitor(sharedM.o2);
210 (void)PR_JoinThread(t2);
211 (void)PR_JoinThread(t3);
213 PR_DestroyMonitor(sharedM.o1);
214 PR_DestroyMonitor(sharedM.o2);
216 } /* T1Mon */
218 static void PR_CALLBACK T2Lock(void *arg)
219 {
220 PRStatus rv;
221 LockShared *shared = (LockShared*)arg;
223 PR_Lock(shared->o1);
224 LogNow("T2 waiting 5 seconds on o1", PR_SUCCESS);
225 rv = PR_WaitCondVar(shared->cv1, PR_SecondsToInterval(5));
226 if (PR_SUCCESS == rv) LogNow("T2 resuming on o1", rv);
227 else LogNow("T2 wait failed on o1", rv);
229 rv = PR_NotifyCondVar(shared->cv1);
230 if (PR_SUCCESS == rv) LogNow("T2 notified o1", rv);
231 else LogNow("T2 notify on o1 failed", rv);
233 PR_Unlock(shared->o1);
234 } /* T2Lock */
236 static void PR_CALLBACK T3Lock(void *arg)
237 {
238 PRStatus rv;
239 LockShared *shared = (LockShared*)arg;
241 PR_Lock(shared->o2);
242 LogNow("T3 waiting 5 seconds on o2", PR_SUCCESS);
243 rv = PR_WaitCondVar(shared->cv2, PR_SecondsToInterval(5));
244 if (PR_SUCCESS == rv) LogNow("T3 resuming on o2", rv);
245 else LogNow("T3 wait failed on o2", rv);
246 rv = PR_NotifyCondVar(shared->cv2);
247 LogNow("T3 notify on o2", rv);
248 PR_Unlock(shared->o2);
250 } /* T3Lock */
252 /*
253 ** Make shared' a static variable for Win16
254 */
255 static LockShared sharedL;
257 static void T1Lock(void)
258 {
259 PRStatus rv;
260 PRThread *t2, *t3;
261 sharedL.o1 = PR_NewLock();
262 sharedL.o2 = PR_NewLock();
263 sharedL.cv1 = PR_NewCondVar(sharedL.o1);
264 sharedL.cv2 = PR_NewCondVar(sharedL.o2);
266 PR_fprintf(err, "\n**********************************\n");
267 PR_fprintf(err, " LOCKS\n");
268 PR_fprintf(err, "**********************************\n");
270 base = PR_IntervalNow();
272 PR_Lock(sharedL.o1);
273 LogNow("T1 waiting 3 seconds on o1", PR_SUCCESS);
274 rv = PR_WaitCondVar(sharedL.cv1, PR_SecondsToInterval(3));
275 if (PR_SUCCESS == rv) LogNow("T1 resuming on o1", rv);
276 else LogNow("T1 wait on o1 failed", rv);
277 PR_Unlock(sharedL.o1);
279 LogNow("T1 creating T2", PR_SUCCESS);
280 t2 = PR_CreateThread(
281 PR_USER_THREAD, T2Lock, &sharedL, PR_PRIORITY_NORMAL,
282 PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
284 LogNow("T1 creating T3", PR_SUCCESS);
285 t3 = PR_CreateThread(
286 PR_USER_THREAD, T3Lock, &sharedL, PR_PRIORITY_NORMAL,
287 PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
289 PR_Lock(sharedL.o2);
290 LogNow("T1 waiting forever on o2", PR_SUCCESS);
291 rv = PR_WaitCondVar(sharedL.cv2, PR_INTERVAL_NO_TIMEOUT);
292 if (PR_SUCCESS == rv) LogNow("T1 resuming on o2", rv);
293 else LogNow("T1 wait on o2 failed", rv);
294 PR_Unlock(sharedL.o2);
296 (void)PR_JoinThread(t2);
297 (void)PR_JoinThread(t3);
299 PR_DestroyLock(sharedL.o1);
300 PR_DestroyLock(sharedL.o2);
301 PR_DestroyCondVar(sharedL.cv1);
302 PR_DestroyCondVar(sharedL.cv2);
303 } /* T1Lock */
305 static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv )
306 {
307 PLOptStatus os;
308 PLOptState *opt = PL_CreateOptState(argc, argv, "dhlmc");
309 PRBool locks = PR_FALSE, monitors = PR_FALSE, cmonitors = PR_FALSE;
311 err = PR_GetSpecialFD(PR_StandardError);
313 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
314 {
315 if (PL_OPT_BAD == os) continue;
316 switch (opt->option)
317 {
318 case 'd': /* debug mode (noop) */
319 break;
320 case 'l': /* locks */
321 locks = PR_TRUE;
322 break;
323 case 'm': /* monitors */
324 monitors = PR_TRUE;
325 break;
326 case 'c': /* cached monitors */
327 cmonitors = PR_TRUE;
328 break;
329 case 'h': /* needs guidance */
330 default:
331 Help();
332 return 2;
333 }
334 }
335 PL_DestroyOptState(opt);
337 ml = PR_NewLock();
338 if (locks) T1Lock();
339 if (monitors) T1Mon();
340 if (cmonitors) T1CMon();
342 PR_DestroyLock(ml);
344 PR_fprintf(err, "Done!\n");
345 return 0;
346 } /* main */
349 int main(int argc, char **argv)
350 {
351 PRIntn rv;
353 PR_STDIO_INIT();
354 rv = PR_Initialize(RealMain, argc, argv, 0);
355 return rv;
356 } /* main */
357 /* xnotify.c */