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