tsd.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #include "test/jemalloc_test.h"
  2. static int data_cleanup_count;
  3. void
  4. data_cleanup(int *data) {
  5. if (data_cleanup_count == 0) {
  6. assert_x_eq(*data, MALLOC_TSD_TEST_DATA_INIT,
  7. "Argument passed into cleanup function should match tsd "
  8. "value");
  9. }
  10. ++data_cleanup_count;
  11. /*
  12. * Allocate during cleanup for two rounds, in order to assure that
  13. * jemalloc's internal tsd reinitialization happens.
  14. */
  15. bool reincarnate = false;
  16. switch (*data) {
  17. case MALLOC_TSD_TEST_DATA_INIT:
  18. *data = 1;
  19. reincarnate = true;
  20. break;
  21. case 1:
  22. *data = 2;
  23. reincarnate = true;
  24. break;
  25. case 2:
  26. return;
  27. default:
  28. not_reached();
  29. }
  30. if (reincarnate) {
  31. void *p = mallocx(1, 0);
  32. assert_ptr_not_null(p, "Unexpeced mallocx() failure");
  33. dallocx(p, 0);
  34. }
  35. }
  36. static void *
  37. thd_start(void *arg) {
  38. int d = (int)(uintptr_t)arg;
  39. void *p;
  40. tsd_t *tsd = tsd_fetch();
  41. assert_x_eq(tsd_test_data_get(tsd), MALLOC_TSD_TEST_DATA_INIT,
  42. "Initial tsd get should return initialization value");
  43. p = malloc(1);
  44. assert_ptr_not_null(p, "Unexpected malloc() failure");
  45. tsd_test_data_set(tsd, d);
  46. assert_x_eq(tsd_test_data_get(tsd), d,
  47. "After tsd set, tsd get should return value that was set");
  48. d = 0;
  49. assert_x_eq(tsd_test_data_get(tsd), (int)(uintptr_t)arg,
  50. "Resetting local data should have no effect on tsd");
  51. tsd_test_callback_set(tsd, &data_cleanup);
  52. free(p);
  53. return NULL;
  54. }
  55. TEST_BEGIN(test_tsd_main_thread) {
  56. thd_start((void *)(uintptr_t)0xa5f3e329);
  57. }
  58. TEST_END
  59. TEST_BEGIN(test_tsd_sub_thread) {
  60. thd_t thd;
  61. data_cleanup_count = 0;
  62. thd_create(&thd, thd_start, (void *)MALLOC_TSD_TEST_DATA_INIT);
  63. thd_join(thd, NULL);
  64. /*
  65. * We reincarnate twice in the data cleanup, so it should execute at
  66. * least 3 times.
  67. */
  68. assert_x_ge(data_cleanup_count, 3,
  69. "Cleanup function should have executed multiple times.");
  70. }
  71. TEST_END
  72. static void *
  73. thd_start_reincarnated(void *arg) {
  74. tsd_t *tsd = tsd_fetch();
  75. assert(tsd);
  76. void *p = malloc(1);
  77. assert_ptr_not_null(p, "Unexpected malloc() failure");
  78. /* Manually trigger reincarnation. */
  79. assert_ptr_not_null(tsd_arena_get(tsd),
  80. "Should have tsd arena set.");
  81. tsd_cleanup((void *)tsd);
  82. assert_ptr_null(*tsd_arenap_get_unsafe(tsd),
  83. "TSD arena should have been cleared.");
  84. assert_u_eq(tsd->state, tsd_state_purgatory,
  85. "TSD state should be purgatory\n");
  86. free(p);
  87. assert_u_eq(tsd->state, tsd_state_reincarnated,
  88. "TSD state should be reincarnated\n");
  89. p = mallocx(1, MALLOCX_TCACHE_NONE);
  90. assert_ptr_not_null(p, "Unexpected malloc() failure");
  91. assert_ptr_null(*tsd_arenap_get_unsafe(tsd),
  92. "Should not have tsd arena set after reincarnation.");
  93. free(p);
  94. tsd_cleanup((void *)tsd);
  95. assert_ptr_null(*tsd_arenap_get_unsafe(tsd),
  96. "TSD arena should have been cleared after 2nd cleanup.");
  97. return NULL;
  98. }
  99. TEST_BEGIN(test_tsd_reincarnation) {
  100. thd_t thd;
  101. thd_create(&thd, thd_start_reincarnated, NULL);
  102. thd_join(thd, NULL);
  103. }
  104. TEST_END
  105. int
  106. main(void) {
  107. /* Ensure tsd bootstrapped. */
  108. if (nallocx(1, 0) == 0) {
  109. malloc_printf("Initialization error");
  110. return test_status_fail;
  111. }
  112. return test_no_reentrancy(
  113. test_tsd_main_thread,
  114. test_tsd_sub_thread,
  115. test_tsd_reincarnation);
  116. }