1 #include <stdio.h>
2 #include <stdbool.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <sys/lock.h>
6 #include "unity.h"
7 #include "test_utils.h"
8 #include "sdkconfig.h"
9 #include "freertos/FreeRTOS.h"
10 #include "freertos/semphr.h"
11 
12 #if defined(_RETARGETABLE_LOCKING)
13 
locking_task(void * arg)14 static void locking_task(void* arg)
15 {
16     _LOCK_T lock = (_LOCK_T) arg;
17     __lock_acquire(lock);
18     __lock_release(lock);
19     vTaskSuspend(NULL);
20 }
21 
recursive_locking_task(void * arg)22 static void recursive_locking_task(void* arg)
23 {
24     _LOCK_T lock = (_LOCK_T) arg;
25     __lock_acquire_recursive(lock);
26     __lock_release_recursive(lock);
27     vTaskSuspend(NULL);
28 }
29 
test_inner_normal(_LOCK_T lock)30 static void test_inner_normal(_LOCK_T lock)
31 {
32     /* Acquire the lock */
33     __lock_acquire(lock);
34 
35     /* Create another task to try acquire same lock */
36     TaskHandle_t task_hdl;
37     TEST_ASSERT(xTaskCreate(&locking_task, "locking_task", 2048, lock, UNITY_FREERTOS_PRIORITY, &task_hdl));
38     vTaskDelay(2);
39     /* It should get blocked */
40     TEST_ASSERT_EQUAL(eBlocked, eTaskGetState(task_hdl));
41 
42     /* Once we release the lock, the task should succeed and suspend itself */
43     __lock_release(lock);
44     vTaskDelay(2);
45     TEST_ASSERT_EQUAL(eSuspended, eTaskGetState(task_hdl));
46     vTaskDelete(task_hdl);
47 
48     /* Can not recursively acquire the lock from same task */
49     TEST_ASSERT_EQUAL(0, __lock_try_acquire(lock));
50     TEST_ASSERT_EQUAL(-1, __lock_try_acquire(lock));
51     __lock_release(lock);
52 }
53 
test_inner_recursive(_LOCK_T lock)54 static void test_inner_recursive(_LOCK_T lock)
55 {
56     /* Acquire the lock */
57     __lock_acquire_recursive(lock);
58 
59     /* Create another task to try acquire same lock */
60     TaskHandle_t task_hdl;
61     TEST_ASSERT(xTaskCreate(&recursive_locking_task, "locking_task", 2048, lock, UNITY_FREERTOS_PRIORITY, &task_hdl));
62     vTaskDelay(2);
63     /* It should get blocked */
64     TEST_ASSERT_EQUAL(eBlocked, eTaskGetState(task_hdl));
65 
66     /* Once we release the lock, the task should succeed and suspend itself */
67     __lock_release_recursive(lock);
68     vTaskDelay(2);
69     TEST_ASSERT_EQUAL(eSuspended, eTaskGetState(task_hdl));
70     vTaskDelete(task_hdl);
71 
72     /* Try recursively acquiring the lock */
73     TEST_ASSERT_EQUAL(0, __lock_try_acquire_recursive(lock));
74     TEST_ASSERT_EQUAL(0, __lock_try_acquire_recursive(lock));
75     __lock_release_recursive(lock);
76     __lock_release_recursive(lock);
77 }
78 
79 TEST_CASE("Retargetable static locks", "[newlib_locks]")
80 {
81     StaticSemaphore_t semaphore;
82     _LOCK_T lock = (_LOCK_T) xSemaphoreCreateMutexStatic(&semaphore);
83     test_inner_normal(lock);
84 }
85 
86 TEST_CASE("Retargetable static recursive locks", "[newlib_locks]")
87 {
88     StaticSemaphore_t semaphore;
89     _LOCK_T lock = (_LOCK_T) xSemaphoreCreateRecursiveMutexStatic(&semaphore);
90     test_inner_recursive(lock);
91 }
92 
93 TEST_CASE("Retargetable dynamic locks", "[newlib_locks]")
94 {
95     _LOCK_T lock;
96     __lock_init(lock);
97     test_inner_normal(lock);
98     __lock_close(lock);
99 }
100 
101 TEST_CASE("Retargetable dynamic recursive locks", "[newlib_locks]")
102 {
103     _LOCK_T lock;
104     __lock_init_recursive(lock);
105     test_inner_recursive(lock);
106     __lock_close_recursive(lock);
107 }
108 
109 #endif // _RETARGETABLE_LOCKING
110