nsprpub/pr/tests/switch.c

Wed, 31 Dec 2014 07:53:36 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:53:36 +0100
branch
TOR_BUG_3246
changeset 5
4ab42b5ab56c
permissions
-rw-r--r--

Correct small whitespace inconsistency, lost while renaming variables.

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

mercurial