nsprpub/pr/tests/xnotify.c

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "plerror.h"
michael@0 7 #include "plgetopt.h"
michael@0 8
michael@0 9 #include "prinit.h"
michael@0 10 #include "prprf.h"
michael@0 11 #include "prio.h"
michael@0 12 #include "prcvar.h"
michael@0 13 #include "prmon.h"
michael@0 14 #include "prcmon.h"
michael@0 15 #include "prlock.h"
michael@0 16 #include "prerror.h"
michael@0 17 #include "prinit.h"
michael@0 18 #include "prinrval.h"
michael@0 19 #include "prthread.h"
michael@0 20
michael@0 21 static PRLock *ml = NULL;
michael@0 22 static PRIntervalTime base;
michael@0 23 static PRFileDesc *err = NULL;
michael@0 24
michael@0 25 typedef struct CMonShared
michael@0 26 {
michael@0 27 PRInt32 o1, o2;
michael@0 28 } CMonShared;
michael@0 29
michael@0 30 typedef struct MonShared
michael@0 31 {
michael@0 32 PRMonitor *o1, *o2;
michael@0 33 } MonShared;
michael@0 34
michael@0 35 typedef struct LockShared
michael@0 36 {
michael@0 37 PRLock *o1, *o2;
michael@0 38 PRCondVar *cv1, *cv2;
michael@0 39 } LockShared;
michael@0 40
michael@0 41 static void LogNow(const char *msg, PRStatus rv)
michael@0 42 {
michael@0 43 PRIntervalTime now = PR_IntervalNow();
michael@0 44 PR_Lock(ml);
michael@0 45 PR_fprintf(err, "%6ld: %s", (now - base), msg);
michael@0 46 if (PR_FAILURE == rv) PL_FPrintError(err, " ");
michael@0 47 else PR_fprintf(err, "\n");
michael@0 48 PR_Unlock(ml);
michael@0 49 } /* LogNow */
michael@0 50
michael@0 51 static void Help(void)
michael@0 52 {
michael@0 53 PR_fprintf(err, "Usage: [-[d][l][m][c]] [-h]\n");
michael@0 54 PR_fprintf(err, "\t-d debug mode (default: FALSE)\n");
michael@0 55 PR_fprintf(err, "\t-l test with locks (default: FALSE)\n");
michael@0 56 PR_fprintf(err, "\t-m tests with monitors (default: FALSE)\n");
michael@0 57 PR_fprintf(err, "\t-c tests with cmonitors (default: FALSE)\n");
michael@0 58 PR_fprintf(err, "\t-h help\n");
michael@0 59 } /* Help */
michael@0 60
michael@0 61 static void PR_CALLBACK T2CMon(void *arg)
michael@0 62 {
michael@0 63 PRStatus rv;
michael@0 64 CMonShared *shared = (CMonShared*)arg;
michael@0 65
michael@0 66 PR_CEnterMonitor(&shared->o1);
michael@0 67 LogNow("T2 waiting 5 seconds on o1", PR_SUCCESS);
michael@0 68 rv = PR_CWait(&shared->o1, PR_SecondsToInterval(5));
michael@0 69 if (PR_SUCCESS == rv) LogNow("T2 resuming on o1", rv);
michael@0 70 else LogNow("T2 wait failed on o1", rv);
michael@0 71
michael@0 72 rv = PR_CNotify(&shared->o1);
michael@0 73 if (PR_SUCCESS == rv) LogNow("T2 notified o1", rv);
michael@0 74 else LogNow("T2 notify on o1 failed", rv);
michael@0 75
michael@0 76 PR_CExitMonitor(&shared->o1);
michael@0 77 } /* T2CMon */
michael@0 78
michael@0 79 static void PR_CALLBACK T3CMon(void *arg)
michael@0 80 {
michael@0 81 PRStatus rv;
michael@0 82 CMonShared *shared = (CMonShared*)arg;
michael@0 83
michael@0 84 PR_CEnterMonitor(&shared->o2);
michael@0 85 LogNow("T3 waiting 5 seconds on o2", PR_SUCCESS);
michael@0 86 rv = PR_CWait(&shared->o2, PR_SecondsToInterval(5));
michael@0 87 if (PR_SUCCESS == rv) LogNow("T3 resuming on o2", rv);
michael@0 88 else LogNow("T3 wait failed on o2", rv);
michael@0 89 rv = PR_CNotify(&shared->o2);
michael@0 90 LogNow("T3 notify on o2", rv);
michael@0 91 PR_CExitMonitor(&shared->o2);
michael@0 92
michael@0 93 } /* T3CMon */
michael@0 94
michael@0 95 static CMonShared sharedCM;
michael@0 96
michael@0 97 static void T1CMon(void)
michael@0 98 {
michael@0 99 PRStatus rv;
michael@0 100 PRThread *t2, *t3;
michael@0 101
michael@0 102 PR_fprintf(err, "\n**********************************\n");
michael@0 103 PR_fprintf(err, " CACHED MONITORS\n");
michael@0 104 PR_fprintf(err, "**********************************\n");
michael@0 105
michael@0 106 base = PR_IntervalNow();
michael@0 107
michael@0 108 PR_CEnterMonitor(&sharedCM.o1);
michael@0 109 LogNow("T1 waiting 3 seconds on o1", PR_SUCCESS);
michael@0 110 rv = PR_CWait(&sharedCM.o1, PR_SecondsToInterval(3));
michael@0 111 if (PR_SUCCESS == rv) LogNow("T1 resuming on o1", rv);
michael@0 112 else LogNow("T1 wait on o1 failed", rv);
michael@0 113 PR_CExitMonitor(&sharedCM.o1);
michael@0 114
michael@0 115 LogNow("T1 creating T2", PR_SUCCESS);
michael@0 116 t2 = PR_CreateThread(
michael@0 117 PR_USER_THREAD, T2CMon, &sharedCM, PR_PRIORITY_NORMAL,
michael@0 118 PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
michael@0 119
michael@0 120 LogNow("T1 creating T3", PR_SUCCESS);
michael@0 121 t3 = PR_CreateThread(
michael@0 122 PR_USER_THREAD, T3CMon, &sharedCM, PR_PRIORITY_NORMAL,
michael@0 123 PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
michael@0 124
michael@0 125 PR_CEnterMonitor(&sharedCM.o2);
michael@0 126 LogNow("T1 waiting forever on o2", PR_SUCCESS);
michael@0 127 rv = PR_CWait(&sharedCM.o2, PR_INTERVAL_NO_TIMEOUT);
michael@0 128 if (PR_SUCCESS == rv) LogNow("T1 resuming on o2", rv);
michael@0 129 else LogNow("T1 wait on o2 failed", rv);
michael@0 130 PR_CExitMonitor(&sharedCM.o2);
michael@0 131
michael@0 132 (void)PR_JoinThread(t2);
michael@0 133 (void)PR_JoinThread(t3);
michael@0 134
michael@0 135 } /* T1CMon */
michael@0 136
michael@0 137 static void PR_CALLBACK T2Mon(void *arg)
michael@0 138 {
michael@0 139 PRStatus rv;
michael@0 140 MonShared *shared = (MonShared*)arg;
michael@0 141
michael@0 142 PR_EnterMonitor(shared->o1);
michael@0 143 LogNow("T2 waiting 5 seconds on o1", PR_SUCCESS);
michael@0 144 rv = PR_Wait(shared->o1, PR_SecondsToInterval(5));
michael@0 145 if (PR_SUCCESS == rv) LogNow("T2 resuming on o1", rv);
michael@0 146 else LogNow("T2 wait failed on o1", rv);
michael@0 147
michael@0 148 rv = PR_Notify(shared->o1);
michael@0 149 if (PR_SUCCESS == rv) LogNow("T2 notified o1", rv);
michael@0 150 else LogNow("T2 notify on o1 failed", rv);
michael@0 151
michael@0 152 PR_ExitMonitor(shared->o1);
michael@0 153 } /* T2Mon */
michael@0 154
michael@0 155 static void PR_CALLBACK T3Mon(void *arg)
michael@0 156 {
michael@0 157 PRStatus rv;
michael@0 158 MonShared *shared = (MonShared*)arg;
michael@0 159
michael@0 160 PR_EnterMonitor(shared->o2);
michael@0 161 LogNow("T3 waiting 5 seconds on o2", PR_SUCCESS);
michael@0 162 rv = PR_Wait(shared->o2, PR_SecondsToInterval(5));
michael@0 163 if (PR_SUCCESS == rv) LogNow("T3 resuming on o2", rv);
michael@0 164 else LogNow("T3 wait failed on o2", rv);
michael@0 165 rv = PR_Notify(shared->o2);
michael@0 166 LogNow("T3 notify on o2", rv);
michael@0 167 PR_ExitMonitor(shared->o2);
michael@0 168
michael@0 169 } /* T3Mon */
michael@0 170
michael@0 171 static MonShared sharedM;
michael@0 172 static void T1Mon(void)
michael@0 173 {
michael@0 174 PRStatus rv;
michael@0 175 PRThread *t2, *t3;
michael@0 176
michael@0 177 PR_fprintf(err, "\n**********************************\n");
michael@0 178 PR_fprintf(err, " MONITORS\n");
michael@0 179 PR_fprintf(err, "**********************************\n");
michael@0 180
michael@0 181 sharedM.o1 = PR_NewMonitor();
michael@0 182 sharedM.o2 = PR_NewMonitor();
michael@0 183
michael@0 184 base = PR_IntervalNow();
michael@0 185
michael@0 186 PR_EnterMonitor(sharedM.o1);
michael@0 187 LogNow("T1 waiting 3 seconds on o1", PR_SUCCESS);
michael@0 188 rv = PR_Wait(sharedM.o1, PR_SecondsToInterval(3));
michael@0 189 if (PR_SUCCESS == rv) LogNow("T1 resuming on o1", rv);
michael@0 190 else LogNow("T1 wait on o1 failed", rv);
michael@0 191 PR_ExitMonitor(sharedM.o1);
michael@0 192
michael@0 193 LogNow("T1 creating T2", PR_SUCCESS);
michael@0 194 t2 = PR_CreateThread(
michael@0 195 PR_USER_THREAD, T2Mon, &sharedM, PR_PRIORITY_NORMAL,
michael@0 196 PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
michael@0 197
michael@0 198 LogNow("T1 creating T3", PR_SUCCESS);
michael@0 199 t3 = PR_CreateThread(
michael@0 200 PR_USER_THREAD, T3Mon, &sharedM, PR_PRIORITY_NORMAL,
michael@0 201 PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
michael@0 202
michael@0 203 PR_EnterMonitor(sharedM.o2);
michael@0 204 LogNow("T1 waiting forever on o2", PR_SUCCESS);
michael@0 205 rv = PR_Wait(sharedM.o2, PR_INTERVAL_NO_TIMEOUT);
michael@0 206 if (PR_SUCCESS == rv) LogNow("T1 resuming on o2", rv);
michael@0 207 else LogNow("T1 wait on o2 failed", rv);
michael@0 208 PR_ExitMonitor(sharedM.o2);
michael@0 209
michael@0 210 (void)PR_JoinThread(t2);
michael@0 211 (void)PR_JoinThread(t3);
michael@0 212
michael@0 213 PR_DestroyMonitor(sharedM.o1);
michael@0 214 PR_DestroyMonitor(sharedM.o2);
michael@0 215
michael@0 216 } /* T1Mon */
michael@0 217
michael@0 218 static void PR_CALLBACK T2Lock(void *arg)
michael@0 219 {
michael@0 220 PRStatus rv;
michael@0 221 LockShared *shared = (LockShared*)arg;
michael@0 222
michael@0 223 PR_Lock(shared->o1);
michael@0 224 LogNow("T2 waiting 5 seconds on o1", PR_SUCCESS);
michael@0 225 rv = PR_WaitCondVar(shared->cv1, PR_SecondsToInterval(5));
michael@0 226 if (PR_SUCCESS == rv) LogNow("T2 resuming on o1", rv);
michael@0 227 else LogNow("T2 wait failed on o1", rv);
michael@0 228
michael@0 229 rv = PR_NotifyCondVar(shared->cv1);
michael@0 230 if (PR_SUCCESS == rv) LogNow("T2 notified o1", rv);
michael@0 231 else LogNow("T2 notify on o1 failed", rv);
michael@0 232
michael@0 233 PR_Unlock(shared->o1);
michael@0 234 } /* T2Lock */
michael@0 235
michael@0 236 static void PR_CALLBACK T3Lock(void *arg)
michael@0 237 {
michael@0 238 PRStatus rv;
michael@0 239 LockShared *shared = (LockShared*)arg;
michael@0 240
michael@0 241 PR_Lock(shared->o2);
michael@0 242 LogNow("T3 waiting 5 seconds on o2", PR_SUCCESS);
michael@0 243 rv = PR_WaitCondVar(shared->cv2, PR_SecondsToInterval(5));
michael@0 244 if (PR_SUCCESS == rv) LogNow("T3 resuming on o2", rv);
michael@0 245 else LogNow("T3 wait failed on o2", rv);
michael@0 246 rv = PR_NotifyCondVar(shared->cv2);
michael@0 247 LogNow("T3 notify on o2", rv);
michael@0 248 PR_Unlock(shared->o2);
michael@0 249
michael@0 250 } /* T3Lock */
michael@0 251
michael@0 252 /*
michael@0 253 ** Make shared' a static variable for Win16
michael@0 254 */
michael@0 255 static LockShared sharedL;
michael@0 256
michael@0 257 static void T1Lock(void)
michael@0 258 {
michael@0 259 PRStatus rv;
michael@0 260 PRThread *t2, *t3;
michael@0 261 sharedL.o1 = PR_NewLock();
michael@0 262 sharedL.o2 = PR_NewLock();
michael@0 263 sharedL.cv1 = PR_NewCondVar(sharedL.o1);
michael@0 264 sharedL.cv2 = PR_NewCondVar(sharedL.o2);
michael@0 265
michael@0 266 PR_fprintf(err, "\n**********************************\n");
michael@0 267 PR_fprintf(err, " LOCKS\n");
michael@0 268 PR_fprintf(err, "**********************************\n");
michael@0 269
michael@0 270 base = PR_IntervalNow();
michael@0 271
michael@0 272 PR_Lock(sharedL.o1);
michael@0 273 LogNow("T1 waiting 3 seconds on o1", PR_SUCCESS);
michael@0 274 rv = PR_WaitCondVar(sharedL.cv1, PR_SecondsToInterval(3));
michael@0 275 if (PR_SUCCESS == rv) LogNow("T1 resuming on o1", rv);
michael@0 276 else LogNow("T1 wait on o1 failed", rv);
michael@0 277 PR_Unlock(sharedL.o1);
michael@0 278
michael@0 279 LogNow("T1 creating T2", PR_SUCCESS);
michael@0 280 t2 = PR_CreateThread(
michael@0 281 PR_USER_THREAD, T2Lock, &sharedL, PR_PRIORITY_NORMAL,
michael@0 282 PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
michael@0 283
michael@0 284 LogNow("T1 creating T3", PR_SUCCESS);
michael@0 285 t3 = PR_CreateThread(
michael@0 286 PR_USER_THREAD, T3Lock, &sharedL, PR_PRIORITY_NORMAL,
michael@0 287 PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
michael@0 288
michael@0 289 PR_Lock(sharedL.o2);
michael@0 290 LogNow("T1 waiting forever on o2", PR_SUCCESS);
michael@0 291 rv = PR_WaitCondVar(sharedL.cv2, PR_INTERVAL_NO_TIMEOUT);
michael@0 292 if (PR_SUCCESS == rv) LogNow("T1 resuming on o2", rv);
michael@0 293 else LogNow("T1 wait on o2 failed", rv);
michael@0 294 PR_Unlock(sharedL.o2);
michael@0 295
michael@0 296 (void)PR_JoinThread(t2);
michael@0 297 (void)PR_JoinThread(t3);
michael@0 298
michael@0 299 PR_DestroyLock(sharedL.o1);
michael@0 300 PR_DestroyLock(sharedL.o2);
michael@0 301 PR_DestroyCondVar(sharedL.cv1);
michael@0 302 PR_DestroyCondVar(sharedL.cv2);
michael@0 303 } /* T1Lock */
michael@0 304
michael@0 305 static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv )
michael@0 306 {
michael@0 307 PLOptStatus os;
michael@0 308 PLOptState *opt = PL_CreateOptState(argc, argv, "dhlmc");
michael@0 309 PRBool locks = PR_FALSE, monitors = PR_FALSE, cmonitors = PR_FALSE;
michael@0 310
michael@0 311 err = PR_GetSpecialFD(PR_StandardError);
michael@0 312
michael@0 313 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
michael@0 314 {
michael@0 315 if (PL_OPT_BAD == os) continue;
michael@0 316 switch (opt->option)
michael@0 317 {
michael@0 318 case 'd': /* debug mode (noop) */
michael@0 319 break;
michael@0 320 case 'l': /* locks */
michael@0 321 locks = PR_TRUE;
michael@0 322 break;
michael@0 323 case 'm': /* monitors */
michael@0 324 monitors = PR_TRUE;
michael@0 325 break;
michael@0 326 case 'c': /* cached monitors */
michael@0 327 cmonitors = PR_TRUE;
michael@0 328 break;
michael@0 329 case 'h': /* needs guidance */
michael@0 330 default:
michael@0 331 Help();
michael@0 332 return 2;
michael@0 333 }
michael@0 334 }
michael@0 335 PL_DestroyOptState(opt);
michael@0 336
michael@0 337 ml = PR_NewLock();
michael@0 338 if (locks) T1Lock();
michael@0 339 if (monitors) T1Mon();
michael@0 340 if (cmonitors) T1CMon();
michael@0 341
michael@0 342 PR_DestroyLock(ml);
michael@0 343
michael@0 344 PR_fprintf(err, "Done!\n");
michael@0 345 return 0;
michael@0 346 } /* main */
michael@0 347
michael@0 348
michael@0 349 int main(int argc, char **argv)
michael@0 350 {
michael@0 351 PRIntn rv;
michael@0 352
michael@0 353 PR_STDIO_INIT();
michael@0 354 rv = PR_Initialize(RealMain, argc, argv, 0);
michael@0 355 return rv;
michael@0 356 } /* main */
michael@0 357 /* xnotify.c */

mercurial