subthread_create.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #ifdef HAVE_CONFIG_H
  2. /* For PARALLEL_MARK */
  3. # include "config.h"
  4. #endif
  5. #ifndef GC_THREADS
  6. # define GC_THREADS
  7. #endif
  8. #include "gc.h"
  9. #ifdef PARALLEL_MARK
  10. # define AO_REQUIRE_CAS
  11. #endif
  12. #include "private/gc_atomic_ops.h"
  13. #include <stdio.h>
  14. #ifdef AO_HAVE_fetch_and_add1
  15. #ifdef GC_PTHREADS
  16. # include <pthread.h>
  17. #else
  18. # include <windows.h>
  19. #endif
  20. #if defined(__HAIKU__)
  21. # include <errno.h>
  22. #endif
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #ifndef NTHREADS
  26. # define NTHREADS 31 /* number of initial threads */
  27. #endif
  28. #ifndef MAX_SUBTHREAD_DEPTH
  29. # define MAX_ALIVE_THREAD_COUNT 55
  30. # define MAX_SUBTHREAD_DEPTH 7
  31. # define MAX_SUBTHREAD_COUNT 200
  32. #endif
  33. #ifndef DECAY_NUMER
  34. # define DECAY_NUMER 15
  35. # define DECAY_DENOM 16
  36. #endif
  37. volatile AO_t thread_created_cnt = 0;
  38. volatile AO_t thread_ended_cnt = 0;
  39. #ifdef GC_PTHREADS
  40. void *entry(void *arg)
  41. #else
  42. DWORD WINAPI entry(LPVOID arg)
  43. #endif
  44. {
  45. int thread_num = AO_fetch_and_add1(&thread_created_cnt);
  46. GC_word my_depth = (GC_word)arg + 1;
  47. if (my_depth <= MAX_SUBTHREAD_DEPTH
  48. && thread_num < MAX_SUBTHREAD_COUNT
  49. && (thread_num % DECAY_DENOM) < DECAY_NUMER
  50. && thread_num - (int)AO_load(&thread_ended_cnt)
  51. <= MAX_ALIVE_THREAD_COUNT) {
  52. # ifdef GC_PTHREADS
  53. int err;
  54. pthread_t th;
  55. err = pthread_create(&th, NULL, entry, (void *)my_depth);
  56. if (err != 0) {
  57. fprintf(stderr, "Thread #%d creation failed: %s\n", thread_num,
  58. strerror(err));
  59. exit(2);
  60. }
  61. err = pthread_detach(th);
  62. if (err != 0) {
  63. fprintf(stderr, "Thread #%d detach failed: %s\n", thread_num,
  64. strerror(err));
  65. exit(2);
  66. }
  67. # else
  68. HANDLE th;
  69. DWORD thread_id;
  70. th = CreateThread(NULL, 0, entry, (LPVOID)my_depth, 0, &thread_id);
  71. if (th == NULL) {
  72. fprintf(stderr, "Thread #%d creation failed: %d\n", thread_num,
  73. (int)GetLastError());
  74. exit(2);
  75. }
  76. CloseHandle(th);
  77. # endif
  78. }
  79. (void)AO_fetch_and_add1(&thread_ended_cnt);
  80. return 0;
  81. }
  82. int main(void)
  83. {
  84. #if NTHREADS > 0
  85. int i;
  86. # ifdef GC_PTHREADS
  87. int err;
  88. pthread_t th[NTHREADS];
  89. # else
  90. HANDLE th[NTHREADS];
  91. # endif
  92. GC_INIT();
  93. for (i = 0; i < NTHREADS; ++i) {
  94. # ifdef GC_PTHREADS
  95. err = pthread_create(&th[i], NULL, entry, 0);
  96. if (err) {
  97. fprintf(stderr, "Thread creation failed: %s\n", strerror(err));
  98. exit(1);
  99. }
  100. # else
  101. DWORD thread_id;
  102. th[i] = CreateThread(NULL, 0, entry, 0, 0, &thread_id);
  103. if (th[i] == NULL) {
  104. fprintf(stderr, "Thread creation failed: %d\n",
  105. (int)GetLastError());
  106. exit(1);
  107. }
  108. # endif
  109. }
  110. for (i = 0; i < NTHREADS; ++i) {
  111. # ifdef GC_PTHREADS
  112. void *res;
  113. err = pthread_join(th[i], &res);
  114. if (err) {
  115. fprintf(stderr, "Failed to join thread: %s\n", strerror(err));
  116. # if defined(__HAIKU__)
  117. /* The error is just ignored (and the test is ended) to */
  118. /* workaround some bug in Haiku pthread_join. */
  119. /* TODO: The thread is not deleted from GC_threads. */
  120. if (ESRCH == err) break;
  121. # endif
  122. exit(1);
  123. }
  124. # else
  125. if (WaitForSingleObject(th[i], INFINITE) != WAIT_OBJECT_0) {
  126. fprintf(stderr, "Failed to join thread: %d\n",
  127. (int)GetLastError());
  128. CloseHandle(th[i]);
  129. exit(1);
  130. }
  131. CloseHandle(th[i]);
  132. # endif
  133. }
  134. #endif
  135. printf("subthread_create: created %d threads (%d ended)\n",
  136. (int)AO_load(&thread_created_cnt), (int)AO_load(&thread_ended_cnt));
  137. return 0;
  138. }
  139. #else
  140. int main(void)
  141. {
  142. printf("subthread_create test skipped\n");
  143. return 0;
  144. }
  145. #endif /* !AO_HAVE_fetch_and_add1 */