Skip to content

Commit 78c33d3

Browse files
recursive mutex implemented, some refactoring.
1 parent 6cd2631 commit 78c33d3

File tree

5 files changed

+139
-12
lines changed

5 files changed

+139
-12
lines changed

cpputest-for-freertos-lib/src/cpputest_for_freertos_fake_queue.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ typedef struct QueueDefinition
1212
UBaseType_t itemSize = {};
1313
uint8_t queueType = {};
1414
std::deque<std::vector<uint8_t>> queue = {};
15+
uint64_t recursiveCallCount = {};
1516
} FakeQueue;
1617

18+
namespace cms {
19+
BaseType_t InternalQueueReceive(FakeQueue *queue, void * const buffer);
20+
BaseType_t InternalQueueReceive(FakeQueue *queue);
21+
} //namespace cms
22+
1723
#endif //CPPUTEST_FOR_FREERTOS_LIB_CPPUTEST_FOR_FREERTOS_FAKE_QUEUE_HPP

cpputest-for-freertos-lib/src/cpputest_for_freertos_mutex.cpp

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,27 +84,69 @@ namespace cms {
8484
} //namespace
8585
}//namespace
8686

87-
extern "C" QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )
87+
extern "C" QueueHandle_t xQueueCreateMutex(const uint8_t queueType)
8888
{
89-
(void)ucQueueType;
90-
auto mutex = xQueueGenericCreate(1, 0, ucQueueType);
91-
switch (ucQueueType) {
89+
(void)queueType;
90+
auto mutex = xQueueGenericCreate(1, 0, queueType);
91+
switch (queueType) {
9292
case queueQUEUE_TYPE_MUTEX:
9393
//wasn't documented, but in experiment, the standard mutex is created unlocked
9494
//(i.e) with one token available
9595
xSemaphoreGive(mutex);
9696
break;
9797
case queueQUEUE_TYPE_RECURSIVE_MUTEX:
98-
//todo
98+
xSemaphoreGive(mutex);
99+
mutex->recursiveCallCount = 0;
99100
break;
100101
default:
101102
configASSERT(true == false);
102-
break;
103103
}
104104
configASSERT(mutex != nullptr);
105105
if (cms::test::s_mutexes != nullptr)
106106
{
107107
cms::test::s_mutexes->push_back(mutex);
108108
}
109109
return mutex;
110-
}
110+
}
111+
112+
extern "C" BaseType_t xQueueTakeMutexRecursive(QueueHandle_t mutex,
113+
TickType_t ticks)
114+
{
115+
(void) ticks; //not used
116+
117+
configASSERT(mutex != nullptr);
118+
configASSERT(mutex->queueType == queueQUEUE_TYPE_RECURSIVE_MUTEX);
119+
120+
if (1 == uxSemaphoreGetCount(mutex))
121+
{
122+
auto rtn = cms::InternalQueueReceive(mutex);
123+
if (rtn != pdTRUE)
124+
{
125+
return rtn;
126+
}
127+
}
128+
129+
mutex->recursiveCallCount++;
130+
return pdTRUE;
131+
132+
}
133+
134+
extern "C" BaseType_t xQueueGiveMutexRecursive(QueueHandle_t mutex)
135+
{
136+
configASSERT(mutex != nullptr);
137+
configASSERT(mutex->queueType == queueQUEUE_TYPE_RECURSIVE_MUTEX);
138+
139+
if (0 == uxSemaphoreGetCount(mutex) && mutex->recursiveCallCount > 0)
140+
{
141+
mutex->recursiveCallCount--;
142+
if (mutex->recursiveCallCount == 0)
143+
{
144+
return xSemaphoreGive(mutex);
145+
}
146+
147+
return pdTRUE;
148+
}
149+
150+
return pdFALSE;
151+
}
152+

cpputest-for-freertos-lib/src/cpputest_for_freertos_queue.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,17 @@ extern "C" UBaseType_t uxQueueSpacesAvailable(const QueueHandle_t queue)
6767
return queue->queueLength - uxQueueMessagesWaiting(queue);
6868
}
6969

