subthreadcreate.c raw

   1  
   2  #ifdef HAVE_CONFIG_H
   3  /* For `GC_THREADS` and `PARALLEL_MARK` macros. */
   4  #  include "config.h"
   5  #endif
   6  
   7  #ifdef GC_THREADS
   8  #  undef GC_NO_THREAD_REDIRECTS
   9  #  include "gc.h"
  10  
  11  #  ifdef PARALLEL_MARK
  12  #    define AO_REQUIRE_CAS
  13  #    if !defined(__GNUC__) && !defined(AO_ASSUME_WINDOWS98)
  14  #      define AO_ASSUME_WINDOWS98
  15  #    endif
  16  #  endif
  17  #  include "private/gc_atomic_ops.h"
  18  #endif /* GC_THREADS */
  19  
  20  #include <stdio.h>
  21  
  22  #ifdef AO_HAVE_fetch_and_add1
  23  
  24  #  ifdef GC_PTHREADS
  25  #    include <errno.h> /*< for `EAGAIN` */
  26  #    include <pthread.h>
  27  #  else
  28  #    ifndef WIN32_LEAN_AND_MEAN
  29  #      define WIN32_LEAN_AND_MEAN 1
  30  #    endif
  31  #    define NOSERVICE
  32  #    include <windows.h>
  33  #  endif /* !GC_PTHREADS */
  34  
  35  #  include <stdlib.h>
  36  
  37  #  ifndef NTHREADS
  38  #    define NTHREADS 5
  39  #  endif
  40  
  41  /* Number of threads to create. */
  42  #  define NTHREADS_INNER (NTHREADS * 6)
  43  
  44  #  ifndef MAX_SUBTHREAD_DEPTH
  45  #    define MAX_ALIVE_THREAD_COUNT 55
  46  #    define MAX_SUBTHREAD_DEPTH 7
  47  #    define MAX_SUBTHREAD_COUNT 200
  48  #  endif
  49  
  50  #  ifndef DECAY_NUMER
  51  #    define DECAY_NUMER 15
  52  #    define DECAY_DENOM 16
  53  #  endif
  54  
  55  volatile AO_t thread_created_cnt = 0;
  56  volatile AO_t thread_ended_cnt = 0;
  57  
  58  #  ifdef GC_PTHREADS
  59  static void *
  60  entry(void *arg)
  61  #  else
  62  static DWORD WINAPI
  63  entry(LPVOID arg)
  64  #  endif
  65  {
  66    int thread_num = (int)AO_fetch_and_add1(&thread_created_cnt);
  67    GC_word my_depth = (GC_word)(GC_uintptr_t)arg + 1;
  68  
  69    if (my_depth <= MAX_SUBTHREAD_DEPTH && thread_num < MAX_SUBTHREAD_COUNT
  70        && (thread_num % DECAY_DENOM) < DECAY_NUMER
  71        && thread_num - (int)AO_load(&thread_ended_cnt)
  72               <= MAX_ALIVE_THREAD_COUNT) {
  73  #  ifdef GC_PTHREADS
  74      int err;
  75      pthread_t th;
  76  
  77      err = pthread_create(&th, NULL, entry, (void *)(GC_uintptr_t)my_depth);
  78      if (err != 0) {
  79        fprintf(stderr,
  80                "Thread #%d creation failed from other thread, errno= %d\n",
  81                thread_num, err);
  82        if (err != EAGAIN)
  83          exit(2);
  84      } else {
  85        err = pthread_detach(th);
  86        if (err != 0) {
  87          fprintf(stderr, "Thread #%d detach failed, errno= %d\n", thread_num,
  88                  err);
  89          exit(2);
  90        }
  91      }
  92  #  else
  93      HANDLE th;
  94      DWORD thread_id;
  95  
  96      th = CreateThread(NULL, 0, entry, (LPVOID)my_depth, 0, &thread_id);
  97      if (th == NULL) {
  98        fprintf(stderr, "Thread #%d creation failed, errcode= %d\n", thread_num,
  99                (int)GetLastError());
 100        exit(2);
 101      }
 102      CloseHandle(th);
 103  #  endif
 104    }
 105  
 106    (void)AO_fetch_and_add1(&thread_ended_cnt);
 107    return 0;
 108  }
 109  
 110  int
 111  main(void)
 112  {
 113  #  if NTHREADS > 0
 114    int i, n;
 115  #    ifdef GC_PTHREADS
 116    int err;
 117    pthread_t th[NTHREADS_INNER];
 118  #    else
 119    HANDLE th[NTHREADS_INNER];
 120  #    endif
 121    int th_nums[NTHREADS_INNER];
 122  
 123    GC_INIT();
 124    for (i = 0; i < NTHREADS_INNER; ++i) {
 125      th_nums[i] = (int)AO_fetch_and_add1(&thread_created_cnt);
 126  #    ifdef GC_PTHREADS
 127      err = pthread_create(&th[i], NULL, entry, 0);
 128      if (err != 0) {
 129        fprintf(stderr, "Thread #%d creation failed, errno= %d\n", th_nums[i],
 130                err);
 131        if (i > 0 && EAGAIN == err)
 132          break;
 133        exit(1);
 134      }
 135  #    else
 136      {
 137        DWORD thread_id;
 138  
 139        th[i] = CreateThread(NULL, 0, entry, 0, 0, &thread_id);
 140      }
 141      if (th[i] == NULL) {
 142        fprintf(stderr, "Thread #%d creation failed, errcode= %d\n", th_nums[i],
 143                (int)GetLastError());
 144        exit(1);
 145      }
 146  #    endif
 147    }
 148    n = i;
 149    for (i = 0; i < n; ++i) {
 150  #    ifdef GC_PTHREADS
 151      void *res;
 152  
 153      err = pthread_join(th[i], &res);
 154      if (err != 0) {
 155        fprintf(stderr, "Thread #%d join failed, errno= %d\n", th_nums[i], err);
 156        exit(1);
 157      }
 158  #    else
 159      if (WaitForSingleObject(th[i], INFINITE) != WAIT_OBJECT_0) {
 160        fprintf(stderr, "Thread #%d join failed, errcode= %d\n", th_nums[i],
 161                (int)GetLastError());
 162        CloseHandle(th[i]);
 163        exit(1);
 164      }
 165      CloseHandle(th[i]);
 166  #    endif
 167    }
 168  #  else
 169    (void)entry(NULL);
 170  #  endif
 171    printf("Created %d threads (%d ended)\n", (int)AO_load(&thread_created_cnt),
 172           (int)AO_load(&thread_ended_cnt));
 173    return 0;
 174  }
 175  
 176  #else
 177  
 178  int
 179  main(void)
 180  {
 181    printf("test skipped\n");
 182    return 0;
 183  }
 184  
 185  #endif /* !AO_HAVE_fetch_and_add1 */
 186