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