70-
extern "C" BaseType_t xQueueReceive(QueueHandle_t queue, void * const buffer, TickType_t ticks)
70+
BaseType_t cms::InternalQueueReceive(FakeQueue * queue)
71+
{
72+
configASSERT(queue != nullptr);
73+
74+
uint64_t dummy;
75+
return cms::InternalQueueReceive(queue, &dummy);
76+
}
77+
78+
BaseType_t cms::InternalQueueReceive(FakeQueue * queue, void * const buffer)
7179
{
7280
configASSERT(queue != nullptr);
73-
(void)ticks; //in our unit testing fake, never honor ticks to wait.
7481

7582
if (!queue->queue.empty())
7683
{
@@ -85,10 +92,19 @@ extern "C" BaseType_t xQueueReceive(QueueHandle_t queue, void * const buffer, Ti
8592
}
8693
}
8794

95+
extern "C" BaseType_t xQueueReceive(QueueHandle_t queue, void * const buffer, TickType_t ticks)
96+
{
97+
configASSERT(queue != nullptr);
98+
configASSERT(buffer != nullptr);
99+
100+
(void)ticks; //in our unit testing fake, never honor ticks to wait.
101+
return cms::InternalQueueReceive(queue, buffer);
102+
}
103+
88104
extern "C" BaseType_t xQueueGenericSend(QueueHandle_t queue,
89105
const void * const itemToQueue,
90106
TickType_t ticks,
91-
const BaseType_t copyPosition )
107+
const BaseType_t copyPosition)
92108
{
93109
(void)ticks;
94110
configASSERT(queue != nullptr);

cpputest-for-freertos-lib/src/cpputest_for_freertos_semaphore.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,19 @@
3333
extern "C" BaseType_t xQueueSemaphoreTake(QueueHandle_t queue, TickType_t ticks)
3434
{
3535
(void) ticks; //ignore in cpputest fake semaphore
36+
configASSERT(queue != nullptr);
37+
configASSERT(queue->queueType != queueQUEUE_TYPE_RECURSIVE_MUTEX);
3638

37-
uint64_t dummy;
38-
return xQueueReceive(queue, &dummy, ticks);
39+
return cms::InternalQueueReceive(queue);
3940
}
4041

4142

4243
extern "C" BaseType_t xQueueGiveFromISR(QueueHandle_t queue,
4344
BaseType_t * const pxHigherPriorityTaskWoken)
4445
{
46+
configASSERT(queue != nullptr);
47+
configASSERT(queue->queueType != queueQUEUE_TYPE_RECURSIVE_MUTEX);
48+
4549
(void)pxHigherPriorityTaskWoken;
4650
return xSemaphoreGive(queue);
4751
}

cpputest-for-freertos-lib/tests/cpputest_for_freertos_mutex_tests.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ TEST_GROUP(MutexTests)
4747
void CreateMutex()
4848
{
4949
mMutexUnderTest = xSemaphoreCreateMutex();
50+
CHECK_TRUE(nullptr != mMutexUnderTest);
51+
}
52+
53+
void CreateRecursiveMutex()
54+
{
55+
mMutexUnderTest = xSemaphoreCreateRecursiveMutex();
56+
CHECK_TRUE(nullptr != mMutexUnderTest);
5057
}
5158
};
5259

@@ -87,6 +94,58 @@ TEST(MutexTests, library_does_not_detect_locked_mutex_that_was_deleted)
8794
xSemaphoreTake(mMutexUnderTest, 1000);
8895
CHECK_TRUE(cms::test::IsAnyMutexLocked());
8996

97+
vSemaphoreDelete(mMutexUnderTest);
98+
mMutexUnderTest = nullptr;
99+
CHECK_FALSE(cms::test::IsAnyMutexLocked());
100+
cms::test::MutexTrackingTeardown();
101+
}
102+
103+
TEST(MutexTests, can_create_a_recursive_mutex)
104+
{
105+
CreateRecursiveMutex();
106+
CHECK_EQUAL(1, uxSemaphoreGetCount(mMutexUnderTest));
107+
}
108+
109+
TEST(MutexTests, can_lock_a_recursive_mutex_multiple_times)
110+
{
111+
CreateRecursiveMutex();
112+
CHECK_EQUAL(1, uxSemaphoreGetCount(mMutexUnderTest));
113+
CHECK_EQUAL(pdTRUE, xSemaphoreTakeRecursive(mMutexUnderTest, 1000));
114+
CHECK_EQUAL(pdTRUE, xSemaphoreTakeRecursive(mMutexUnderTest, 1000));
115+
CHECK_EQUAL(pdTRUE, xSemaphoreTakeRecursive(mMutexUnderTest, 1000));
116+
CHECK_EQUAL(0, uxSemaphoreGetCount(mMutexUnderTest));
117+
118+
//now confirm give recursive while here
119+
CHECK_EQUAL(pdTRUE, xSemaphoreGiveRecursive(mMutexUnderTest));
120+
CHECK_EQUAL(0, uxSemaphoreGetCount(mMutexUnderTest));
121+
CHECK_EQUAL(pdTRUE, xSemaphoreGiveRecursive(mMutexUnderTest));
122+
CHECK_EQUAL(0, uxSemaphoreGetCount(mMutexUnderTest));
123+
CHECK_EQUAL(pdTRUE, xSemaphoreGiveRecursive(mMutexUnderTest));
124+
CHECK_EQUAL(1, uxSemaphoreGetCount(mMutexUnderTest));
125+
}
126+
127+
TEST(MutexTests, library_can_detect_locked_recursive_mutexes)
128+
{
129+
CHECK_FALSE(cms::test::IsAnyMutexLocked());
130+
cms::test::MutexTrackingInit();
131+
CreateRecursiveMutex();
132+
CHECK_FALSE(cms::test::IsAnyMutexLocked());
133+
134+
xSemaphoreTakeRecursive(mMutexUnderTest, 1000);
135+
CHECK_TRUE(cms::test::IsAnyMutexLocked());
136+
137+
xSemaphoreGiveRecursive(mMutexUnderTest);
138+
CHECK_FALSE(cms::test::IsAnyMutexLocked());
139+
cms::test::MutexTrackingTeardown();
140+
}
141+
142+
TEST(MutexTests, library_does_not_detect_locked_recursive_mutex_that_was_deleted)
143+
{
144+
cms::test::MutexTrackingInit();
145+
CreateRecursiveMutex();
146+
xSemaphoreTakeRecursive(mMutexUnderTest, 1000);
147+
CHECK_TRUE(cms::test::IsAnyMutexLocked());
148+
90149
vSemaphoreDelete(mMutexUnderTest);
91150
mMutexUnderTest = nullptr;
92151
CHECK_FALSE(cms::test::IsAnyMutexLocked());

0 commit comments

Comments
 (0)