concur.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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/. */
  5. /*
  6. ** File: concur.c
  7. ** Description: test of adding and removing concurrency options
  8. */
  9. #include "prcvar.h"
  10. #include "prinit.h"
  11. #include "prinrval.h"
  12. #include "prlock.h"
  13. #include "prprf.h"
  14. #include "prmem.h"
  15. #include "prlog.h"
  16. #include "plgetopt.h"
  17. #include "private/pprio.h"
  18. #include <stdlib.h>
  19. #define DEFAULT_RANGE 10
  20. #define DEFAULT_LOOPS 100
  21. static PRThreadScope thread_scope = PR_LOCAL_THREAD;
  22. typedef struct Context
  23. {
  24. PRLock *ml;
  25. PRCondVar *cv;
  26. PRIntn want, have;
  27. } Context;
  28. /*
  29. ** Make the instance of 'context' static (not on the stack)
  30. ** for Win16 threads
  31. */
  32. static Context context = {NULL, NULL, 0, 0};
  33. static void PR_CALLBACK Dull(void *arg)
  34. {
  35. Context *context = (Context*)arg;
  36. PR_Lock(context->ml);
  37. context->have += 1;
  38. while (context->want >= context->have) {
  39. PR_WaitCondVar(context->cv, PR_INTERVAL_NO_TIMEOUT);
  40. }
  41. context->have -= 1;
  42. PR_Unlock(context->ml);
  43. } /* Dull */
  44. PRIntn PR_CALLBACK Concur(PRIntn argc, char **argv)
  45. {
  46. PRUintn cpus;
  47. PLOptStatus os;
  48. PRThread **threads;
  49. PRBool debug = PR_FALSE;
  50. PRUintn range = DEFAULT_RANGE;
  51. PRStatus rc;
  52. PRUintn cnt;
  53. PRUintn loops = DEFAULT_LOOPS;
  54. PRIntervalTime hundredMills = PR_MillisecondsToInterval(100);
  55. PLOptState *opt = PL_CreateOptState(argc, argv, "Gdl:r:");
  56. while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
  57. {
  58. if (PL_OPT_BAD == os) {
  59. continue;
  60. }
  61. switch (opt->option)
  62. {
  63. case 'G': /* GLOBAL threads */
  64. thread_scope = PR_GLOBAL_THREAD;
  65. break;
  66. case 'd': /* debug mode */
  67. debug = PR_TRUE;
  68. break;
  69. case 'r': /* range limit */
  70. range = atoi(opt->value);
  71. break;
  72. case 'l': /* loop counter */
  73. loops = atoi(opt->value);
  74. break;
  75. default:
  76. break;
  77. }
  78. }
  79. PL_DestroyOptState(opt);
  80. if (0 == range) {
  81. range = DEFAULT_RANGE;
  82. }
  83. if (0 == loops) {
  84. loops = DEFAULT_LOOPS;
  85. }
  86. context.ml = PR_NewLock();
  87. context.cv = PR_NewCondVar(context.ml);
  88. if (debug)
  89. PR_fprintf(
  90. PR_STDERR, "Testing with %d CPUs and %d interations\n", range, loops);
  91. threads = (PRThread**) PR_CALLOC(sizeof(PRThread*) * range);
  92. while (--loops > 0)
  93. {
  94. for (cpus = 1; cpus <= range; ++cpus)
  95. {
  96. PR_SetConcurrency(cpus);
  97. context.want = cpus;
  98. threads[cpus - 1] = PR_CreateThread(
  99. PR_USER_THREAD, Dull, &context, PR_PRIORITY_NORMAL,
  100. thread_scope, PR_JOINABLE_THREAD, 0);
  101. }
  102. PR_Sleep(hundredMills);
  103. for (cpus = range; cpus > 0; cpus--)
  104. {
  105. PR_SetConcurrency(cpus);
  106. context.want = cpus - 1;
  107. PR_Lock(context.ml);
  108. PR_NotifyCondVar(context.cv);
  109. PR_Unlock(context.ml);
  110. }
  111. for(cnt = 0; cnt < range; cnt++) {
  112. rc = PR_JoinThread(threads[cnt]);
  113. PR_ASSERT(rc == PR_SUCCESS);
  114. }
  115. }
  116. if (debug)
  117. PR_fprintf(
  118. PR_STDERR, "Waiting for %d thread(s) to exit\n", context.have);
  119. while (context.have > 0) {
  120. PR_Sleep(hundredMills);
  121. }
  122. if (debug)
  123. PR_fprintf(
  124. PR_STDERR, "Finished [want: %d, have: %d]\n",
  125. context.want, context.have);
  126. PR_DestroyLock(context.ml);
  127. PR_DestroyCondVar(context.cv);
  128. PR_DELETE(threads);
  129. PR_fprintf(PR_STDERR, "PASSED\n");
  130. return 0;
  131. } /* Concur */
  132. int main(int argc, char **argv)
  133. {
  134. PR_STDIO_INIT();
  135. return PR_Initialize(Concur, argc, argv, 0);
  136. } /* main */
  137. /* concur.c */