home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / pr / tests / cvar2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  30.6 KB  |  989 lines

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