2017-10-30 08:03:56 +00:00
|
|
|
/*
|
|
|
|
* Test FreeRTOS debug functions and utilities.
|
|
|
|
* - Queue registry functions vQueueAddToRegistry(), vQueueUnregisterQueue(),
|
|
|
|
* and pcQueueGetName(backported)
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "freertos/FreeRTOS.h"
|
|
|
|
#include "freertos/task.h"
|
|
|
|
#include "freertos/semphr.h"
|
|
|
|
#include "freertos/queue.h"
|
|
|
|
#include "unity.h"
|
2018-10-25 04:52:32 +00:00
|
|
|
#include "test_utils.h"
|
2017-10-30 08:03:56 +00:00
|
|
|
|
|
|
|
#if (CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE > 0)
|
|
|
|
#define NO_OF_QUEUES_PER_CORE ((int)((CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE - 3)/portNUM_PROCESSORS)) //Save space for some preallocated tasks
|
|
|
|
#define NO_OF_QUEUES_TOTAL (NO_OF_QUEUES_PER_CORE * portNUM_PROCESSORS)
|
2018-06-14 16:11:21 +00:00
|
|
|
#define QUEUE_NAME_MAX_LENGTH 30
|
2017-10-30 08:03:56 +00:00
|
|
|
|
unit tests: fix queue registry test
In the queue registry test, start_sem is given twice to let both tasks
start the test. Each task takes start_sem, does some work, gives done_sem,
and goes on to wait for start_sem again.
It may happen that one task can grab start_sem, add queues to the
registry, give done_sem, then grab start_sem again, delete the queues
from the registry, and give done_sem again. At this point, main test
task takes done_sem twice and proceeds to verify that queues have been
added to the registry. But in fact, the first task has already deleted
its queues from the registry, and the second one might not have added
the queues yet. This causes test to fail.
This changes the test to use separate start semaphores for each task,
to avoid the race condition.
2017-11-14 12:35:16 +00:00
|
|
|
static SemaphoreHandle_t start_sem[portNUM_PROCESSORS];
|
2017-10-30 08:03:56 +00:00
|
|
|
static SemaphoreHandle_t done_sem = NULL;
|
|
|
|
static char *names[NO_OF_QUEUES_TOTAL];
|
|
|
|
static QueueHandle_t handles[NO_OF_QUEUES_TOTAL];
|
|
|
|
|
|
|
|
void test_queue_registry_task(void *arg)
|
|
|
|
{
|
|
|
|
int core = xPortGetCoreID();
|
|
|
|
int offset = core * NO_OF_QUEUES_PER_CORE;
|
|
|
|
//Create queues and accompanying queue names
|
|
|
|
for(int i = 0; i < NO_OF_QUEUES_PER_CORE; i++){
|
|
|
|
handles[i + offset] = xQueueCreate(1,1); //Create queues
|
|
|
|
names[i + offset] = calloc(QUEUE_NAME_MAX_LENGTH, sizeof(char));
|
|
|
|
sprintf(names[i + offset], "Queue%d%d", core, i);
|
|
|
|
}
|
|
|
|
|
unit tests: fix queue registry test
In the queue registry test, start_sem is given twice to let both tasks
start the test. Each task takes start_sem, does some work, gives done_sem,
and goes on to wait for start_sem again.
It may happen that one task can grab start_sem, add queues to the
registry, give done_sem, then grab start_sem again, delete the queues
from the registry, and give done_sem again. At this point, main test
task takes done_sem twice and proceeds to verify that queues have been
added to the registry. But in fact, the first task has already deleted
its queues from the registry, and the second one might not have added
the queues yet. This causes test to fail.
This changes the test to use separate start semaphores for each task,
to avoid the race condition.
2017-11-14 12:35:16 +00:00
|
|
|
xSemaphoreTake(start_sem[core], portMAX_DELAY); //Wait for start vQueueAddToRegistry()
|
2017-10-30 08:03:56 +00:00
|
|
|
for(int i = 0; i < NO_OF_QUEUES_PER_CORE; i++){
|
|
|
|
vQueueAddToRegistry(handles[i + offset] , names[i + offset]); //Register queues to queue registry
|
|
|
|
}
|
|
|
|
xSemaphoreGive(done_sem); //Signal that vQueueAddToRegistry() has completed
|
|
|
|
|
|
|
|
vTaskDelay(1);
|
|
|
|
|
unit tests: fix queue registry test
In the queue registry test, start_sem is given twice to let both tasks
start the test. Each task takes start_sem, does some work, gives done_sem,
and goes on to wait for start_sem again.
It may happen that one task can grab start_sem, add queues to the
registry, give done_sem, then grab start_sem again, delete the queues
from the registry, and give done_sem again. At this point, main test
task takes done_sem twice and proceeds to verify that queues have been
added to the registry. But in fact, the first task has already deleted
its queues from the registry, and the second one might not have added
the queues yet. This causes test to fail.
This changes the test to use separate start semaphores for each task,
to avoid the race condition.
2017-11-14 12:35:16 +00:00
|
|
|
xSemaphoreTake(start_sem[core], portMAX_DELAY); //Wait to start vQueueUnregisterQueue()
|
2017-10-30 08:03:56 +00:00
|
|
|
for(int i = 0; i < NO_OF_QUEUES_PER_CORE; i++){
|
|
|
|
vQueueDelete(handles[i + offset]); //Internally calls vQueueUnregisterQueue
|
|
|
|
}
|
|
|
|
xSemaphoreGive(done_sem); //Signal done
|
|
|
|
|
|
|
|
vTaskDelete(NULL); //Delete self
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_CASE("Test FreeRTOS Queue Registry", "[freertos]")
|
|
|
|
{
|
unit tests: fix queue registry test
In the queue registry test, start_sem is given twice to let both tasks
start the test. Each task takes start_sem, does some work, gives done_sem,
and goes on to wait for start_sem again.
It may happen that one task can grab start_sem, add queues to the
registry, give done_sem, then grab start_sem again, delete the queues
from the registry, and give done_sem again. At this point, main test
task takes done_sem twice and proceeds to verify that queues have been
added to the registry. But in fact, the first task has already deleted
its queues from the registry, and the second one might not have added
the queues yet. This causes test to fail.
This changes the test to use separate start semaphores for each task,
to avoid the race condition.
2017-11-14 12:35:16 +00:00
|
|
|
//Create synchronization semaphores and tasks to test queue registry
|
2017-10-30 08:03:56 +00:00
|
|
|
done_sem = xSemaphoreCreateCounting(portNUM_PROCESSORS, 0);
|
unit tests: fix queue registry test
In the queue registry test, start_sem is given twice to let both tasks
start the test. Each task takes start_sem, does some work, gives done_sem,
and goes on to wait for start_sem again.
It may happen that one task can grab start_sem, add queues to the
registry, give done_sem, then grab start_sem again, delete the queues
from the registry, and give done_sem again. At this point, main test
task takes done_sem twice and proceeds to verify that queues have been
added to the registry. But in fact, the first task has already deleted
its queues from the registry, and the second one might not have added
the queues yet. This causes test to fail.
This changes the test to use separate start semaphores for each task,
to avoid the race condition.
2017-11-14 12:35:16 +00:00
|
|
|
for(int i = 0; i < portNUM_PROCESSORS; i++){
|
|
|
|
start_sem[i] = xSemaphoreCreateBinary();
|
2017-10-30 08:03:56 +00:00
|
|
|
xTaskCreatePinnedToCore(test_queue_registry_task, "testing task", 4096, NULL, UNITY_FREERTOS_PRIORITY+1, NULL, i);
|
|
|
|
}
|
|
|
|
|
|
|
|
portDISABLE_INTERRUPTS();
|
|
|
|
for(int i = 0; i < portNUM_PROCESSORS; i++){
|
unit tests: fix queue registry test
In the queue registry test, start_sem is given twice to let both tasks
start the test. Each task takes start_sem, does some work, gives done_sem,
and goes on to wait for start_sem again.
It may happen that one task can grab start_sem, add queues to the
registry, give done_sem, then grab start_sem again, delete the queues
from the registry, and give done_sem again. At this point, main test
task takes done_sem twice and proceeds to verify that queues have been
added to the registry. But in fact, the first task has already deleted
its queues from the registry, and the second one might not have added
the queues yet. This causes test to fail.
This changes the test to use separate start semaphores for each task,
to avoid the race condition.
2017-11-14 12:35:16 +00:00
|
|
|
xSemaphoreGive(start_sem[i]); //Trigger start
|
2017-10-30 08:03:56 +00:00
|
|
|
}
|
|
|
|
portENABLE_INTERRUPTS();
|
|
|
|
for(int i = 0; i < portNUM_PROCESSORS; i++){
|
|
|
|
xSemaphoreTake(done_sem, portMAX_DELAY); //Wait for tasks to complete vQueueAddToRegistry
|
|
|
|
}
|
|
|
|
for(int i = 0; i < NO_OF_QUEUES_TOTAL; i++){
|
|
|
|
const char *addr = pcQueueGetName(handles[i]);
|
|
|
|
TEST_ASSERT(addr == names[i]) //Check vQueueAddToRegistry was successful
|
|
|
|
}
|
|
|
|
|
|
|
|
portDISABLE_INTERRUPTS();
|
|
|
|
for(int i = 0; i < portNUM_PROCESSORS; i++){
|
unit tests: fix queue registry test
In the queue registry test, start_sem is given twice to let both tasks
start the test. Each task takes start_sem, does some work, gives done_sem,
and goes on to wait for start_sem again.
It may happen that one task can grab start_sem, add queues to the
registry, give done_sem, then grab start_sem again, delete the queues
from the registry, and give done_sem again. At this point, main test
task takes done_sem twice and proceeds to verify that queues have been
added to the registry. But in fact, the first task has already deleted
its queues from the registry, and the second one might not have added
the queues yet. This causes test to fail.
This changes the test to use separate start semaphores for each task,
to avoid the race condition.
2017-11-14 12:35:16 +00:00
|
|
|
xSemaphoreGive(start_sem[i]); //Trigger start
|
2017-10-30 08:03:56 +00:00
|
|
|
}
|
|
|
|
portENABLE_INTERRUPTS();
|
|
|
|
for(int i = 0; i < portNUM_PROCESSORS; i++){
|
|
|
|
xSemaphoreTake(done_sem, portMAX_DELAY); //Wait for tasks to complete vQueueUnregisterQueue
|
|
|
|
}
|
|
|
|
for(int i = 0; i < NO_OF_QUEUES_TOTAL; i++){
|
|
|
|
const char *addr = pcQueueGetName(handles[i]);
|
|
|
|
TEST_ASSERT(addr == NULL) //Check vQueueUnregisterQueue was successful
|
|
|
|
handles[i] = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Cleanup
|
|
|
|
for(int i = 0; i < NO_OF_QUEUES_TOTAL; i++){
|
|
|
|
free(names[i]);
|
|
|
|
names[i] = NULL;
|
|
|
|
}
|
unit tests: fix queue registry test
In the queue registry test, start_sem is given twice to let both tasks
start the test. Each task takes start_sem, does some work, gives done_sem,
and goes on to wait for start_sem again.
It may happen that one task can grab start_sem, add queues to the
registry, give done_sem, then grab start_sem again, delete the queues
from the registry, and give done_sem again. At this point, main test
task takes done_sem twice and proceeds to verify that queues have been
added to the registry. But in fact, the first task has already deleted
its queues from the registry, and the second one might not have added
the queues yet. This causes test to fail.
This changes the test to use separate start semaphores for each task,
to avoid the race condition.
2017-11-14 12:35:16 +00:00
|
|
|
for(int i = 0; i < portNUM_PROCESSORS; i++){
|
|
|
|
vSemaphoreDelete(start_sem[i]);
|
|
|
|
start_sem[i] = NULL;
|
|
|
|
}
|
2017-10-30 08:03:56 +00:00
|
|
|
vSemaphoreDelete(done_sem);
|
|
|
|
done_sem = NULL;
|
|
|
|
}
|
|
|
|
#endif //(CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE > 0)
|