nsprpub/pr/tests/pollable.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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  * A test for the pollable events.
     8  *
     9  * A number of threads are in a ring configuration, each waiting on
    10  * a pollable event that is set by its upstream neighbor.
    11  */
    13 #include "prinit.h"
    14 #include "prio.h"
    15 #include "prthread.h"
    16 #include "prerror.h"
    17 #include "prmem.h"
    18 #include "prlog.h"
    19 #include "prprf.h"
    21 #include "plgetopt.h"
    23 #include <stdlib.h>
    25 #define DEFAULT_THREADS 10
    26 #define DEFAULT_LOOPS 100
    28 PRIntn numThreads = DEFAULT_THREADS;
    29 PRIntn numIterations = DEFAULT_LOOPS;
    30 PRIntervalTime dally = PR_INTERVAL_NO_WAIT;
    31 PRFileDesc *debug_out = NULL;
    32 PRBool debug_mode = PR_FALSE;
    33 PRBool verbosity = PR_FALSE;
    35 typedef struct ThreadData {
    36     PRFileDesc *event;
    37     int index;
    38     struct ThreadData *next;
    39 } ThreadData;
    41 void ThreadRoutine(void *arg)
    42 {
    43     ThreadData *data = (ThreadData *) arg;
    44     PRIntn i;
    45     PRPollDesc pd;
    46     PRInt32 rv;
    48     pd.fd = data->event;
    49     pd.in_flags = PR_POLL_READ;
    51     for (i = 0; i < numIterations; i++) {
    52         rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
    53         if (rv == -1) {
    54             PR_fprintf(PR_STDERR, "PR_Poll failed\n");
    55             exit(1);
    56         }
    57         if (verbosity) {
    58             PR_fprintf(debug_out, "thread %d awakened\n", data->index);
    59         }
    60         PR_ASSERT(rv != 0);
    61         PR_ASSERT(pd.out_flags & PR_POLL_READ);
    62         if (PR_WaitForPollableEvent(data->event) == PR_FAILURE) {
    63             PR_fprintf(PR_STDERR, "consume event failed\n");
    64             exit(1);
    65         }
    66         if (dally != PR_INTERVAL_NO_WAIT) {
    67             PR_Sleep(dally);
    68         }
    69         if (verbosity) {
    70             PR_fprintf(debug_out, "thread %d posting event\n", data->index);
    71         }
    72         if (PR_SetPollableEvent(data->next->event) == PR_FAILURE) {
    73             PR_fprintf(PR_STDERR, "post event failed\n");
    74             exit(1);
    75         }
    76     }
    77 }
    79 static void Help(void)
    80 {
    81     debug_out = PR_STDOUT;
    83     PR_fprintf(
    84             debug_out, "Usage: pollable [-c n] [-t n] [-d] [-v] [-G] [-C n] [-D n]\n");
    85     PR_fprintf(
    86             debug_out, "-c n\tloops at thread level (default: %d)\n", DEFAULT_LOOPS);
    87     PR_fprintf(
    88             debug_out, "-t n\tnumber of threads (default: %d)\n", DEFAULT_THREADS);
    89     PR_fprintf(debug_out, "-d\tturn on debugging output (default: FALSE)\n");
    90     PR_fprintf(debug_out, "-v\tturn on verbose output (default: FALSE)\n");
    91     PR_fprintf(debug_out, "-G\tglobal threads only (default: FALSE)\n");
    92     PR_fprintf(debug_out, "-C n\tconcurrency setting (default: 1)\n");
    93     PR_fprintf(debug_out, "-D n\tdally setting (msecs) (default: 0)\n");
    94 }  /* Help */
    96 int main(int argc, char **argv)
    97 {
    98     ThreadData selfData;
    99     ThreadData *data;
   100     PRThread **thread;
   101     void *block;
   102     PRIntn i;
   103     PRIntervalTime timeStart, timeEnd;
   104     PRPollDesc pd;
   105     PRInt32 rv;
   106     PRThreadScope thread_scope = PR_LOCAL_THREAD;
   107     PRBool help = PR_FALSE;
   108     PRUintn concurrency = 1;
   109     PRUintn average;
   110     PLOptStatus os;
   111     PLOptState *opt;
   113     PR_STDIO_INIT();
   115     opt = PL_CreateOptState(argc, argv, "hdvc:t:C:GD:");
   116     while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
   117         if (PL_OPT_BAD == os) {
   118             continue;
   119         }
   120         switch (opt->option) {
   121             case 'v':  /* verbose mode */
   122                 verbosity = PR_TRUE;
   123             case 'd':  /* debug mode */
   124                 debug_mode = PR_TRUE;
   125                 break;
   126             case 'c':  /* loop counter */
   127                 numIterations = atoi(opt->value);
   128                 break;
   129             case 't':  /* thread limit */
   130                 numThreads = atoi(opt->value);
   131                 break;
   132             case 'C':  /* Concurrency limit */
   133                 concurrency = atoi(opt->value);
   134                 break;
   135             case 'G':  /* global threads only */
   136                 thread_scope = PR_GLOBAL_THREAD;
   137                 break;
   138             case 'D':  /* dally */
   139                 dally = PR_MillisecondsToInterval(atoi(opt->value));
   140                 break;
   141             case 'h':  /* help message */
   142                 Help();
   143                 help = PR_TRUE;
   144                 break;
   145             default:
   146                 break;
   147         }
   148     }
   149     PL_DestroyOptState(opt);
   151     if (help) {
   152         return 1;
   153     }
   155     if (concurrency > 1) {
   156         PR_SetConcurrency(concurrency);
   157     }
   159     if (PR_TRUE == debug_mode) {
   160         debug_out = PR_STDOUT;
   161 	PR_fprintf(debug_out, "Test parameters\n");
   162         PR_fprintf(debug_out, "\tThreads involved: %d\n", numThreads);
   163         PR_fprintf(debug_out, "\tIteration limit: %d\n", numIterations);
   164         PR_fprintf(debug_out, "\tConcurrency: %d\n", concurrency);
   165         PR_fprintf(debug_out, "\tThread type: %s\n",
   166                 (PR_GLOBAL_THREAD == thread_scope) ? "GLOBAL" : "LOCAL");
   167     }
   169     /*
   170      * Malloc a block of memory and divide it into data and thread.
   171      */
   172     block = PR_MALLOC(numThreads * (sizeof(ThreadData) + sizeof(PRThread *)));
   173     if (block == NULL) {
   174         PR_fprintf(PR_STDERR, "cannot malloc, failed\n");
   175         exit(1);
   176     }
   177     data = (ThreadData *) block;
   178     thread = (PRThread **) &data[numThreads];
   180     /* Pollable event */
   181     selfData.event = PR_NewPollableEvent();
   182     if (selfData.event == NULL) {
   183         PR_fprintf(PR_STDERR, "cannot create event: (%ld, %ld)\n",
   184                 PR_GetError(), PR_GetOSError());
   185         exit(1);
   186     }
   187     selfData.next = &data[0];
   188     for (i = 0; i < numThreads; i++) {
   189         data[i].event = PR_NewPollableEvent();
   190         if (data[i].event == NULL) {
   191             PR_fprintf(PR_STDERR, "cannot create event: (%ld, %ld)\n",
   192                     PR_GetError(), PR_GetOSError());
   193             exit(1);
   194         }
   195         data[i].index = i;
   196         if (i != numThreads - 1) {
   197             data[i].next = &data[i + 1];
   198         } else {
   199             data[i].next = &selfData;
   200         }
   202         thread[i] = PR_CreateThread(PR_USER_THREAD,
   203                 ThreadRoutine, &data[i], PR_PRIORITY_NORMAL,
   204                 thread_scope, PR_JOINABLE_THREAD, 0);
   205         if (thread[i] == NULL) {
   206             PR_fprintf(PR_STDERR, "cannot create thread\n");
   207             exit(1);
   208         }
   209     }
   211     timeStart = PR_IntervalNow();
   212     pd.fd = selfData.event;
   213     pd.in_flags = PR_POLL_READ;
   214     for (i = 0; i < numIterations; i++) {
   215         if (dally != PR_INTERVAL_NO_WAIT) {
   216             PR_Sleep(dally);
   217         }
   218         if (verbosity) {
   219             PR_fprintf(debug_out, "main thread posting event\n");
   220         }
   221         if (PR_SetPollableEvent(selfData.next->event) == PR_FAILURE) {
   222             PR_fprintf(PR_STDERR, "set event failed\n");
   223             exit(1);
   224         }
   225         rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
   226         if (rv == -1) {
   227             PR_fprintf(PR_STDERR, "wait failed\n");
   228             exit(1);
   229         }
   230         PR_ASSERT(rv != 0);
   231         PR_ASSERT(pd.out_flags & PR_POLL_READ);
   232         if (verbosity) {
   233             PR_fprintf(debug_out, "main thread awakened\n");
   234         }
   235 	if (PR_WaitForPollableEvent(selfData.event) == PR_FAILURE) {
   236             PR_fprintf(PR_STDERR, "consume event failed\n");
   237             exit(1);
   238         }
   239     }
   240     timeEnd = PR_IntervalNow();
   242     if (debug_mode) {
   243         average = PR_IntervalToMicroseconds(timeEnd - timeStart)
   244                 / (numIterations * numThreads);
   245         PR_fprintf(debug_out, "Average switch times %d usecs for %d threads\n",
   246                 average, numThreads);
   247     }
   249     for (i = 0; i < numThreads; i++) {
   250         if (PR_JoinThread(thread[i]) == PR_FAILURE) {
   251             PR_fprintf(PR_STDERR, "join thread failed\n");
   252             exit(1);
   253         }
   254         PR_DestroyPollableEvent(data[i].event);
   255     }
   256     PR_DELETE(block);
   257 	PR_DestroyPollableEvent(selfData.event);
   259     PR_fprintf(PR_STDOUT, "PASSED\n");
   260     return 0;
   261 }

mercurial