initfromthread.c raw

   1  /*
   2   * Copyright (c) 2011 Ludovic Courtes
   3   *
   4   * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
   5   * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
   6   *
   7   * Permission is hereby granted to use or copy this program
   8   * for any purpose, provided the above notices are retained on all copies.
   9   * Permission to modify the code and to distribute modified code is granted,
  10   * provided the above notices are retained, and a notice that the code was
  11   * modified is included with the above copyright notice.
  12   */
  13  
  14  /*
  15   * Make sure `GC_INIT()` can be called from threads other than the
  16   * initial thread.
  17   */
  18  
  19  #ifdef HAVE_CONFIG_H
  20  #  include "config.h"
  21  #endif
  22  
  23  #ifndef GC_THREADS
  24  #  define GC_THREADS
  25  #endif
  26  
  27  /* Do not redirect thread creation and join calls. */
  28  #define GC_NO_THREAD_REDIRECTS 1
  29  
  30  #include "gc.h"
  31  
  32  #ifdef GC_PTHREADS
  33  #  include <pthread.h>
  34  #else
  35  #  ifndef WIN32_LEAN_AND_MEAN
  36  #    define WIN32_LEAN_AND_MEAN 1
  37  #  endif
  38  #  define NOSERVICE
  39  #  include <windows.h>
  40  #endif /* !GC_PTHREADS */
  41  
  42  #include <stdio.h>
  43  #include <stdlib.h>
  44  
  45  #define CHECK_OUT_OF_MEMORY(p)            \
  46    do {                                    \
  47      if (NULL == (p)) {                    \
  48        fprintf(stderr, "Out of memory\n"); \
  49        exit(69);                           \
  50      }                                     \
  51    } while (0)
  52  
  53  #ifdef GC_PTHREADS
  54  static void *
  55  thread(void *arg)
  56  #else
  57  static DWORD WINAPI
  58  thread(LPVOID arg)
  59  #endif
  60  {
  61    GC_INIT();
  62    CHECK_OUT_OF_MEMORY(GC_MALLOC(123));
  63    CHECK_OUT_OF_MEMORY(GC_MALLOC(12345));
  64  #ifdef GC_PTHREADS
  65    return arg;
  66  #else
  67    return (DWORD)(GC_uintptr_t)arg;
  68  #endif
  69  }
  70  
  71  #include "private/gcconfig.h"
  72  
  73  int
  74  main(void)
  75  {
  76  #ifdef GC_PTHREADS
  77    int err;
  78    pthread_t t;
  79  
  80  #  ifdef LINT2
  81    /* Explicitly initialize t to some value. */
  82    t = pthread_self();
  83  #  endif
  84  #else
  85    HANDLE t;
  86    DWORD thread_id;
  87  #endif
  88  #if !(defined(ANY_MSWIN) || defined(BEOS)                              \
  89        || (defined(DARWIN) && !defined(NO_PTHREAD_GET_STACKADDR_NP))    \
  90        || ((defined(FREEBSD) || defined(LINUX) || defined(NETBSD)       \
  91             || defined(HOST_ANDROID))                                   \
  92            && !defined(NO_PTHREAD_ATTR_GET_NP)                          \
  93            && !defined(NO_PTHREAD_GETATTR_NP))                          \
  94        || (defined(SOLARIS) && !defined(_STRICT_STDC))                  \
  95        || ((!defined(SPECIFIC_MAIN_STACKBOTTOM) || defined(HEURISTIC1)) \
  96            && !defined(STACKBOTTOM)))
  97    /* `GC_INIT()` must be called from main thread only. */
  98    GC_INIT();
  99  #endif
 100  
 101    /* Linking fails if no thread support. */
 102    (void)GC_get_suspend_signal();
 103  
 104    if (GC_get_find_leak())
 105      printf("This test program is not designed for leak detection mode\n");
 106  #ifdef GC_PTHREADS
 107    err = pthread_create(&t, NULL, thread, NULL);
 108    if (err != 0) {
 109      fprintf(stderr, "Thread #0 creation failed, errno= %d\n", err);
 110      return 1;
 111    }
 112    err = pthread_join(t, NULL);
 113    if (err != 0) {
 114      fprintf(stderr, "Thread #0 join failed, errno= %d\n", err);
 115      return 1;
 116    }
 117  #else
 118    t = CreateThread(NULL, 0, thread, 0, 0, &thread_id);
 119    if (t == NULL) {
 120      fprintf(stderr, "Thread #0 creation failed, errcode= %d\n",
 121              (int)GetLastError());
 122      return 1;
 123    }
 124    if (WaitForSingleObject(t, INFINITE) != WAIT_OBJECT_0) {
 125      fprintf(stderr, "Thread #0 join failed, errcode= %d\n",
 126              (int)GetLastError());
 127      CloseHandle(t);
 128      return 1;
 129    }
 130    CloseHandle(t);
 131  #endif
 132    printf("SUCCEEDED\n");
 133    return 0;
 134  }
 135