nsprpub/pr/tests/bug1test.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.

     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).
    10 */
    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
    19 {
    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)
    38 {
    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
    50     ;
    51   PR_Sleep(0); 
    52 }
    54 void  doWriteThread (void* arg)
    55 {
    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)
    62   {
    63     // -- enter write lock
    64     PR_EnterMonitor (gMonitor);
    66     if (0 < gReading)     // wait for read locks to go away
    67     {
    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--;
    76     }
    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);
    94   }
    95 }
    97 void  doReadThread (void* arg)
    98 {
    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)
   105   {
   106     // -- enter read lock
   107     PR_EnterMonitor (gMonitor); 
   109     if (0 < gWriteWaiting)  // give up the monitor to waiting writes
   110     {
   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--;
   119     }
   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);
   146   }
   147 }
   150 void fireThread (
   151     char* aName, void (*aProc)(void *arg), Arg_t *aArg)
   152 {
   153   PRThread *thread = PR_CreateThread(
   154 	  PR_USER_THREAD, aProc, aArg, PR_PRIORITY_NORMAL,
   155 	  PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0);
   156 }
   158 int pseudoMain (int argc, char** argv, char *pad)
   159 {
   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)
   191   {
   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;
   206   }
   207   return 0;
   208 }
   211 static void padStack (int argc, char** argv)
   212 {
   213   char pad[512];      /* Work around bug in nspr on windoze */
   214   pseudoMain (argc, argv, pad);
   215 }
   217 int main(int argc, char **argv)
   218 {
   219   PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
   220   PR_STDIO_INIT();
   221   padStack (argc, argv);
   222 }
   225 /* bug1test.c */

mercurial