nsprpub/pr/tests/cvar2.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 **  1996 - Netscape Communications Corporation
     8 **
     9 ** Name: cvar2.c
    10 **
    11 ** Description: Simple test creates several local and global threads;
    12 **              half use a single,shared condvar, and the
    13 **              other half have their own condvar. The main thread then loops
    14 **				notifying them to wakeup. 
    15 **
    16 ** Modification History:
    17 ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
    18 **	         The debug mode will print all of the printfs associated with this test.
    19 **			 The regress mode will be the default mode. Since the regress tool limits
    20 **           the output to a one line status:PASS or FAIL,all of the printf statements
    21 **			 have been handled with an if (debug_mode) statement. 
    22 ***********************************************************************/
    24 #include "nspr.h"
    25 #include "plerror.h"
    26 #include "plgetopt.h"
    28 #include <stdio.h>
    29 #include <stdlib.h>
    30 #include <string.h>
    32 int _debug_on = 0;
    33 #define DPRINTF(arg) if (_debug_on) printf arg
    35 #define DEFAULT_COUNT   100
    36 #define DEFAULT_THREADS 5
    37 PRInt32 count = DEFAULT_COUNT;
    39 typedef struct threadinfo {
    40     PRThread        *thread;
    41     PRInt32          id;
    42     PRBool           internal;
    43     PRInt32         *tcount;
    44     PRLock          *lock;
    45     PRCondVar       *cvar;
    46     PRIntervalTime   timeout;
    47     PRInt32          loops;
    49     PRLock          *exitlock;
    50     PRCondVar       *exitcvar;
    51     PRInt32         *exitcount;
    52 } threadinfo;
    54 /*
    55 ** Make exitcount, tcount static. for Win16.
    56 */
    57 static PRInt32 exitcount=0;
    58 static PRInt32 tcount=0;
    61 /* Thread that gets notified; many threads share the same condvar */
    62 void PR_CALLBACK
    63 SharedCondVarThread(void *_info)
    64 {
    65     threadinfo *info = (threadinfo *)_info;
    66     PRInt32 index;
    68     for (index=0; index<info->loops; index++) {
    69         PR_Lock(info->lock);
    70         if (*info->tcount == 0)
    71             PR_WaitCondVar(info->cvar, info->timeout);
    72 #if 0
    73         printf("shared thread %ld notified in loop %ld\n", info->id, index);
    74 #endif
    75         (*info->tcount)--;
    76         PR_Unlock(info->lock);
    78         PR_Lock(info->exitlock);
    79         (*info->exitcount)++;
    80         PR_NotifyCondVar(info->exitcvar);
    81         PR_Unlock(info->exitlock);
    82     }
    83 #if 0
    84     printf("shared thread %ld terminating\n", info->id);
    85 #endif
    86 }
    88 /* Thread that gets notified; no other threads use the same condvar */
    89 void PR_CALLBACK
    90 PrivateCondVarThread(void *_info)
    91 {
    92     threadinfo *info = (threadinfo *)_info;
    93     PRInt32 index;
    95     for (index=0; index<info->loops; index++) {
    96         PR_Lock(info->lock);
    97         if (*info->tcount == 0) {
    98 	    DPRINTF(("PrivateCondVarThread: thread 0x%lx waiting on cvar = 0x%lx\n",
    99 				PR_GetCurrentThread(), info->cvar));
   100             PR_WaitCondVar(info->cvar, info->timeout);
   101 	}
   102 #if 0
   103         printf("solo   thread %ld notified in loop %ld\n", info->id, index);
   104 #endif
   105         (*info->tcount)--;
   106         PR_Unlock(info->lock);
   108         PR_Lock(info->exitlock);
   109         (*info->exitcount)++;
   110         PR_NotifyCondVar(info->exitcvar);
   111 DPRINTF(("PrivateCondVarThread: thread 0x%lx notified exitcvar = 0x%lx cnt = %ld\n",
   112 			PR_GetCurrentThread(), info->exitcvar,(*info->exitcount)));
   113         PR_Unlock(info->exitlock);
   114     }
   115 #if 0
   116     printf("solo   thread %ld terminating\n", info->id);
   117 #endif
   118 }
   120 void 
   121 CreateTestThread(threadinfo *info, 
   122                  PRInt32 id,
   123                  PRLock *lock,
   124                  PRCondVar *cvar,
   125                  PRInt32 loops,
   126                  PRIntervalTime timeout,
   127                  PRInt32 *tcount,
   128                  PRLock *exitlock,
   129                  PRCondVar *exitcvar,
   130                  PRInt32 *exitcount,
   131                  PRBool shared, 
   132                  PRThreadScope scope)
   133 {
   134     info->id = id;
   135     info->internal = (shared) ? PR_FALSE : PR_TRUE;
   136     info->lock = lock;
   137     info->cvar = cvar;
   138     info->loops = loops;
   139     info->timeout = timeout;
   140     info->tcount = tcount;
   141     info->exitlock = exitlock;
   142     info->exitcvar = exitcvar;
   143     info->exitcount = exitcount;
   144     info->thread = PR_CreateThread(
   145                            PR_USER_THREAD,
   146                            shared?SharedCondVarThread:PrivateCondVarThread,
   147                            info,
   148                            PR_PRIORITY_NORMAL,
   149                            scope,
   150                            PR_JOINABLE_THREAD,
   151                            0);
   152     if (!info->thread)
   153         PL_PrintError("error creating thread\n");
   154 }
   157 void 
   158 CondVarTestSUU(void *_arg)
   159 {
   160     PRInt32 arg = (PRInt32)_arg;
   161     PRInt32 index, loops;
   162     threadinfo *list;
   163     PRLock *sharedlock;
   164     PRCondVar *sharedcvar;
   165     PRLock *exitlock;
   166     PRCondVar *exitcvar;
   168     exitcount=0;
   169     tcount=0;
   170     list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4));
   172     sharedlock = PR_NewLock();
   173     sharedcvar = PR_NewCondVar(sharedlock);
   174     exitlock = PR_NewLock();
   175     exitcvar = PR_NewCondVar(exitlock);
   177     /* Create the threads */
   178     for(index=0; index<arg; ) {
   179         CreateTestThread(&list[index],
   180                          index,
   181                          sharedlock,
   182                          sharedcvar,
   183                          count,
   184                          PR_INTERVAL_NO_TIMEOUT,
   185                          &tcount,
   186                          exitlock,
   187                          exitcvar,
   188                          &exitcount,
   189                          PR_TRUE,
   190                          PR_LOCAL_THREAD);
   191         index++;
   192 	DPRINTF(("CondVarTestSUU: created thread 0x%lx\n",list[index].thread));
   193     }
   195     for (loops = 0; loops < count; loops++) {
   196         /* Notify the threads */
   197         for(index=0; index<(arg); index++) {
   198             PR_Lock(list[index].lock);
   199             (*list[index].tcount)++;
   200             PR_NotifyCondVar(list[index].cvar);
   201             PR_Unlock(list[index].lock);
   202 	    DPRINTF(("PrivateCondVarThread: thread 0x%lx notified cvar = 0x%lx\n",
   203 				PR_GetCurrentThread(), list[index].cvar));
   204         }
   206         /* Wait for threads to finish */
   207         PR_Lock(exitlock);
   208         while(exitcount < arg)
   209             PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60));
   210         PR_ASSERT(exitcount >= arg);
   211         exitcount -= arg;
   212         PR_Unlock(exitlock);
   213     }
   215     /* Join all the threads */
   216     for(index=0; index<(arg); index++) 
   217         PR_JoinThread(list[index].thread);
   219     PR_DestroyCondVar(sharedcvar);
   220     PR_DestroyLock(sharedlock);
   221     PR_DestroyCondVar(exitcvar);
   222     PR_DestroyLock(exitlock);
   224     PR_DELETE(list);
   225 }
   227 void 
   228 CondVarTestSUK(void *_arg)
   229 {
   230     PRInt32 arg = (PRInt32)_arg;
   231     PRInt32 index, loops;
   232     threadinfo *list;
   233     PRLock *sharedlock;
   234     PRCondVar *sharedcvar;
   235     PRLock *exitlock;
   236     PRCondVar *exitcvar;
   237     exitcount=0;
   238     tcount=0;
   240     list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4));
   242     sharedlock = PR_NewLock();
   243     sharedcvar = PR_NewCondVar(sharedlock);
   244     exitlock = PR_NewLock();
   245     exitcvar = PR_NewCondVar(exitlock);
   247     /* Create the threads */
   248     for(index=0; index<arg; ) {
   249         CreateTestThread(&list[index],
   250                          index,
   251                          sharedlock,
   252                          sharedcvar,
   253                          count,
   254                          PR_INTERVAL_NO_TIMEOUT,
   255                          &tcount,
   256                          exitlock,
   257                          exitcvar,
   258                          &exitcount,
   259                          PR_TRUE,
   260                          PR_GLOBAL_THREAD);
   261         index++;
   262     }
   264     for (loops = 0; loops < count; loops++) {
   265         /* Notify the threads */
   266         for(index=0; index<(arg); index++) {
   268             PR_Lock(list[index].lock);
   269             (*list[index].tcount)++;
   270             PR_NotifyCondVar(list[index].cvar);
   271             PR_Unlock(list[index].lock);
   272         }
   274 #if 0
   275         printf("wait for threads to be done\n");
   276 #endif
   277         /* Wait for threads to finish */
   278         PR_Lock(exitlock);
   279         while(exitcount < arg)
   280             PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60));
   281         PR_ASSERT(exitcount >= arg);
   282         exitcount -= arg;
   283         PR_Unlock(exitlock);
   284 #if 0
   285         printf("threads ready\n");
   286 #endif
   287     }
   289     /* Join all the threads */
   290     for(index=0; index<(arg); index++) 
   291         PR_JoinThread(list[index].thread);
   293     PR_DestroyCondVar(sharedcvar);
   294     PR_DestroyLock(sharedlock);
   295     PR_DestroyCondVar(exitcvar);
   296     PR_DestroyLock(exitlock);
   298     PR_DELETE(list);
   299 }
   301 void 
   302 CondVarTestPUU(void *_arg)
   303 {
   304     PRInt32 arg = (PRInt32)_arg;
   305     PRInt32 index, loops;
   306     threadinfo *list;
   307     PRLock *sharedlock;
   308     PRCondVar *sharedcvar;
   309     PRLock *exitlock;
   310     PRCondVar *exitcvar;
   311     PRInt32 *tcount, *saved_tcount;
   313     exitcount=0;
   314     list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4));
   315     saved_tcount = tcount = (PRInt32 *)PR_CALLOC(sizeof(*tcount) * (arg * 4));
   317     sharedlock = PR_NewLock();
   318     sharedcvar = PR_NewCondVar(sharedlock);
   319     exitlock = PR_NewLock();
   320     exitcvar = PR_NewCondVar(exitlock);
   322     /* Create the threads */
   323     for(index=0; index<arg; ) {
   324         list[index].lock = PR_NewLock();
   325         list[index].cvar = PR_NewCondVar(list[index].lock);
   326         CreateTestThread(&list[index],
   327                          index,
   328                          list[index].lock,
   329                          list[index].cvar,
   330                          count,
   331                          PR_INTERVAL_NO_TIMEOUT,
   332                          tcount,
   333                          exitlock,
   334                          exitcvar,
   335                          &exitcount,
   336                          PR_FALSE,
   337                          PR_LOCAL_THREAD);
   339 	DPRINTF(("CondVarTestPUU: created thread 0x%lx\n",list[index].thread));
   340         index++;
   341 	tcount++;
   342     }
   344     for (loops = 0; loops < count; loops++) {
   345         /* Notify the threads */
   346         for(index=0; index<(arg); index++) {
   348             PR_Lock(list[index].lock);
   349             (*list[index].tcount)++;
   350             PR_NotifyCondVar(list[index].cvar);
   351             PR_Unlock(list[index].lock);
   352         }
   354 	PR_Lock(exitlock);
   355         /* Wait for threads to finish */
   356         while(exitcount < arg) {
   357 DPRINTF(("CondVarTestPUU: thread 0x%lx waiting on exitcvar = 0x%lx cnt = %ld\n",
   358 				PR_GetCurrentThread(), exitcvar, exitcount));
   359             	PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60));
   360 	}
   361         PR_ASSERT(exitcount >= arg);
   362         exitcount -= arg;
   363         PR_Unlock(exitlock);
   364     }
   366     /* Join all the threads */
   367     for(index=0; index<(arg); index++)  {
   368 	DPRINTF(("CondVarTestPUU: joining thread 0x%lx\n",list[index].thread));
   369         PR_JoinThread(list[index].thread);
   370         if (list[index].internal) {
   371             PR_Lock(list[index].lock);
   372             PR_DestroyCondVar(list[index].cvar);
   373             PR_Unlock(list[index].lock);
   374             PR_DestroyLock(list[index].lock);
   375         }
   376     }
   378     PR_DestroyCondVar(sharedcvar);
   379     PR_DestroyLock(sharedlock);
   380     PR_DestroyCondVar(exitcvar);
   381     PR_DestroyLock(exitlock);
   383     PR_DELETE(list);
   384     PR_DELETE(saved_tcount);
   385 }
   387 void 
   388 CondVarTestPUK(void *_arg)
   389 {
   390     PRInt32 arg = (PRInt32)_arg;
   391     PRInt32 index, loops;
   392     threadinfo *list;
   393     PRLock *sharedlock;
   394     PRCondVar *sharedcvar;
   395     PRLock *exitlock;
   396     PRCondVar *exitcvar;
   397     PRInt32 *tcount, *saved_tcount;
   399     exitcount=0;
   400     list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4));
   401     saved_tcount = tcount = (PRInt32 *)PR_CALLOC(sizeof(*tcount) * (arg * 4));
   403     sharedlock = PR_NewLock();
   404     sharedcvar = PR_NewCondVar(sharedlock);
   405     exitlock = PR_NewLock();
   406     exitcvar = PR_NewCondVar(exitlock);
   408     /* Create the threads */
   409     for(index=0; index<arg; ) {
   410         list[index].lock = PR_NewLock();
   411         list[index].cvar = PR_NewCondVar(list[index].lock);
   412         CreateTestThread(&list[index],
   413                          index,
   414                          list[index].lock,
   415                          list[index].cvar,
   416                          count,
   417                          PR_INTERVAL_NO_TIMEOUT,
   418                          tcount,
   419                          exitlock,
   420                          exitcvar,
   421                          &exitcount,
   422                          PR_FALSE,
   423                          PR_GLOBAL_THREAD);
   425         index++;
   426         tcount++;
   427     }
   429     for (loops = 0; loops < count; loops++) {
   430         /* Notify the threads */
   431         for(index=0; index<(arg); index++) {
   433             PR_Lock(list[index].lock);
   434             (*list[index].tcount)++;
   435             PR_NotifyCondVar(list[index].cvar);
   436             PR_Unlock(list[index].lock);
   437         }
   439         /* Wait for threads to finish */
   440         PR_Lock(exitlock);
   441         while(exitcount < arg)
   442             PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60));
   443         PR_ASSERT(exitcount >= arg);
   444         exitcount -= arg;
   445         PR_Unlock(exitlock);
   446     }
   448     /* Join all the threads */
   449     for(index=0; index<(arg); index++) {
   450         PR_JoinThread(list[index].thread);
   451         if (list[index].internal) {
   452             PR_Lock(list[index].lock);
   453             PR_DestroyCondVar(list[index].cvar);
   454             PR_Unlock(list[index].lock);
   455             PR_DestroyLock(list[index].lock);
   456         }
   457     }
   459     PR_DestroyCondVar(sharedcvar);
   460     PR_DestroyLock(sharedlock);
   461     PR_DestroyCondVar(exitcvar);
   462     PR_DestroyLock(exitlock);
   464     PR_DELETE(list);
   465     PR_DELETE(saved_tcount);
   466 }
   468 void 
   469 CondVarTest(void *_arg)
   470 {
   471     PRInt32 arg = (PRInt32)_arg;
   472     PRInt32 index, loops;
   473     threadinfo *list;
   474     PRLock *sharedlock;
   475     PRCondVar *sharedcvar;
   476     PRLock *exitlock;
   477     PRCondVar *exitcvar;
   478     PRInt32 *ptcount, *saved_ptcount;
   480     exitcount=0;
   481     tcount=0;
   482     list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4));
   483     saved_ptcount = ptcount = (PRInt32 *)PR_CALLOC(sizeof(*ptcount) * (arg * 4));
   485     sharedlock = PR_NewLock();
   486     sharedcvar = PR_NewCondVar(sharedlock);
   487     exitlock = PR_NewLock();
   488     exitcvar = PR_NewCondVar(exitlock);
   490     /* Create the threads */
   491     for(index=0; index<arg*4; ) {
   492         CreateTestThread(&list[index],
   493                          index,
   494                          sharedlock,
   495                          sharedcvar,
   496                          count,
   497                          PR_INTERVAL_NO_TIMEOUT,
   498                          &tcount,
   499                          exitlock,
   500                          exitcvar,
   501                          &exitcount,
   502                          PR_TRUE,
   503                          PR_LOCAL_THREAD);
   505         index++;
   506         CreateTestThread(&list[index],
   507                          index,
   508                          sharedlock,
   509                          sharedcvar,
   510                          count,
   511                          PR_INTERVAL_NO_TIMEOUT,
   512                          &tcount,
   513                          exitlock,
   514                          exitcvar,
   515                          &exitcount,
   516                          PR_TRUE,
   517                          PR_GLOBAL_THREAD);
   519         index++;
   520         list[index].lock = PR_NewLock();
   521         list[index].cvar = PR_NewCondVar(list[index].lock);
   522         CreateTestThread(&list[index],
   523                          index,
   524                          list[index].lock,
   525                          list[index].cvar,
   526                          count,
   527                          PR_INTERVAL_NO_TIMEOUT,
   528                          ptcount,
   529                          exitlock,
   530                          exitcvar,
   531                          &exitcount,
   532                          PR_FALSE,
   533                          PR_LOCAL_THREAD);
   534         index++;
   535 	ptcount++;
   536         list[index].lock = PR_NewLock();
   537         list[index].cvar = PR_NewCondVar(list[index].lock);
   538         CreateTestThread(&list[index],
   539                          index,
   540                          list[index].lock,
   541                          list[index].cvar,
   542                          count,
   543                          PR_INTERVAL_NO_TIMEOUT,
   544                          ptcount,
   545                          exitlock,
   546                          exitcvar,
   547                          &exitcount,
   548                          PR_FALSE,
   549                          PR_GLOBAL_THREAD);
   551         index++;
   552 	ptcount++;
   553     }
   555     for (loops = 0; loops < count; loops++) {
   557         /* Notify the threads */
   558         for(index=0; index<(arg*4); index++) {
   559             PR_Lock(list[index].lock);
   560             (*list[index].tcount)++;
   561             PR_NotifyCondVar(list[index].cvar);
   562             PR_Unlock(list[index].lock);
   563         }
   565 #if 0
   566         printf("wait for threads done\n");
   567 #endif
   569         /* Wait for threads to finish */
   570         PR_Lock(exitlock);
   571         while(exitcount < arg*4)
   572             PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60));
   573         PR_ASSERT(exitcount >= arg*4);
   574         exitcount -= arg*4;
   575         PR_Unlock(exitlock);
   576 #if 0
   577         printf("threads ready\n");
   578 #endif
   579     }
   581     /* Join all the threads */
   582     for(index=0; index<(arg*4); index++) {
   583         PR_JoinThread(list[index].thread);
   584         if (list[index].internal) {
   585             PR_Lock(list[index].lock);
   586             PR_DestroyCondVar(list[index].cvar);
   587             PR_Unlock(list[index].lock);
   588             PR_DestroyLock(list[index].lock);
   589         }
   590     }
   592     PR_DestroyCondVar(sharedcvar);
   593     PR_DestroyLock(sharedlock);
   594     PR_DestroyCondVar(exitcvar);
   595     PR_DestroyLock(exitlock);
   597     PR_DELETE(list);
   598     PR_DELETE(saved_ptcount);
   599 }
   601 void 
   602 CondVarTimeoutTest(void *_arg)
   603 {
   604     PRInt32 arg = (PRInt32)_arg;
   605     PRInt32 index, loops;
   606     threadinfo *list;
   607     PRLock *sharedlock;
   608     PRCondVar *sharedcvar;
   609     PRLock *exitlock;
   610     PRCondVar *exitcvar;
   612     list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4));
   614     sharedlock = PR_NewLock();
   615     sharedcvar = PR_NewCondVar(sharedlock);
   616     exitlock = PR_NewLock();
   617     exitcvar = PR_NewCondVar(exitlock);
   619     /* Create the threads */
   620     for(index=0; index<arg*4; ) {
   621         CreateTestThread(&list[index],
   622                          index,
   623                          sharedlock,
   624                          sharedcvar,
   625                          count,
   626                          PR_MillisecondsToInterval(50),
   627                          &tcount,
   628                          exitlock,
   629                          exitcvar,
   630                          &exitcount,
   631                          PR_TRUE,
   632                          PR_LOCAL_THREAD);
   633         index++;
   634         CreateTestThread(&list[index],
   635                          index,
   636                          sharedlock,
   637                          sharedcvar,
   638                          count,
   639                          PR_MillisecondsToInterval(50),
   640                          &tcount,
   641                          exitlock,
   642                          exitcvar,
   643                          &exitcount,
   644                          PR_TRUE,
   645                          PR_GLOBAL_THREAD);
   646         index++;
   647         list[index].lock = PR_NewLock();
   648         list[index].cvar = PR_NewCondVar(list[index].lock);
   649         CreateTestThread(&list[index],
   650                          index,
   651                          list[index].lock,
   652                          list[index].cvar,
   653                          count,
   654                          PR_MillisecondsToInterval(50),
   655                          &tcount,
   656                          exitlock,
   657                          exitcvar,
   658                          &exitcount,
   659                          PR_FALSE,
   660                          PR_LOCAL_THREAD);
   661         index++;
   663         list[index].lock = PR_NewLock();
   664         list[index].cvar = PR_NewCondVar(list[index].lock);
   665         CreateTestThread(&list[index],
   666                          index,
   667                          list[index].lock,
   668                          list[index].cvar,
   669                          count,
   670                          PR_MillisecondsToInterval(50),
   671                          &tcount,
   672                          exitlock,
   673                          exitcvar,
   674                          &exitcount,
   675                          PR_FALSE,
   676                          PR_GLOBAL_THREAD);
   678         index++;
   679     }
   681     for (loops = 0; loops < count; loops++) {
   683         /* Wait for threads to finish */
   684         PR_Lock(exitlock);
   685         while(exitcount < arg*4)
   686             PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60));
   687         PR_ASSERT(exitcount >= arg*4);
   688         exitcount -= arg*4;
   689         PR_Unlock(exitlock);
   690     }
   693     /* Join all the threads */
   694     for(index=0; index<(arg*4); index++) {
   695         PR_JoinThread(list[index].thread);
   696         if (list[index].internal) {
   697             PR_Lock(list[index].lock);
   698             PR_DestroyCondVar(list[index].cvar);
   699             PR_Unlock(list[index].lock);
   700             PR_DestroyLock(list[index].lock);
   701         }
   702     }
   704     PR_DestroyCondVar(sharedcvar);
   705     PR_DestroyLock(sharedlock);
   706     PR_DestroyCondVar(exitcvar);
   707     PR_DestroyLock(exitlock);
   709     PR_DELETE(list);
   710 }
   712 void 
   713 CondVarMixedTest(void *_arg)
   714 {
   715     PRInt32 arg = (PRInt32)_arg;
   716     PRInt32 index, loops;
   717     threadinfo *list;
   718     PRLock *sharedlock;
   719     PRCondVar *sharedcvar;
   720     PRLock *exitlock;
   721     PRCondVar *exitcvar;
   722     PRInt32 *ptcount;
   724     exitcount=0;
   725     tcount=0;
   726     list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4));
   727     ptcount = (PRInt32 *)PR_CALLOC(sizeof(*ptcount) * (arg * 4));
   729     sharedlock = PR_NewLock();
   730     sharedcvar = PR_NewCondVar(sharedlock);
   731     exitlock = PR_NewLock();
   732     exitcvar = PR_NewCondVar(exitlock);
   734     /* Create the threads */
   735     for(index=0; index<arg*4; ) {
   736         CreateTestThread(&list[index],
   737                          index,
   738                          sharedlock,
   739                          sharedcvar,
   740                          count,
   741                          PR_MillisecondsToInterval(50),
   742                          &tcount,
   743                          exitlock,
   744                          exitcvar,
   745                          &exitcount,
   746                          PR_TRUE,
   747                          PR_LOCAL_THREAD);
   748         index++;
   749         CreateTestThread(&list[index],
   750                          index,
   751                          sharedlock,
   752                          sharedcvar,
   753                          count,
   754                          PR_MillisecondsToInterval(50),
   755                          &tcount,
   756                          exitlock,
   757                          exitcvar,
   758                          &exitcount,
   759                          PR_TRUE,
   760                          PR_GLOBAL_THREAD);
   761         index++;
   762         list[index].lock = PR_NewLock();
   763         list[index].cvar = PR_NewCondVar(list[index].lock);
   764         CreateTestThread(&list[index],
   765                          index,
   766                          list[index].lock,
   767                          list[index].cvar,
   768                          count,
   769                          PR_MillisecondsToInterval(50),
   770                          ptcount,
   771                          exitlock,
   772                          exitcvar,
   773                          &exitcount,
   774                          PR_FALSE,
   775                          PR_LOCAL_THREAD);
   776         index++;
   777 	ptcount++;
   779         list[index].lock = PR_NewLock();
   780         list[index].cvar = PR_NewCondVar(list[index].lock);
   781         CreateTestThread(&list[index],
   782                          index,
   783                          list[index].lock,
   784                          list[index].cvar,
   785                          count,
   786                          PR_MillisecondsToInterval(50),
   787                          ptcount,
   788                          exitlock,
   789                          exitcvar,
   790                          &exitcount,
   791                          PR_FALSE,
   792                          PR_GLOBAL_THREAD);
   793         index++;
   794 	ptcount++;
   795     }
   798     /* Notify every 3rd thread */
   799     for (loops = 0; loops < count; loops++) {
   801         /* Notify the threads */
   802         for(index=0; index<(arg*4); index+=3) {
   804             PR_Lock(list[index].lock);
   805             *list[index].tcount++;
   806             PR_NotifyCondVar(list[index].cvar);
   807             PR_Unlock(list[index].lock);
   809         }
   810         /* Wait for threads to finish */
   811         PR_Lock(exitlock);
   812         while(exitcount < arg*4)
   813             PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60));
   814         PR_ASSERT(exitcount >= arg*4);
   815         exitcount -= arg*4;
   816         PR_Unlock(exitlock);
   817     }
   819     /* Join all the threads */
   820     for(index=0; index<(arg*4); index++) {
   821         PR_JoinThread(list[index].thread);
   822         if (list[index].internal) {
   823             PR_Lock(list[index].lock);
   824             PR_DestroyCondVar(list[index].cvar);
   825             PR_Unlock(list[index].lock);
   826             PR_DestroyLock(list[index].lock);
   827         }
   828     }
   830     PR_DestroyCondVar(sharedcvar);
   831     PR_DestroyLock(sharedlock);
   833     PR_DELETE(list);
   834 }
   836 void 
   837 CondVarCombinedTest(void *arg)
   838 {
   839     PRThread *threads[3];
   841     threads[0] = PR_CreateThread(PR_USER_THREAD,
   842                                  CondVarTest,
   843                                  (void *)arg,
   844                                  PR_PRIORITY_NORMAL,
   845                                  PR_GLOBAL_THREAD,
   846                                  PR_JOINABLE_THREAD,
   847                                  0);
   848     threads[1] = PR_CreateThread(PR_USER_THREAD,
   849                                  CondVarTimeoutTest,
   850                                  (void *)arg,
   851                                  PR_PRIORITY_NORMAL,
   852                                  PR_GLOBAL_THREAD,
   853                                  PR_JOINABLE_THREAD,
   854                                  0);
   855     threads[2] = PR_CreateThread(PR_USER_THREAD,
   856                                  CondVarMixedTest,
   857                                  (void *)arg,
   858                                  PR_PRIORITY_NORMAL,
   859                                  PR_GLOBAL_THREAD,
   860                                  PR_JOINABLE_THREAD,
   861                                  0);
   863     PR_JoinThread(threads[0]);
   864     PR_JoinThread(threads[1]);
   865     PR_JoinThread(threads[2]);
   866 }
   868 /************************************************************************/
   870 static void Measure(void (*func)(void *), PRInt32 arg, const char *msg)
   871 {
   872     PRIntervalTime start, stop;
   873     double d;
   875     start = PR_IntervalNow();
   876     (*func)((void *)arg);
   877     stop = PR_IntervalNow();
   879     d = (double)PR_IntervalToMicroseconds(stop - start);
   881     printf("%40s: %6.2f usec\n", msg, d / count);
   882 }
   884 static PRIntn PR_CALLBACK RealMain(int argc, char **argv)
   885 {
   886     PRInt32 threads, default_threads = DEFAULT_THREADS;
   887 	PLOptStatus os;
   888 	PLOptState *opt = PL_CreateOptState(argc, argv, "vc:t:");
   889 	while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
   890     {
   891 		if (PL_OPT_BAD == os) continue;
   892         switch (opt->option)
   893         {
   894         case 'v':  /* debug mode */
   895 			_debug_on = 1;
   896             break;
   897         case 'c':  /* loop counter */
   898 			count = atoi(opt->value);
   899             break;
   900         case 't':  /* number of threads involved */
   901 			default_threads = atoi(opt->value);
   902             break;
   903          default:
   904             break;
   905         }
   906     }
   907 	PL_DestroyOptState(opt);
   909     if (0 == count) count = DEFAULT_COUNT;
   910     if (0 == default_threads) default_threads = DEFAULT_THREADS;
   912     printf("\n\
   913 CondVar Test:                                                           \n\
   914                                                                         \n\
   915 Simple test creates several local and global threads; half use a single,\n\
   916 shared condvar, and the other half have their own condvar.  The main    \n\
   917 thread then loops notifying them to wakeup.                             \n\
   918                                                                         \n\
   919 The timeout test is very similar except that the threads are not        \n\
   920 notified.  They will all wakeup on a 1 second timeout.                  \n\
   921                                                                         \n\
   922 The mixed test combines the simple test and the timeout test; every     \n\
   923 third thread is notified, the other threads are expected to timeout     \n\
   924 correctly.                                                              \n\
   925                                                                         \n\
   926 Lastly, the combined test creates a thread for each of the above three  \n\
   927 cases and they all run simultaneously.                                  \n\
   928                                                                         \n\
   929 This test is run with %d, %d, %d, and %d threads of each type.\n\n",
   930 default_threads, default_threads*2, default_threads*3, default_threads*4);
   932     PR_SetConcurrency(2);
   934     for (threads = default_threads; threads < default_threads*5; threads+=default_threads) {
   935         printf("\n%ld Thread tests\n", threads);
   936         Measure(CondVarTestSUU, threads, "Condvar simple test shared UU");
   937         Measure(CondVarTestSUK, threads, "Condvar simple test shared UK");
   938         Measure(CondVarTestPUU, threads, "Condvar simple test priv UU");
   939         Measure(CondVarTestPUK, threads, "Condvar simple test priv UK");
   940         Measure(CondVarTest, threads, "Condvar simple test All");
   941         Measure(CondVarTimeoutTest, threads,  "Condvar timeout test");
   942 #if 0
   943         Measure(CondVarMixedTest, threads,  "Condvar mixed timeout test");
   944         Measure(CondVarCombinedTest, threads, "Combined condvar test");
   945 #endif
   946     }
   948     printf("PASS\n");
   950     return 0;
   951 }
   953 int main(int argc, char **argv)
   954 {
   955     PRIntn rv;
   957     PR_STDIO_INIT();
   958     rv = PR_Initialize(RealMain, argc, argv, 0);
   959     return rv;
   960 }  /* main */

mercurial