threads.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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. #include "nspr.h"
  6. #include "prinrval.h"
  7. #include "plgetopt.h"
  8. #include "pprthred.h"
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. PRMonitor *mon;
  13. PRInt32 count, iterations, alive;
  14. PRBool debug_mode = PR_FALSE, passed = PR_TRUE;
  15. void
  16. PR_CALLBACK
  17. ReallyDumbThread(void *arg)
  18. {
  19. return;
  20. }
  21. void
  22. PR_CALLBACK
  23. DumbThread(void *arg)
  24. {
  25. PRInt32 tmp = (PRInt32)arg;
  26. PRThreadScope scope = (PRThreadScope)tmp;
  27. PRThread *thr;
  28. thr = PR_CreateThread(PR_USER_THREAD,
  29. ReallyDumbThread,
  30. NULL,
  31. PR_PRIORITY_NORMAL,
  32. scope,
  33. PR_JOINABLE_THREAD,
  34. 0);
  35. if (!thr) {
  36. if (debug_mode) {
  37. printf("Could not create really dumb thread (%d, %d)!\n",
  38. PR_GetError(), PR_GetOSError());
  39. }
  40. passed = PR_FALSE;
  41. } else {
  42. PR_JoinThread(thr);
  43. }
  44. PR_EnterMonitor(mon);
  45. alive--;
  46. PR_Notify(mon);
  47. PR_ExitMonitor(mon);
  48. }
  49. static void CreateThreads(PRThreadScope scope1, PRThreadScope scope2)
  50. {
  51. PRThread *thr;
  52. int n;
  53. alive = 0;
  54. mon = PR_NewMonitor();
  55. alive = count;
  56. for (n=0; n<count; n++) {
  57. thr = PR_CreateThread(PR_USER_THREAD,
  58. DumbThread,
  59. (void *)scope2,
  60. PR_PRIORITY_NORMAL,
  61. scope1,
  62. PR_UNJOINABLE_THREAD,
  63. 0);
  64. if (!thr) {
  65. if (debug_mode) {
  66. printf("Could not create dumb thread (%d, %d)!\n",
  67. PR_GetError(), PR_GetOSError());
  68. }
  69. passed = PR_FALSE;
  70. alive--;
  71. }
  72. PR_Sleep(0);
  73. }
  74. /* Wait for all threads to exit */
  75. PR_EnterMonitor(mon);
  76. while (alive) {
  77. PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
  78. }
  79. PR_ExitMonitor(mon);
  80. PR_DestroyMonitor(mon);
  81. }
  82. static void CreateThreadsUU(void)
  83. {
  84. CreateThreads(PR_LOCAL_THREAD, PR_LOCAL_THREAD);
  85. }
  86. static void CreateThreadsUK(void)
  87. {
  88. CreateThreads(PR_LOCAL_THREAD, PR_GLOBAL_THREAD);
  89. }
  90. static void CreateThreadsKU(void)
  91. {
  92. CreateThreads(PR_GLOBAL_THREAD, PR_LOCAL_THREAD);
  93. }
  94. static void CreateThreadsKK(void)
  95. {
  96. CreateThreads(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD);
  97. }
  98. /************************************************************************/
  99. static void Measure(void (*func)(void), const char *msg)
  100. {
  101. PRIntervalTime start, stop;
  102. double d;
  103. start = PR_IntervalNow();
  104. (*func)();
  105. stop = PR_IntervalNow();
  106. if (debug_mode)
  107. {
  108. d = (double)PR_IntervalToMicroseconds(stop - start);
  109. printf("%40s: %6.2f usec\n", msg, d / count);
  110. }
  111. }
  112. int main(int argc, char **argv)
  113. {
  114. int index;
  115. PR_STDIO_INIT();
  116. PR_Init(PR_USER_THREAD, PR_PRIORITY_HIGH, 0);
  117. {
  118. PLOptStatus os;
  119. PLOptState *opt = PL_CreateOptState(argc, argv, "dc:i:");
  120. while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
  121. {
  122. if (PL_OPT_BAD == os) {
  123. continue;
  124. }
  125. switch (opt->option)
  126. {
  127. case 'd': /* debug mode */
  128. debug_mode = PR_TRUE;
  129. break;
  130. case 'c': /* loop counter */
  131. count = atoi(opt->value);
  132. break;
  133. case 'i': /* loop counter */
  134. iterations = atoi(opt->value);
  135. break;
  136. default:
  137. break;
  138. }
  139. }
  140. PL_DestroyOptState(opt);
  141. }
  142. if (0 == count) {
  143. count = 50;
  144. }
  145. if (0 == iterations) {
  146. iterations = 10;
  147. }
  148. if (debug_mode)
  149. {
  150. printf("\
  151. ** Tests lots of thread creations. \n\
  152. ** Create %ld native threads %ld times. \n\
  153. ** Create %ld user threads %ld times \n", iterations,count,iterations,count);
  154. }
  155. for (index=0; index<iterations; index++) {
  156. Measure(CreateThreadsUU, "Create user/user threads");
  157. Measure(CreateThreadsUK, "Create user/native threads");
  158. Measure(CreateThreadsKU, "Create native/user threads");
  159. Measure(CreateThreadsKK, "Create native/native threads");
  160. }
  161. if (debug_mode) {
  162. printf("\nNow switch to recycling threads \n\n");
  163. }
  164. PR_SetThreadRecycleMode(1);
  165. for (index=0; index<iterations; index++) {
  166. Measure(CreateThreadsUU, "Create user/user threads");
  167. Measure(CreateThreadsUK, "Create user/native threads");
  168. Measure(CreateThreadsKU, "Create native/user threads");
  169. Measure(CreateThreadsKK, "Create native/native threads");
  170. }
  171. printf("%s\n", ((passed) ? "PASS" : "FAIL"));
  172. PR_Cleanup();
  173. if (passed) {
  174. return 0;
  175. } else {
  176. return 1;
  177. }
  178. }