threadkey_test.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #ifdef HAVE_CONFIG_H
  2. # include "config.h"
  3. #endif
  4. #ifndef GC_THREADS
  5. # define GC_THREADS
  6. #endif
  7. #define GC_NO_THREAD_REDIRECTS 1
  8. #include "gc.h"
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #if (!defined(GC_PTHREADS) || defined(GC_SOLARIS_THREADS) \
  12. || defined(__native_client__)) && !defined(SKIP_THREADKEY_TEST)
  13. /* FIXME: Skip this test on Solaris for now. The test may fail on */
  14. /* other targets as well. Currently, tested only on Linux, Cygwin */
  15. /* and Darwin. */
  16. # define SKIP_THREADKEY_TEST
  17. #endif
  18. #ifdef SKIP_THREADKEY_TEST
  19. int main (void)
  20. {
  21. printf("threadkey_test skipped\n");
  22. return 0;
  23. }
  24. #else
  25. #include <pthread.h>
  26. pthread_key_t key;
  27. #ifdef GC_SOLARIS_THREADS
  28. /* pthread_once_t key_once = { PTHREAD_ONCE_INIT }; */
  29. #else
  30. pthread_once_t key_once = PTHREAD_ONCE_INIT;
  31. #endif
  32. void * entry (void *arg)
  33. {
  34. pthread_setspecific(key,
  35. (void *)GC_HIDE_POINTER(GC_STRDUP("hello, world")));
  36. return arg;
  37. }
  38. void * GC_CALLBACK on_thread_exit_inner (struct GC_stack_base * sb, void * arg)
  39. {
  40. int res = GC_register_my_thread (sb);
  41. pthread_t t;
  42. int creation_res; /* Used to suppress a warning about */
  43. /* unchecked pthread_create() result. */
  44. pthread_attr_t attr;
  45. if (pthread_attr_init(&attr) != 0
  46. || pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0) {
  47. fprintf(stderr, "Thread attribute init or setdetachstate failed\n");
  48. exit(2);
  49. }
  50. creation_res = GC_pthread_create(&t, &attr, entry, NULL);
  51. (void)pthread_attr_destroy(&attr);
  52. if (res == GC_SUCCESS)
  53. GC_unregister_my_thread ();
  54. return arg ? (void*)(GC_word)creation_res : 0;
  55. }
  56. void on_thread_exit (void *v)
  57. {
  58. GC_call_with_stack_base (on_thread_exit_inner, v);
  59. }
  60. void make_key (void)
  61. {
  62. pthread_key_create (&key, on_thread_exit);
  63. }
  64. #ifndef NTHREADS
  65. # define NTHREADS 30 /* number of initial threads */
  66. #endif
  67. int main (void)
  68. {
  69. int i;
  70. GC_INIT ();
  71. # ifdef GC_SOLARIS_THREADS
  72. pthread_key_create (&key, on_thread_exit);
  73. # else
  74. pthread_once (&key_once, make_key);
  75. # endif
  76. for (i = 0; i < NTHREADS; i++) {
  77. pthread_t t;
  78. if (GC_pthread_create(&t, NULL, entry, NULL) == 0) {
  79. void *res;
  80. int code = (i & 1) != 0 ? GC_pthread_join(t, &res)
  81. : GC_pthread_detach(t);
  82. if (code != 0) {
  83. fprintf(stderr, "Thread %s failed %d\n",
  84. (i & 1) != 0 ? "join" : "detach", code);
  85. exit(2);
  86. }
  87. }
  88. }
  89. return 0;
  90. }
  91. #endif /* !SKIP_THREADKEY_TEST */