While working on an implementation of FreeRTOS with LwIP on a TI TM4C129ENCPDT processor, I've come across the sys_sem_new() and sys_sem_free() functions that are implemented by TI in the sys_arch.c file used in LwIP as part of TivaWare. These two functions are basically used for creating and destroying semaphores, but there seems to be a bug in the implementation so that semaphores are not actually cleared when calling sys_sem_free().
Consider the following code copied and pasted from TI's implementation of sys_arch.c <TivaWare>\third_party\lwip-1.4.1\ports\tiva-tm4c129\sys_arch.c
/* An array to hold the memory for the available semaphores. */
static sem_t sems[SYS_SEM_MAX];
/**
* Initializes the system architecture layer.
*
*/
void
sys_init(void)
{
u32_t i;
/* Clear out the semaphores. */
for(i = 0; i < SYS_SEM_MAX; i++) {
sems[i].queue = 0;
}
}
/**
* Creates a new semaphore.
*
* @param count is non-zero if the semaphore should be acquired initially.
* @return the handle of the created semaphore.
*/
err_t
sys_sem_new(sys_sem_t *sem, u8_t count)
{
void *temp;
u32_t i;
/* Find a semaphore that is not in use. */
for(i = 0; i < SYS_SEM_MAX; i++) {
if(*(*int)sems[i].queue == 0) {
break;
}
}
if(i == SYS_SEM_MAX) {
#if SYS_STATS
STATS_INC(sys.sem.err);
#endif /* SYS_STATS */
return ERR_MEM;
}
/* Create a single-entry queue to act as a semaphore. */
#if RTOS_FREERTOS
sem->queue = xQueueCreate(1, sizeof(void *));
if(sem->queue == NULL) {
#endif /* RTOS_FREERTOS */
#if SYS_STATS
STATS_INC(sys.sem.err);
#endif /* SYS_STATS */
return ERR_MEM;
}
/* Acquired the semaphore if necessary. */
if(count == 0) {
temp = 0;
xQueueSend(sem->queue, &temp, 0);
}
/* Update the semaphore statistics. */
#if SYS_STATS
STATS_INC(sys.sem.used);
#if LWIP_STATS
if(lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) {
lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
}
#endif
#endif /* SYS_STATS */
/* Save the queue handle. */
sems[i].queue = sem->queue;
/* Return this semaphore. */
return (ERR_OK);
}
/**
* Destroys a semaphore.
*
* @param sem is the semaphore to be destroyed.
*/
void
sys_sem_free(sys_sem_t *sem)
{
/* Clear the queue handle. */
sem->queue = 0;
/* Update the semaphore statistics. */
#if SYS_STATS
STATS_DEC(sys.sem.used);
#endif /* SYS_STATS */
}
It appears to me that the code in sys_sem_free() does nothing to clear the value set in the global sems array that is being checked and set when creating a new semaphore with sys_sem_new().
In my project, this quickly results in a condition where the sys_sem_new() function returns ERR_MEM because SYS_SEM_MAX has been reached, and no new semaphores can be allocated.
Please note that even if I set SYS_SEM_MAX to a very high number, I am still unable to clear semaphores, and will eventually be unable to create new semaphores.
It seems that the same create and destroy functionality is used for mailboxes in the same file, and so I would expect a similar problem here, but have not yet experienced it myself.
Is this a bug in TI's implementation of the sys_arc.c file, or am I missing something??
FYI: I'm using TivaWare version 2.1.0.12573 which includes the newest version of LwIP (version 1.4.1).