tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

xnotify.c (10082B)


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