diff --git a/components/pthread/component.mk b/components/pthread/component.mk index 97ace4b78..0dd239481 100644 --- a/components/pthread/component.mk +++ b/components/pthread/component.mk @@ -7,3 +7,7 @@ COMPONENT_SRCDIRS := . COMPONENT_ADD_INCLUDEDIRS := include COMPONENT_ADD_LDFLAGS := -lpthread + +ifdef CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK +COMPONENT_ADD_LDFLAGS += -Wl,--wrap=vPortCleanUpTCB +endif diff --git a/components/pthread/pthread_local_storage.c b/components/pthread/pthread_local_storage.c index da59726a3..f87f698d8 100644 --- a/components/pthread/pthread_local_storage.c +++ b/components/pthread/pthread_local_storage.c @@ -142,6 +142,29 @@ static void pthread_local_storage_thread_deleted_callback(int index, void *v_tls free(tls); } +#if defined(CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK) +/* Called from FreeRTOS task delete hook */ +void pthread_local_storage_cleanup(TaskHandle_t task) +{ + void *tls = pvTaskGetThreadLocalStoragePointer(task, PTHREAD_TLS_INDEX); + if (tls != NULL) { + pthread_local_storage_thread_deleted_callback(PTHREAD_TLS_INDEX, tls); + vTaskSetThreadLocalStoragePointer(task, PTHREAD_TLS_INDEX, NULL); + } +} + +void __real_vPortCleanUpTCB(void *tcb); + +/* If static task cleanup hook is defined then its applications responsibility to define `vPortCleanUpTCB`. + Here we are wrapping it, so that we can do pthread specific TLS cleanup and then invoke application + real specific `vPortCleanUpTCB` */ +void __wrap_vPortCleanUpTCB(void *tcb) +{ + pthread_local_storage_cleanup(tcb); + __real_vPortCleanUpTCB(tcb); +} +#endif + /* this function called from pthread_task_func for "early" cleanup of TLS in a pthread */ void pthread_internal_local_storage_destructor_callback() { @@ -151,10 +174,14 @@ void pthread_internal_local_storage_destructor_callback() /* remove the thread-local-storage pointer to avoid the idle task cleanup calling it again... */ +#if defined(CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK) + vTaskSetThreadLocalStoragePointer(NULL, PTHREAD_TLS_INDEX, NULL); +#else vTaskSetThreadLocalStoragePointerAndDelCallback(NULL, PTHREAD_TLS_INDEX, NULL, NULL); +#endif } } @@ -196,10 +223,14 @@ int pthread_setspecific(pthread_key_t key, const void *value) if (tls == NULL) { return ENOMEM; } +#if defined(CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK) + vTaskSetThreadLocalStoragePointer(NULL, PTHREAD_TLS_INDEX, tls); +#else vTaskSetThreadLocalStoragePointerAndDelCallback(NULL, PTHREAD_TLS_INDEX, tls, pthread_local_storage_thread_deleted_callback); +#endif } value_entry_t *entry = find_value(tls, key);