feat(lwip): Add thread local semaphore to sync thread

This commit is contained in:
Dong Heng
2018-05-14 17:48:56 +08:00
parent 9139341b14
commit 900e3613f8
4 changed files with 90 additions and 1 deletions

View File

@ -602,4 +602,9 @@ config LWIP_SNTP_DEBUG
depends on LWIP_DEBUG
default n
config LWIP_THREAD_SAFE_DEBUG
bool "Enable debugging for LWIP thread safety."
depends on LWIP_DEBUG
default n
endmenu

View File

@ -50,5 +50,16 @@ typedef xTaskHandle sys_thread_t;
#define LWIP_COMPAT_MUTEX 0
#if LWIP_NETCONN_SEM_PER_THREAD
sys_sem_t* sys_thread_sem_init(void);
void sys_thread_sem_deinit(void);
sys_sem_t* sys_thread_sem_get(void);
#define LWIP_NETCONN_THREAD_SEM_ALLOC() sys_thread_sem_init()
#define LWIP_NETCONN_THREAD_SEM_FREE() sys_thread_sem_deinit()
#define LWIP_NETCONN_THREAD_SEM_GET() sys_thread_sem_get()
#endif
#endif /* __SYS_ARCH_H__ */

View File

@ -1313,7 +1313,7 @@ extern void vPortFree(void *pv, const char * file, unsigned line);
* The latter 2 can be invoked up by calling netconn_thread_init()/netconn_thread_cleanup().
* Ports may call these for threads created with sys_thread_new().
*/
#define LWIP_NETCONN_SEM_PER_THREAD 0
#define LWIP_NETCONN_SEM_PER_THREAD 1
/** LWIP_NETCONN_FULLDUPLEX==1: Enable code that allows reading from one thread,
* writing from a 2nd thread and closing from a 3rd thread at the same time.
@ -2146,6 +2146,12 @@ extern void vPortFree(void *pv, const char * file, unsigned line);
#define SNTP_DEBUG LWIP_DBG_ON
#endif
#ifdef CONFIG_LWIP_THREAD_SAFE_DEBUG
#define ESP_THREAD_SAFE_DEBUG LWIP_DBG_ON
#else
#define ESP_THREAD_SAFE_DEBUG LWIP_DBG_OFF
#endif
/**
* @}
*/

View File

@ -38,6 +38,7 @@
#include "lwip/mem.h"
#include "arch/sys_arch.h"
#define LWIP_THREAD_TLS 0
/* Message queue constants. */
#define archMESG_QUEUE_LENGTH (100)//( 6 )
@ -424,3 +425,69 @@ sys_arch_msleep(int ms)
vTaskDelay(ms / portTICK_RATE_MS);
}
#if LWIP_NETCONN_SEM_PER_THREAD
static void sys_thread_sem_free(int index, void *data) // destructor for TLS semaphore
{
sys_sem_t *sem = (sys_sem_t *)(data);
if (sem && *sem){
LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sem del, sem=%p\n", *sem));
vSemaphoreDelete(*sem);
}
if (sem) {
LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sem pointer del, sem_p=%p\n", sem));
free(sem);
}
}
/*
* get per thread semphore
*/
sys_sem_t* sys_thread_sem_init(void)
{
sys_sem_t *sem = (sys_sem_t*)mem_malloc(sizeof(sys_sem_t*));
if (!sem){
LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, "thread_sem_init: out of memory\n");
return 0;
}
*sem = xSemaphoreCreateBinary();
if (!(*sem)){
free(sem);
LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, "thread_sem_init: out of memory\n");
return 0;
}
vTaskSetThreadLocalStoragePointerAndDelCallback(NULL, LWIP_THREAD_TLS, sem, sys_thread_sem_free);
return sem;
}
/*
* get per thread semphore
*/
sys_sem_t* sys_thread_sem_get(void)
{
sys_sem_t *sem = pvTaskGetThreadLocalStoragePointer(NULL, LWIP_THREAD_TLS);
if (!sem) {
sem = sys_thread_sem_init();
}
LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sem_get s=%p\n", sem));
return sem;
}
void sys_thread_sem_deinit(void)
{
sys_sem_t *sem = pvTaskGetThreadLocalStoragePointer(NULL, LWIP_THREAD_TLS);
if (sem != NULL) {
sys_thread_sem_free(LWIP_THREAD_TLS, sem);
vTaskSetThreadLocalStoragePointerAndDelCallback(NULL, LWIP_THREAD_TLS, NULL, NULL);
}
}
#endif