test_thread_local.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /*
  7. Test for thread local storage support.
  8. */
  9. #include <string.h>
  10. #include <stdlib.h>
  11. #include <esp_types.h>
  12. #include "freertos/FreeRTOS.h"
  13. #include "freertos/task.h"
  14. #include "unity.h"
  15. #include "test_utils.h"
  16. #include "sdkconfig.h"
  17. #if defined(__XTENSA__)
  18. #define GET_THREADPTR(tp_dest) do { asm volatile ("rur.threadptr %0":"=r"(tp_dest)); } while(0)
  19. #elif defined (__riscv)
  20. #define GET_THREADPTR(tp_dest) do { register uint32_t _tp asm("tp"); tp_dest = _tp; } while(0)
  21. #endif
  22. static __thread int tl_test_var1;
  23. static __thread uint8_t tl_test_var2 = 55;
  24. static __thread uint16_t tl_test_var3 = 44;
  25. static __thread uint8_t tl_test_arr_var[10];
  26. static __thread struct test_tls_var {
  27. int f32;
  28. uint8_t f8;
  29. uint16_t f16;
  30. uint8_t farr[10];
  31. } tl_test_struct_var;
  32. static void task_test_tls(void *arg)
  33. {
  34. bool *running = (bool *)arg;
  35. uint32_t tp = (uint32_t) -1;
  36. int test_var1_old = 0;
  37. uint8_t test_var2_old = 0;
  38. uint16_t test_var3_old = 0;
  39. int f32_old = 0;
  40. uint8_t f8_old = 0;
  41. uint16_t f16_old = 0;
  42. srand((int) xTaskGetCurrentTaskHandle());
  43. int step = (rand() % 10) + 1;
  44. GET_THREADPTR(tp);
  45. for (int i = 0; i < 5; i++) {
  46. printf("Task[%x]: var = 0x%x 0x%x step=%d\n", tp, tl_test_var1, tl_test_var2, step);
  47. if (i == 0) {
  48. TEST_ASSERT_EQUAL(0, tl_test_var1);
  49. TEST_ASSERT_EQUAL(55, tl_test_var2);
  50. TEST_ASSERT_EQUAL(44, tl_test_var3);
  51. for (int k = 0; k < sizeof(tl_test_arr_var); k++) {
  52. TEST_ASSERT_EQUAL(0, tl_test_arr_var[k]);
  53. }
  54. TEST_ASSERT_EQUAL(0, tl_test_struct_var.f32);
  55. TEST_ASSERT_EQUAL(0, tl_test_struct_var.f8);
  56. TEST_ASSERT_EQUAL(0, tl_test_struct_var.f16);
  57. for (int k = 0; k < sizeof(tl_test_struct_var.farr); k++) {
  58. TEST_ASSERT_EQUAL(0, tl_test_struct_var.farr[k]);
  59. }
  60. } else {
  61. TEST_ASSERT_EQUAL(test_var1_old + step, tl_test_var1);
  62. TEST_ASSERT_EQUAL(test_var2_old + step, tl_test_var2);
  63. TEST_ASSERT_EQUAL(test_var3_old + step, tl_test_var3);
  64. for (int k = 0; k < sizeof(tl_test_arr_var); k++) {
  65. TEST_ASSERT_EQUAL((i - 1) * step, tl_test_arr_var[k]);
  66. }
  67. TEST_ASSERT_EQUAL(f32_old + step, tl_test_struct_var.f32);
  68. TEST_ASSERT_EQUAL(f8_old + step, tl_test_struct_var.f8);
  69. TEST_ASSERT_EQUAL(f16_old + step, tl_test_struct_var.f16);
  70. for (int k = 0; k < sizeof(tl_test_struct_var.farr); k++) {
  71. TEST_ASSERT_EQUAL((i - 1) * step, tl_test_struct_var.farr[k]);
  72. }
  73. }
  74. test_var1_old = tl_test_var1;
  75. test_var2_old = tl_test_var2;
  76. test_var3_old = tl_test_var3;
  77. f32_old = tl_test_struct_var.f32;
  78. f8_old = tl_test_struct_var.f8;
  79. f16_old = tl_test_struct_var.f16;
  80. tl_test_var1 += step;
  81. tl_test_var2 += step;
  82. tl_test_var3 += step;
  83. memset(tl_test_arr_var, i * step, sizeof(tl_test_arr_var));
  84. tl_test_struct_var.f32 += step;
  85. tl_test_struct_var.f8 += step;
  86. tl_test_struct_var.f16 += step;
  87. memset(tl_test_struct_var.farr, i * step, sizeof(tl_test_struct_var.farr));
  88. vTaskDelay(10);
  89. }
  90. if (running) {
  91. *running = false;
  92. vTaskDelete(NULL);
  93. }
  94. }
  95. TEST_CASE("TLS test", "[freertos]")
  96. {
  97. const size_t stack_size = 3072;
  98. StackType_t s_stack[stack_size]; /* with 8KB test task stack (default) this test still has ~3KB headroom */
  99. StaticTask_t s_task;
  100. bool running[2] = {true, true};
  101. #if CONFIG_FREERTOS_UNICORE == 0
  102. int other_core = 1;
  103. #else
  104. int other_core = 0;
  105. #endif
  106. xTaskCreatePinnedToCore((TaskFunction_t)&task_test_tls, "task_test_tls", stack_size, &running[0],
  107. UNITY_FREERTOS_PRIORITY, NULL, 0);
  108. xTaskCreateStaticPinnedToCore((TaskFunction_t)&task_test_tls, "task_test_tls", stack_size, &running[1],
  109. UNITY_FREERTOS_PRIORITY, s_stack, &s_task, other_core);
  110. while (running[0] || running[1]) {
  111. vTaskDelay(10);
  112. }
  113. vTaskDelay(10); /* Make sure idle task can clean up s_task, before it goes out of scope */
  114. }