nsprpub/pr/tests/switch.c

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /*
michael@0 7 ** File: switch.c
michael@0 8 ** Description: trying to time context switches
michael@0 9 */
michael@0 10
michael@0 11 #include "prinit.h"
michael@0 12 #include "prcvar.h"
michael@0 13 #include "prmem.h"
michael@0 14 #include "prinrval.h"
michael@0 15 #include "prlock.h"
michael@0 16 #include "prlog.h"
michael@0 17 #include "prthread.h"
michael@0 18 #include "prprf.h"
michael@0 19
michael@0 20 #include "plerror.h"
michael@0 21 #include "plgetopt.h"
michael@0 22
michael@0 23 #include "private/pprio.h"
michael@0 24
michael@0 25 #include <stdlib.h>
michael@0 26
michael@0 27 #define INNER_LOOPS 100
michael@0 28 #define DEFAULT_LOOPS 100
michael@0 29 #define DEFAULT_THREADS 10
michael@0 30
michael@0 31 static PRFileDesc *debug_out = NULL;
michael@0 32 static PRBool debug_mode = PR_FALSE, verbosity = PR_FALSE, failed = PR_FALSE;
michael@0 33
michael@0 34 typedef struct Shared
michael@0 35 {
michael@0 36 PRLock *ml;
michael@0 37 PRCondVar *cv;
michael@0 38 PRBool twiddle;
michael@0 39 PRThread *thread;
michael@0 40 struct Shared *next;
michael@0 41 } Shared;
michael@0 42
michael@0 43 static void Help(void)
michael@0 44 {
michael@0 45 debug_out = PR_STDOUT;
michael@0 46
michael@0 47 PR_fprintf(
michael@0 48 debug_out, "Usage: >./switch [-c n] [-t n] [-d] [-v] [-G] [-C n]\n");
michael@0 49 PR_fprintf(
michael@0 50 debug_out, "-c n\tloops at thread level (default: %d)\n", DEFAULT_LOOPS);
michael@0 51 PR_fprintf(
michael@0 52 debug_out, "-t n\tnumber of threads (default: %d)\n", DEFAULT_THREADS);
michael@0 53 PR_fprintf(debug_out, "-d\tturn on debugging output (default: FALSE)\n");
michael@0 54 PR_fprintf(debug_out, "-v\tturn on verbose output (default: FALSE)\n");
michael@0 55 PR_fprintf(debug_out, "-G\tglobal threads only (default: FALSE)\n");
michael@0 56 PR_fprintf(debug_out, "-C n\tconcurrency setting (default: 1)\n");
michael@0 57 } /* Help */
michael@0 58
michael@0 59 static void PR_CALLBACK Notified(void *arg)
michael@0 60 {
michael@0 61 Shared *shared = (Shared*)arg;
michael@0 62 PRStatus status = PR_SUCCESS;
michael@0 63 while (PR_SUCCESS == status)
michael@0 64 {
michael@0 65 PR_Lock(shared->ml);
michael@0 66 while (shared->twiddle && (PR_SUCCESS == status))
michael@0 67 status = PR_WaitCondVar(shared->cv, PR_INTERVAL_NO_TIMEOUT);
michael@0 68 if (verbosity) PR_fprintf(debug_out, "+");
michael@0 69 shared->twiddle = PR_TRUE;
michael@0 70 shared->next->twiddle = PR_FALSE;
michael@0 71 PR_NotifyCondVar(shared->next->cv);
michael@0 72 PR_Unlock(shared->ml);
michael@0 73 }
michael@0 74 } /* Notified */
michael@0 75
michael@0 76 static Shared home;
michael@0 77 PRIntn PR_CALLBACK Switch(PRIntn argc, char **argv)
michael@0 78 {
michael@0 79 PLOptStatus os;
michael@0 80 PRStatus status;
michael@0 81 PRBool help = PR_FALSE;
michael@0 82 PRUintn concurrency = 1;
michael@0 83 Shared *shared, *link;
michael@0 84 PRIntervalTime timein, timeout;
michael@0 85 PRThreadScope thread_scope = PR_LOCAL_THREAD;
michael@0 86 PRUintn thread_count, inner_count, loop_count, average;
michael@0 87 PRUintn thread_limit = DEFAULT_THREADS, loop_limit = DEFAULT_LOOPS;
michael@0 88 PLOptState *opt = PL_CreateOptState(argc, argv, "hdvc:t:C:G");
michael@0 89 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
michael@0 90 {
michael@0 91 if (PL_OPT_BAD == os) continue;
michael@0 92 switch (opt->option)
michael@0 93 {
michael@0 94 case 'v': /* verbose mode */
michael@0 95 verbosity = PR_TRUE;
michael@0 96 case 'd': /* debug mode */
michael@0 97 debug_mode = PR_TRUE;
michael@0 98 break;
michael@0 99 case 'c': /* loop counter */
michael@0 100 loop_limit = atoi(opt->value);
michael@0 101 break;
michael@0 102 case 't': /* thread limit */
michael@0 103 thread_limit = atoi(opt->value);
michael@0 104 break;
michael@0 105 case 'C': /* Concurrency limit */
michael@0 106 concurrency = atoi(opt->value);
michael@0 107 break;
michael@0 108 case 'G': /* global threads only */
michael@0 109 thread_scope = PR_GLOBAL_THREAD;
michael@0 110 break;
michael@0 111 case 'h': /* help message */
michael@0 112 Help();
michael@0 113 help = PR_TRUE;
michael@0 114 break;
michael@0 115 default:
michael@0 116 break;
michael@0 117 }
michael@0 118 }
michael@0 119 PL_DestroyOptState(opt);
michael@0 120
michael@0 121 if (help) return -1;
michael@0 122
michael@0 123 if (PR_TRUE == debug_mode)
michael@0 124 {
michael@0 125 debug_out = PR_STDOUT;
michael@0 126 PR_fprintf(debug_out, "Test parameters\n");
michael@0 127 PR_fprintf(debug_out, "\tThreads involved: %d\n", thread_limit);
michael@0 128 PR_fprintf(debug_out, "\tIteration limit: %d\n", loop_limit);
michael@0 129 PR_fprintf(debug_out, "\tConcurrency: %d\n", concurrency);
michael@0 130 PR_fprintf(
michael@0 131 debug_out, "\tThread type: %s\n",
michael@0 132 (PR_GLOBAL_THREAD == thread_scope) ? "GLOBAL" : "LOCAL");
michael@0 133 }
michael@0 134
michael@0 135 PR_SetConcurrency(concurrency);
michael@0 136
michael@0 137 link = &home;
michael@0 138 home.ml = PR_NewLock();
michael@0 139 home.cv = PR_NewCondVar(home.ml);
michael@0 140 home.twiddle = PR_FALSE;
michael@0 141 home.next = NULL;
michael@0 142
michael@0 143 timeout = 0;
michael@0 144
michael@0 145 for (thread_count = 1; thread_count <= thread_limit; ++thread_count)
michael@0 146 {
michael@0 147 shared = PR_NEWZAP(Shared);
michael@0 148
michael@0 149 shared->ml = home.ml;
michael@0 150 shared->cv = PR_NewCondVar(home.ml);
michael@0 151 shared->twiddle = PR_TRUE;
michael@0 152 shared->next = link;
michael@0 153 link = shared;
michael@0 154
michael@0 155 shared->thread = PR_CreateThread(
michael@0 156 PR_USER_THREAD, Notified, shared,
michael@0 157 PR_PRIORITY_HIGH, thread_scope,
michael@0 158 PR_JOINABLE_THREAD, 0);
michael@0 159 PR_ASSERT(shared->thread != NULL);
michael@0 160 if (NULL == shared->thread)
michael@0 161 failed = PR_TRUE;
michael@0 162 }
michael@0 163
michael@0 164 for (loop_count = 1; loop_count <= loop_limit; ++loop_count)
michael@0 165 {
michael@0 166 timein = PR_IntervalNow();
michael@0 167 for (inner_count = 0; inner_count < INNER_LOOPS; ++inner_count)
michael@0 168 {
michael@0 169 PR_Lock(home.ml);
michael@0 170 home.twiddle = PR_TRUE;
michael@0 171 shared->twiddle = PR_FALSE;
michael@0 172 PR_NotifyCondVar(shared->cv);
michael@0 173 while (home.twiddle)
michael@0 174 {
michael@0 175 status = PR_WaitCondVar(home.cv, PR_INTERVAL_NO_TIMEOUT);
michael@0 176 if (PR_FAILURE == status)
michael@0 177 failed = PR_TRUE;
michael@0 178 }
michael@0 179 PR_Unlock(home.ml);
michael@0 180 }
michael@0 181 timeout += (PR_IntervalNow() - timein);
michael@0 182 }
michael@0 183
michael@0 184 if (debug_mode)
michael@0 185 {
michael@0 186 average = PR_IntervalToMicroseconds(timeout)
michael@0 187 / (INNER_LOOPS * loop_limit * thread_count);
michael@0 188 PR_fprintf(
michael@0 189 debug_out, "Average switch times %d usecs for %d threads\n",
michael@0 190 average, thread_limit);
michael@0 191 }
michael@0 192
michael@0 193 link = shared;
michael@0 194 for (thread_count = 1; thread_count <= thread_limit; ++thread_count)
michael@0 195 {
michael@0 196 if (&home == link) break;
michael@0 197 status = PR_Interrupt(link->thread);
michael@0 198 if (PR_SUCCESS != status)
michael@0 199 {
michael@0 200 failed = PR_TRUE;
michael@0 201 if (debug_mode)
michael@0 202 PL_FPrintError(debug_out, "Failed to interrupt");
michael@0 203 }
michael@0 204 link = link->next;
michael@0 205 }
michael@0 206
michael@0 207 for (thread_count = 1; thread_count <= thread_limit; ++thread_count)
michael@0 208 {
michael@0 209 link = shared->next;
michael@0 210 status = PR_JoinThread(shared->thread);
michael@0 211 if (PR_SUCCESS != status)
michael@0 212 {
michael@0 213 failed = PR_TRUE;
michael@0 214 if (debug_mode)
michael@0 215 PL_FPrintError(debug_out, "Failed to join");
michael@0 216 }
michael@0 217 PR_DestroyCondVar(shared->cv);
michael@0 218 PR_DELETE(shared);
michael@0 219 if (&home == link) break;
michael@0 220 shared = link;
michael@0 221 }
michael@0 222 PR_DestroyCondVar(home.cv);
michael@0 223 PR_DestroyLock(home.ml);
michael@0 224
michael@0 225 PR_fprintf(PR_STDOUT, ((failed) ? "FAILED\n" : "PASSED\n"));
michael@0 226 return ((failed) ? 1 : 0);
michael@0 227 } /* Switch */
michael@0 228
michael@0 229 int main(int argc, char **argv)
michael@0 230 {
michael@0 231 PRIntn result;
michael@0 232 PR_STDIO_INIT();
michael@0 233 result = PR_Initialize(Switch, argc, argv, 0);
michael@0 234 return result;
michael@0 235 } /* main */
michael@0 236
michael@0 237 /* switch.c */

mercurial