tor-browser

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

lockfile.c (6939B)


      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 /*
      7 ** File:        lockfile.c
      8 ** Purpose:     test basic locking functions
      9 **              Just because this times stuff, don't think its a perforamnce
     10 **              test!!!
     11 **
     12 ** Modification History:
     13 ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
     14 **           The debug mode will print all of the printfs associated with this
     15 *test.
     16 **           The regress mode will be the default mode. Since the regress tool
     17 *limits
     18 **           the output to a one line status:PASS or FAIL,all of the printf
     19 *statements
     20 **           have been handled with an if (debug_mode) statement.
     21 ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been
     22 *updated to
     23 **          recognize the return code from tha main program.
     24 ***********************************************************************/
     25 /***********************************************************************
     26 ** Includes
     27 ***********************************************************************/
     28 /* Used to get the command line option */
     29 #include "plgetopt.h"
     30 
     31 #include "prcmon.h"
     32 #include "prerror.h"
     33 #include "prinit.h"
     34 #include "prinrval.h"
     35 #include "prlock.h"
     36 #include "prlog.h"
     37 #include "prmon.h"
     38 #include "prthread.h"
     39 #include "prtypes.h"
     40 
     41 #include "private/pprio.h"
     42 
     43 #include <stdio.h>
     44 #include <stdlib.h>
     45 #include <string.h>
     46 
     47 PRIntn failed_already = 0;
     48 PRIntn debug_mode;
     49 
     50 const static PRIntervalTime contention_interval = 50;
     51 
     52 typedef struct LockContentious_s {
     53  PRLock* ml;
     54  PRInt32 loops;
     55  PRIntervalTime overhead;
     56  PRIntervalTime interval;
     57 } LockContentious_t;
     58 
     59 #define LOCKFILE "prlock.fil"
     60 
     61 static PRIntervalTime NonContentiousLock(PRInt32 loops) {
     62  PRFileDesc* _lockfile;
     63  while (loops-- > 0) {
     64    _lockfile = PR_Open(LOCKFILE, PR_CREATE_FILE | PR_RDWR, 0666);
     65    if (!_lockfile) {
     66      if (debug_mode)
     67        printf("could not create lockfile: %d [%d]\n", PR_GetError(),
     68               PR_GetOSError());
     69      return PR_INTERVAL_NO_TIMEOUT;
     70    }
     71    PR_LockFile(_lockfile);
     72    PR_UnlockFile(_lockfile);
     73    PR_Close(_lockfile);
     74  }
     75  return 0;
     76 } /* NonContentiousLock */
     77 
     78 static void PR_CALLBACK LockContender(void* arg) {
     79  LockContentious_t* contention = (LockContentious_t*)arg;
     80  PRFileDesc* _lockfile;
     81  while (contention->loops-- > 0) {
     82    _lockfile = PR_Open(LOCKFILE, PR_CREATE_FILE | PR_RDWR, 0666);
     83    if (!_lockfile) {
     84      if (debug_mode)
     85        printf("could not create lockfile: %d [%d]\n", PR_GetError(),
     86               PR_GetOSError());
     87      break;
     88    }
     89    PR_LockFile(_lockfile);
     90    PR_Sleep(contention->interval);
     91    PR_UnlockFile(_lockfile);
     92    PR_Close(_lockfile);
     93  }
     94 
     95 } /* LockContender */
     96 
     97 /*
     98 ** Win16 requires things passed to Threads not be on the stack
     99 */
    100 static LockContentious_t contention;
    101 
    102 static PRIntervalTime ContentiousLock(PRInt32 loops) {
    103  PRStatus status;
    104  PRThread* thread = NULL;
    105  PRIntervalTime overhead, timein = PR_IntervalNow();
    106 
    107  contention.loops = loops;
    108  contention.overhead = 0;
    109  contention.ml = PR_NewLock();
    110  contention.interval = contention_interval;
    111  thread =
    112      PR_CreateThread(PR_USER_THREAD, LockContender, &contention,
    113                      PR_PRIORITY_LOW, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
    114  PR_ASSERT(thread != NULL);
    115 
    116  overhead = PR_IntervalNow() - timein;
    117 
    118  while (contention.loops > 0) {
    119    PR_Lock(contention.ml);
    120    contention.overhead += contention.interval;
    121    PR_Sleep(contention.interval);
    122    PR_Unlock(contention.ml);
    123  }
    124 
    125  timein = PR_IntervalNow();
    126  status = PR_JoinThread(thread);
    127  PR_DestroyLock(contention.ml);
    128  overhead += (PR_IntervalNow() - timein);
    129  return overhead + contention.overhead;
    130 } /* ContentiousLock */
    131 
    132 static PRIntervalTime Test(const char* msg,
    133                           PRIntervalTime (*test)(PRInt32 loops), PRInt32 loops,
    134                           PRIntervalTime overhead) {
    135  /*
    136   * overhead - overhead not measured by the test.
    137   * duration - wall clock time it took to perform test.
    138   * predicted - extra time test says should not be counted
    139   *
    140   * Time accountable to the test is duration - overhead - predicted
    141   * All times are Intervals and accumulated for all iterations.
    142   */
    143  PRFloat64 elapsed;
    144  PRIntervalTime accountable, duration;
    145  PRUintn spaces = strlen(msg);
    146  PRIntervalTime timeout, timein = PR_IntervalNow();
    147  PRIntervalTime predicted = test(loops);
    148  timeout = PR_IntervalNow();
    149  duration = timeout - timein;
    150  accountable = duration - predicted;
    151  accountable -= overhead;
    152  elapsed = (PRFloat64)PR_IntervalToMicroseconds(accountable);
    153  if (debug_mode) {
    154    printf("%s:", msg);
    155  }
    156  while (spaces++ < 50)
    157    if (debug_mode) {
    158      printf(" ");
    159    }
    160  if ((PRInt32)accountable < 0) {
    161    if (debug_mode) {
    162      printf("*****.** usecs/iteration\n");
    163    }
    164  } else {
    165    if (debug_mode) {
    166      printf("%8.2f usecs/iteration\n", elapsed / loops);
    167    }
    168  }
    169  return duration;
    170 } /* Test */
    171 
    172 int main(int argc, char** argv) {
    173  PRIntervalTime duration;
    174  PRUint32 cpu, cpus = 2;
    175  PRInt32 loops = 100;
    176 
    177  /* The command line argument: -d is used to determine if the test is being run
    178  in debug mode. The regress tool requires only one line output:PASS or FAIL.
    179  All of the printfs associated with this test has been handled with a if
    180  (debug_mode) test. Usage: test_name -d
    181  */
    182  PLOptStatus os;
    183  PLOptState* opt = PL_CreateOptState(argc, argv, "d:");
    184  while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
    185    if (PL_OPT_BAD == os) {
    186      continue;
    187    }
    188    switch (opt->option) {
    189      case 'd': /* debug mode */
    190        debug_mode = 1;
    191        break;
    192      default:
    193        break;
    194    }
    195  }
    196  PL_DestroyOptState(opt);
    197 
    198  /* main test */
    199 
    200  PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
    201 
    202  if (argc > 1) {
    203    loops = atoi(argv[1]);
    204  }
    205  if (loops == 0) {
    206    loops = 100;
    207  }
    208  if (debug_mode) {
    209    printf("Lock: Using %d loops\n", loops);
    210  }
    211 
    212  cpus = (argc < 3) ? 2 : atoi(argv[2]);
    213  if (cpus == 0) {
    214    cpus = 2;
    215  }
    216  if (debug_mode) {
    217    printf("Lock: Using %d cpu(s)\n", cpus);
    218  }
    219 
    220  for (cpu = 1; cpu <= cpus; ++cpu) {
    221    if (debug_mode) {
    222      printf("\nLockFile: Using %d CPU(s)\n", cpu);
    223    }
    224    PR_SetConcurrency(cpu);
    225 
    226    duration = Test("LockFile non-contentious locking/unlocking",
    227                    NonContentiousLock, loops, 0);
    228    (void)Test("LockFile contentious locking/unlocking", ContentiousLock, loops,
    229               duration);
    230  }
    231 
    232  PR_Delete(LOCKFILE); /* try to get rid of evidence */
    233 
    234  if (debug_mode) {
    235    printf("%s: test %s\n", "Lock(mutex) test",
    236           ((failed_already) ? "failed" : "passed"));
    237  }
    238  if (failed_already) {
    239    return 1;
    240  } else {
    241    return 0;
    242  }
    243 } /* main */
    244 
    245 /* testlock.c */