tor-browser

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

rwlocktest.c (4877B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 /*
      6 *
      7 * RWLock tests
      8 *
      9 *  Several threads are created to access and modify data arrays using
     10 *  PRRWLocks for synchronization. Two data arrays, array_A and array_B, are
     11 *  initialized with random data and a third array, array_C, is initialized
     12 *  with the sum of the first 2 arrays.
     13 *
     14 *  Each one of the threads acquires a read lock to verify that the sum of
     15 *  the arrays A and B is equal to array C, and acquires a write lock to
     16 *  consistently update arrays A and B so that their is equal to array C.
     17 *
     18 */
     19 
     20 #include "nspr.h"
     21 #include "plgetopt.h"
     22 #include "prrwlock.h"
     23 
     24 static int _debug_on;
     25 static void rwtest(void* args);
     26 static PRInt32 *array_A, *array_B, *array_C;
     27 static void update_array(void);
     28 static void check_array(void);
     29 
     30 typedef struct thread_args {
     31  PRRWLock* rwlock;
     32  PRInt32 loop_cnt;
     33 } thread_args;
     34 
     35 PRFileDesc* output;
     36 PRFileDesc* errhandle;
     37 
     38 #define DEFAULT_THREAD_CNT 4
     39 #define DEFAULT_LOOP_CNT 100
     40 #define TEST_ARRAY_SIZE 100
     41 
     42 int main(int argc, char** argv) {
     43  PRInt32 cnt;
     44  PRStatus rc;
     45  PRInt32 i;
     46 
     47  PRInt32 thread_cnt = DEFAULT_THREAD_CNT;
     48  PRInt32 loop_cnt = DEFAULT_LOOP_CNT;
     49  PRThread** threads;
     50  thread_args* params;
     51  PRRWLock* rwlock1;
     52 
     53  PLOptStatus os;
     54  PLOptState* opt = PL_CreateOptState(argc, argv, "dt:c:");
     55 
     56  while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
     57    if (PL_OPT_BAD == os) {
     58      continue;
     59    }
     60    switch (opt->option) {
     61      case 'd': /* debug mode */
     62        _debug_on = 1;
     63        break;
     64      case 't': /* thread count */
     65        thread_cnt = atoi(opt->value);
     66        break;
     67      case 'c': /* loop count */
     68        loop_cnt = atoi(opt->value);
     69        break;
     70      default:
     71        break;
     72    }
     73  }
     74  PL_DestroyOptState(opt);
     75 
     76  PR_SetConcurrency(4);
     77 
     78  output = PR_GetSpecialFD(PR_StandardOutput);
     79  errhandle = PR_GetSpecialFD(PR_StandardError);
     80 
     81  rwlock1 = PR_NewRWLock(0, "Lock 1");
     82  if (rwlock1 == NULL) {
     83    PR_fprintf(errhandle, "PR_NewRWLock failed - error %d\n", PR_GetError());
     84    return 1;
     85  }
     86 
     87  threads = (PRThread**)PR_CALLOC(sizeof(PRThread*) * thread_cnt);
     88  params = (thread_args*)PR_CALLOC(sizeof(thread_args) * thread_cnt);
     89 
     90  /*
     91   * allocate and initialize data arrays
     92   */
     93  array_A = (PRInt32*)PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE);
     94  array_B = (PRInt32*)PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE);
     95  array_C = (PRInt32*)PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE);
     96  cnt = 0;
     97  for (i = 0; i < TEST_ARRAY_SIZE; i++) {
     98    array_A[i] = cnt++;
     99    array_B[i] = cnt++;
    100    array_C[i] = array_A[i] + array_B[i];
    101  }
    102 
    103  if (_debug_on)
    104    PR_fprintf(output, "%s: thread_cnt = %d loop_cnt = %d\n", argv[0],
    105               thread_cnt, loop_cnt);
    106  for (cnt = 0; cnt < thread_cnt; cnt++) {
    107    PRThreadScope scope;
    108 
    109    params[cnt].rwlock = rwlock1;
    110    params[cnt].loop_cnt = loop_cnt;
    111 
    112    /*
    113     * create LOCAL and GLOBAL threads alternately
    114     */
    115    if (cnt & 1) {
    116      scope = PR_LOCAL_THREAD;
    117    } else {
    118      scope = PR_GLOBAL_THREAD;
    119    }
    120 
    121    threads[cnt] =
    122        PR_CreateThread(PR_USER_THREAD, rwtest, &params[cnt],
    123                        PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0);
    124    if (threads[cnt] == NULL) {
    125      PR_fprintf(errhandle, "PR_CreateThread failed - error %d\n",
    126                 PR_GetError());
    127      PR_ProcessExit(2);
    128    }
    129    if (_debug_on)
    130      PR_fprintf(output, "%s: created thread = %p\n", argv[0], threads[cnt]);
    131  }
    132 
    133  for (cnt = 0; cnt < thread_cnt; cnt++) {
    134    rc = PR_JoinThread(threads[cnt]);
    135    PR_ASSERT(rc == PR_SUCCESS);
    136  }
    137 
    138  PR_DELETE(threads);
    139  PR_DELETE(params);
    140 
    141  PR_DELETE(array_A);
    142  PR_DELETE(array_B);
    143  PR_DELETE(array_C);
    144 
    145  PR_DestroyRWLock(rwlock1);
    146 
    147  printf("PASS\n");
    148  return 0;
    149 }
    150 
    151 static void rwtest(void* args) {
    152  PRInt32 index;
    153  thread_args* arg = (thread_args*)args;
    154 
    155  for (index = 0; index < arg->loop_cnt; index++) {
    156    /*
    157     * verify sum, update arrays and verify sum again
    158     */
    159 
    160    PR_RWLock_Rlock(arg->rwlock);
    161    check_array();
    162    PR_RWLock_Unlock(arg->rwlock);
    163 
    164    PR_RWLock_Wlock(arg->rwlock);
    165    update_array();
    166    PR_RWLock_Unlock(arg->rwlock);
    167 
    168    PR_RWLock_Rlock(arg->rwlock);
    169    check_array();
    170    PR_RWLock_Unlock(arg->rwlock);
    171  }
    172  if (_debug_on)
    173    PR_fprintf(output, "Thread[0x%x] lock = 0x%x exiting\n",
    174               PR_GetCurrentThread(), arg->rwlock);
    175 }
    176 
    177 static void check_array(void) {
    178  PRInt32 i;
    179 
    180  for (i = 0; i < TEST_ARRAY_SIZE; i++)
    181    if (array_C[i] != (array_A[i] + array_B[i])) {
    182      PR_fprintf(output, "Error - data check failed\n");
    183      PR_ProcessExit(1);
    184    }
    185 }
    186 
    187 static void update_array(void) {
    188  PRInt32 i;
    189 
    190  for (i = 0; i < TEST_ARRAY_SIZE; i++) {
    191    array_A[i] += i;
    192    array_B[i] -= i;
    193  }
    194 }