tor-browser

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

concur.c (3657B)


      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:            concur.c
      8 ** Description:     test of adding and removing concurrency options
      9 */
     10 
     11 #include "prcvar.h"
     12 #include "prinit.h"
     13 #include "prinrval.h"
     14 #include "prlock.h"
     15 #include "prprf.h"
     16 #include "prmem.h"
     17 #include "prlog.h"
     18 
     19 #include "plgetopt.h"
     20 
     21 #include "private/pprio.h"
     22 
     23 #include <stdlib.h>
     24 
     25 #define DEFAULT_RANGE 10
     26 #define DEFAULT_LOOPS 100
     27 
     28 static PRThreadScope thread_scope = PR_LOCAL_THREAD;
     29 
     30 typedef struct Context {
     31  PRLock* ml;
     32  PRCondVar* cv;
     33  PRIntn want, have;
     34 } Context;
     35 
     36 /*
     37 ** Make the instance of 'context' static (not on the stack)
     38 ** for Win16 threads
     39 */
     40 static Context context = {NULL, NULL, 0, 0};
     41 
     42 static void PR_CALLBACK Dull(void* arg) {
     43  Context* context = (Context*)arg;
     44  PR_Lock(context->ml);
     45  context->have += 1;
     46  while (context->want >= context->have) {
     47    PR_WaitCondVar(context->cv, PR_INTERVAL_NO_TIMEOUT);
     48  }
     49  context->have -= 1;
     50  PR_Unlock(context->ml);
     51 } /* Dull */
     52 
     53 PRIntn PR_CALLBACK Concur(PRIntn argc, char** argv) {
     54  PRUintn cpus;
     55  PLOptStatus os;
     56  PRThread** threads;
     57  PRBool debug = PR_FALSE;
     58  PRUintn range = DEFAULT_RANGE;
     59  PRStatus rc;
     60  PRUintn cnt;
     61  PRUintn loops = DEFAULT_LOOPS;
     62  PRIntervalTime hundredMills = PR_MillisecondsToInterval(100);
     63  PLOptState* opt = PL_CreateOptState(argc, argv, "Gdl:r:");
     64  while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
     65    if (PL_OPT_BAD == os) {
     66      continue;
     67    }
     68    switch (opt->option) {
     69      case 'G': /* GLOBAL threads */
     70        thread_scope = PR_GLOBAL_THREAD;
     71        break;
     72      case 'd': /* debug mode */
     73        debug = PR_TRUE;
     74        break;
     75      case 'r': /* range limit */
     76        range = atoi(opt->value);
     77        break;
     78      case 'l': /* loop counter */
     79        loops = atoi(opt->value);
     80        break;
     81      default:
     82        break;
     83    }
     84  }
     85  PL_DestroyOptState(opt);
     86 
     87  if (0 == range) {
     88    range = DEFAULT_RANGE;
     89  }
     90  if (0 == loops) {
     91    loops = DEFAULT_LOOPS;
     92  }
     93 
     94  context.ml = PR_NewLock();
     95  context.cv = PR_NewCondVar(context.ml);
     96 
     97  if (debug)
     98    PR_fprintf(PR_STDERR, "Testing with %d CPUs and %d interations\n", range,
     99               loops);
    100 
    101  threads = (PRThread**)PR_CALLOC(sizeof(PRThread*) * range);
    102  while (--loops > 0) {
    103    for (cpus = 1; cpus <= range; ++cpus) {
    104      PR_SetConcurrency(cpus);
    105      context.want = cpus;
    106 
    107      threads[cpus - 1] =
    108          PR_CreateThread(PR_USER_THREAD, Dull, &context, PR_PRIORITY_NORMAL,
    109                          thread_scope, PR_JOINABLE_THREAD, 0);
    110    }
    111 
    112    PR_Sleep(hundredMills);
    113 
    114    for (cpus = range; cpus > 0; cpus--) {
    115      PR_SetConcurrency(cpus);
    116      context.want = cpus - 1;
    117 
    118      PR_Lock(context.ml);
    119      PR_NotifyCondVar(context.cv);
    120      PR_Unlock(context.ml);
    121    }
    122    for (cnt = 0; cnt < range; cnt++) {
    123      rc = PR_JoinThread(threads[cnt]);
    124      PR_ASSERT(rc == PR_SUCCESS);
    125    }
    126  }
    127 
    128  if (debug)
    129    PR_fprintf(PR_STDERR, "Waiting for %d thread(s) to exit\n", context.have);
    130 
    131  while (context.have > 0) {
    132    PR_Sleep(hundredMills);
    133  }
    134 
    135  if (debug)
    136    PR_fprintf(PR_STDERR, "Finished [want: %d, have: %d]\n", context.want,
    137               context.have);
    138 
    139  PR_DestroyLock(context.ml);
    140  PR_DestroyCondVar(context.cv);
    141  PR_DELETE(threads);
    142 
    143  PR_fprintf(PR_STDERR, "PASSED\n");
    144 
    145  return 0;
    146 } /* Concur */
    147 
    148 int main(int argc, char** argv) {
    149  return PR_Initialize(Concur, argc, argv, 0);
    150 } /* main */
    151 
    152 /* concur.c */