1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/tests/concur.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,157 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 +** File: concur.c 1.11 +** Description: test of adding and removing concurrency options 1.12 +*/ 1.13 + 1.14 +#include "prcvar.h" 1.15 +#include "prinit.h" 1.16 +#include "prinrval.h" 1.17 +#include "prlock.h" 1.18 +#include "prprf.h" 1.19 +#include "prmem.h" 1.20 +#include "prlog.h" 1.21 + 1.22 +#include "plgetopt.h" 1.23 + 1.24 +#include "private/pprio.h" 1.25 + 1.26 +#include <stdlib.h> 1.27 + 1.28 +#define DEFAULT_RANGE 10 1.29 +#define DEFAULT_LOOPS 100 1.30 + 1.31 +static PRThreadScope thread_scope = PR_LOCAL_THREAD; 1.32 + 1.33 +typedef struct Context 1.34 +{ 1.35 + PRLock *ml; 1.36 + PRCondVar *cv; 1.37 + PRIntn want, have; 1.38 +} Context; 1.39 + 1.40 + 1.41 +/* 1.42 +** Make the instance of 'context' static (not on the stack) 1.43 +** for Win16 threads 1.44 +*/ 1.45 +static Context context = {NULL, NULL, 0, 0}; 1.46 + 1.47 +static void PR_CALLBACK Dull(void *arg) 1.48 +{ 1.49 + Context *context = (Context*)arg; 1.50 + PR_Lock(context->ml); 1.51 + context->have += 1; 1.52 + while (context->want >= context->have) 1.53 + PR_WaitCondVar(context->cv, PR_INTERVAL_NO_TIMEOUT); 1.54 + context->have -= 1; 1.55 + PR_Unlock(context->ml); 1.56 +} /* Dull */ 1.57 + 1.58 +PRIntn PR_CALLBACK Concur(PRIntn argc, char **argv) 1.59 +{ 1.60 + PRUintn cpus; 1.61 + PLOptStatus os; 1.62 + PRThread **threads; 1.63 + PRBool debug = PR_FALSE; 1.64 + PRUintn range = DEFAULT_RANGE; 1.65 + PRStatus rc; 1.66 + PRUintn cnt; 1.67 + PRUintn loops = DEFAULT_LOOPS; 1.68 + PRIntervalTime hundredMills = PR_MillisecondsToInterval(100); 1.69 + PLOptState *opt = PL_CreateOptState(argc, argv, "Gdl:r:"); 1.70 + while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) 1.71 + { 1.72 + if (PL_OPT_BAD == os) continue; 1.73 + switch (opt->option) 1.74 + { 1.75 + case 'G': /* GLOBAL threads */ 1.76 + thread_scope = PR_GLOBAL_THREAD; 1.77 + break; 1.78 + case 'd': /* debug mode */ 1.79 + debug = PR_TRUE; 1.80 + break; 1.81 + case 'r': /* range limit */ 1.82 + range = atoi(opt->value); 1.83 + break; 1.84 + case 'l': /* loop counter */ 1.85 + loops = atoi(opt->value); 1.86 + break; 1.87 + default: 1.88 + break; 1.89 + } 1.90 + } 1.91 + PL_DestroyOptState(opt); 1.92 + 1.93 + if (0 == range) range = DEFAULT_RANGE; 1.94 + if (0 == loops) loops = DEFAULT_LOOPS; 1.95 + 1.96 + context.ml = PR_NewLock(); 1.97 + context.cv = PR_NewCondVar(context.ml); 1.98 + 1.99 + if (debug) 1.100 + PR_fprintf( 1.101 + PR_STDERR, "Testing with %d CPUs and %d interations\n", range, loops); 1.102 + 1.103 + threads = (PRThread**) PR_CALLOC(sizeof(PRThread*) * range); 1.104 + while (--loops > 0) 1.105 + { 1.106 + for (cpus = 1; cpus <= range; ++cpus) 1.107 + { 1.108 + PR_SetConcurrency(cpus); 1.109 + context.want = cpus; 1.110 + 1.111 + threads[cpus - 1] = PR_CreateThread( 1.112 + PR_USER_THREAD, Dull, &context, PR_PRIORITY_NORMAL, 1.113 + thread_scope, PR_JOINABLE_THREAD, 0); 1.114 + } 1.115 + 1.116 + PR_Sleep(hundredMills); 1.117 + 1.118 + for (cpus = range; cpus > 0; cpus--) 1.119 + { 1.120 + PR_SetConcurrency(cpus); 1.121 + context.want = cpus - 1; 1.122 + 1.123 + PR_Lock(context.ml); 1.124 + PR_NotifyCondVar(context.cv); 1.125 + PR_Unlock(context.ml); 1.126 + } 1.127 + for(cnt = 0; cnt < range; cnt++) { 1.128 + rc = PR_JoinThread(threads[cnt]); 1.129 + PR_ASSERT(rc == PR_SUCCESS); 1.130 + } 1.131 + } 1.132 + 1.133 + 1.134 + if (debug) 1.135 + PR_fprintf( 1.136 + PR_STDERR, "Waiting for %d thread(s) to exit\n", context.have); 1.137 + 1.138 + while (context.have > 0) PR_Sleep(hundredMills); 1.139 + 1.140 + if (debug) 1.141 + PR_fprintf( 1.142 + PR_STDERR, "Finished [want: %d, have: %d]\n", 1.143 + context.want, context.have); 1.144 + 1.145 + PR_DestroyLock(context.ml); 1.146 + PR_DestroyCondVar(context.cv); 1.147 + PR_DELETE(threads); 1.148 + 1.149 + PR_fprintf(PR_STDERR, "PASSED\n"); 1.150 + 1.151 + return 0; 1.152 +} /* Concur */ 1.153 + 1.154 +int main(int argc, char **argv) 1.155 +{ 1.156 + PR_STDIO_INIT(); 1.157 + return PR_Initialize(Concur, argc, argv, 0); 1.158 +} /* main */ 1.159 + 1.160 +/* concur.c */