Files
lab-rv32i-freertos-semaphor…/tests/synchronization_host.cpp
T

136 lines
4.5 KiB
C++

#include <cassert>
#include <type_traits>
#include "freertos/synchronization.hpp"
namespace
{
unsigned target_token;
uint32_t notification_value;
bool notification_pending;
unsigned deletes;
TickType_t last_timeout;
eNotifyAction last_action;
} // namespace
extern "C" SemaphoreHandle_t xSemaphoreCreateBinaryStatic(
StaticSemaphore_t * storage )
{
*storage = MockSemaphore { 0U, 1U };
return storage;
}
extern "C" SemaphoreHandle_t xSemaphoreCreateCountingStatic(
UBaseType_t maximum, UBaseType_t initial, StaticSemaphore_t * storage )
{
if( initial > maximum ) return nullptr;
*storage = MockSemaphore { initial, maximum };
return storage;
}
extern "C" BaseType_t xSemaphoreTake( SemaphoreHandle_t semaphore,
TickType_t timeout )
{
last_timeout = timeout;
if( semaphore->count == 0U ) return pdFAIL;
--semaphore->count;
return pdPASS;
}
extern "C" BaseType_t xSemaphoreGive( SemaphoreHandle_t semaphore )
{
if( semaphore->count == semaphore->maximum ) return pdFAIL;
++semaphore->count;
return pdPASS;
}
extern "C" UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t semaphore )
{
return semaphore->count;
}
extern "C" void vSemaphoreDelete( SemaphoreHandle_t )
{
++deletes;
}
extern "C" BaseType_t xTaskNotifyGive( TaskHandle_t target )
{
if( target != &target_token ) return pdFAIL;
++notification_value;
notification_pending = true;
return pdPASS;
}
extern "C" BaseType_t xTaskNotify( TaskHandle_t target, uint32_t value,
eNotifyAction action )
{
if( target != &target_token ) return pdFAIL;
last_action = action;
if( action == eSetBits ) notification_value |= value;
else if( action == eIncrement ) ++notification_value;
else if( action == eSetValueWithOverwrite ) notification_value = value;
else if( action == eSetValueWithoutOverwrite )
{
if( notification_pending ) return pdFAIL;
notification_value = value;
}
notification_pending = true;
return pdPASS;
}
extern "C" uint32_t ulTaskNotifyTake( BaseType_t clear, TickType_t timeout )
{
last_timeout = timeout;
const uint32_t result = notification_value;
if( result == 0U ) return 0U;
if( clear != pdFALSE ) notification_value = 0U;
else --notification_value;
notification_pending = false;
return result;
}
extern "C" BaseType_t xTaskNotifyWait( uint32_t clear_entry,
uint32_t clear_exit,
uint32_t * value,
TickType_t timeout )
{
last_timeout = timeout;
notification_value &= ~clear_entry;
if( !notification_pending ) return pdFAIL;
*value = notification_value;
notification_value &= ~clear_exit;
notification_pending = false;
return pdPASS;
}
static_assert( !std::is_copy_constructible< freertos::BinarySemaphore >::value );
static_assert( !std::is_move_constructible<
freertos::CountingSemaphore< 2U > >::value );
static_assert( std::is_trivially_copyable<
freertos::TaskNotification >::value );
int main()
{
freertos::StaticSemaphoreStorage binary_storage {};
freertos::StaticSemaphoreStorage counting_storage {};
{
freertos::BinarySemaphore binary { binary_storage };
assert( binary.valid() && binary.count() == 0U );
assert( binary.give() && binary.count() == 1U );
assert( !binary.give() );
assert( binary.take( 7U ) && last_timeout == 7U );
assert( binary.count() == 0U );
freertos::CountingSemaphore< 2U > counting { counting_storage, 2U };
assert( counting.valid() && counting.maximum() == 2U );
assert( !counting.give() );
assert( counting.take( 0U ) && counting.count() == 1U );
assert( counting.take( 0U ) && counting.count() == 0U );
assert( !counting.take( 4U ) && last_timeout == 4U );
assert( counting.give() && counting.count() == 1U );
freertos::TaskNotification notification { &target_token };
assert( notification.valid() && notification.give() );
assert( freertos::TaskNotification::take( true, 3U ) == 1U );
assert( notification.notify(
0xA5A55A5AU, freertos::NotificationAction::overwrite ) );
assert( last_action == eSetValueWithOverwrite );
uint32_t value = 0U;
assert( freertos::TaskNotification::wait_value( value, 5U ) );
assert( value == 0xA5A55A5AU && last_timeout == 5U );
}
assert( deletes == 2U );
}