From 20942421c3599cac568f4eb0e8602f848274c2be Mon Sep 17 00:00:00 2001 From: Alexey Gerenkov Date: Fri, 1 Sep 2017 02:18:14 +0300 Subject: [PATCH] According to review comments --- components/freertos/tasks.c | 2 - components/newlib/include/pthread.h | 2 +- components/newlib/include/sys/features.h | 7 +- components/newlib/include/sys/sched.h | 2 + components/newlib/time.c | 6 + components/pthread/pthread.c | 598 ++++++++++--------- components/pthread/test/test_pthread_cxx.cpp | 40 +- 7 files changed, 337 insertions(+), 320 deletions(-) diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index e4b63fdad..0433deb2a 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -4623,7 +4623,6 @@ TickType_t uxReturn; TickType_t xTimeToWake; BaseType_t xReturn; - // UNTESTED_FUNCTION(); taskENTER_CRITICAL(&xTaskQueueMutex); { /* Only block if a notification is not already pending. */ @@ -4747,7 +4746,6 @@ TickType_t uxReturn; eNotifyValue eOriginalNotifyState; BaseType_t xReturn = pdPASS; - // UNTESTED_FUNCTION(); configASSERT( xTaskToNotify ); pxTCB = ( TCB_t * ) xTaskToNotify; diff --git a/components/newlib/include/pthread.h b/components/newlib/include/pthread.h index 907970fdf..db1f9c1ca 100644 --- a/components/newlib/include/pthread.h +++ b/components/newlib/include/pthread.h @@ -31,7 +31,7 @@ extern "C" { #include #include -#include +#include #include struct _pthread_cleanup_context { diff --git a/components/newlib/include/sys/features.h b/components/newlib/include/sys/features.h index 792f68bbc..87f3314fd 100644 --- a/components/newlib/include/sys/features.h +++ b/components/newlib/include/sys/features.h @@ -210,8 +210,11 @@ extern "C" { #endif /* __CYGWIN__ */ -#define _POSIX_THREADS 1 -#define _UNIX98_THREAD_MUTEX_ATTRIBUTES 1 +/* ESP-IDF-specific: enable pthreads support */ +#ifdef __XTENSA__ +#define _POSIX_THREADS 1 +#define _UNIX98_THREAD_MUTEX_ATTRIBUTES 1 +#endif /* Per the permission given in POSIX.1-2008 section 2.2.1, define * _POSIX_C_SOURCE if _XOPEN_SOURCE is defined and _POSIX_C_SOURCE is not. diff --git a/components/newlib/include/sys/sched.h b/components/newlib/include/sys/sched.h index 58f99d682..8554fc2b9 100644 --- a/components/newlib/include/sys/sched.h +++ b/components/newlib/include/sys/sched.h @@ -58,6 +58,8 @@ struct sched_param { #endif }; +int sched_yield( void ); + #ifdef __cplusplus } #endif diff --git a/components/newlib/time.c b/components/newlib/time.c index 1655c0b8e..6fde8b934 100644 --- a/components/newlib/time.c +++ b/components/newlib/time.c @@ -216,6 +216,12 @@ int usleep(useconds_t us) return 0; } +unsigned int sleep(unsigned int seconds) +{ + usleep(seconds*1000000UL); + return 0; +} + uint32_t system_get_time(void) { #if defined( WITH_FRC1 ) || defined( WITH_RTC ) diff --git a/components/pthread/pthread.c b/components/pthread/pthread.c index 44d76ec8c..f2409671a 100644 --- a/components/pthread/pthread.c +++ b/components/pthread/pthread.c @@ -8,35 +8,35 @@ #include "freertos/semphr.h" #include "freertos/list.h" -#define LOG_LOCAL_LEVEL CONFIG_LOG_DEFAULT_LEVEL//ESP_LOG_VERBOSE +#define LOG_LOCAL_LEVEL CONFIG_LOG_DEFAULT_LEVEL #include "esp_log.h" const static char *TAG = "esp_pthread"; -#define ESP_PTHREAD_LOGE( _tag_, format, ... ) ESP_LOGE(_tag_, format, ##__VA_ARGS__) -#define ESP_PTHREAD_LOGW( _tag_, format, ... ) ESP_LOGW(_tag_, format, ##__VA_ARGS__) -#define ESP_PTHREAD_LOGI( _tag_, format, ... ) ESP_LOGI(_tag_, format, ##__VA_ARGS__) -#define ESP_PTHREAD_LOGD( _tag_, format, ... ) ESP_LOGD(_tag_, format, ##__VA_ARGS__) -#define ESP_PTHREAD_LOGV( _tag_, format, ... ) ESP_LOGV(_tag_, format, ##__VA_ARGS__) - -#define PTHREAD_TASK_STATE_RUN 0 -#define PTHREAD_TASK_STATE_EXIT 1 +/** task state */ +enum esp_pthread_task_state { + PTHREAD_TASK_STATE_RUN, + PTHREAD_TASK_STATE_EXIT +}; +/** pthread thread FreeRTOS wrapper */ typedef struct { - ListItem_t list_item; - TaskHandle_t join_task; - int state; - bool detached; + ListItem_t list_item; ///< Tasks list node struct. FreeRTOS task handle is kept as list_item.xItemValue + TaskHandle_t join_task; ///< Handle of the task waiting to join + enum esp_pthread_task_state state; ///< pthread task state + bool detached; ///< True if pthread is detached } esp_pthread_t; +/** pthread wrapper task arg */ typedef struct { - void *(*func)(void *); - void *arg; + void *(*func)(void *); ///< user task entry + void *arg; ///< user task argument } esp_pthread_task_arg_t; +/** pthread mutex FreeRTOS wrapper */ typedef struct { - ListItem_t list_item; - SemaphoreHandle_t sem; - int type; + ListItem_t list_item; ///< mutexes list node struct + SemaphoreHandle_t sem; ///< Handle of the task waiting to join + int type; ///< Handle of the task waiting to join } esp_pthread_mutex_t; @@ -50,358 +50,371 @@ static int IRAM_ATTR pthread_mutex_lock_internal(esp_pthread_mutex_t *mux, TickT int esp_pthread_init(void) { - vListInitialise((List_t *)&s_threads_list); - s_once_mux = xSemaphoreCreateMutex(); - if (s_once_mux == NULL) - return ESP_FAIL; - s_threads_mux = xSemaphoreCreateMutex(); - if (s_threads_mux == NULL) { - vSemaphoreDelete(s_once_mux); - return ESP_FAIL; - } - return ESP_OK; + vListInitialise((List_t *)&s_threads_list); + s_once_mux = xSemaphoreCreateMutex(); + if (s_once_mux == NULL) { + return ESP_ERR_NO_MEM; + } + s_threads_mux = xSemaphoreCreateMutex(); + if (s_threads_mux == NULL) { + vSemaphoreDelete(s_once_mux); + return ESP_ERR_NO_MEM; + } + return ESP_OK; } -static TaskHandle_t pthread_find_handle(pthread_t thread) +static void *pthread_find_list_item(void *(*item_check)(ListItem_t *, void *arg), void *check_arg) { - ListItem_t const *list_end = listGET_END_MARKER(&s_threads_list); - ListItem_t *list_item = listGET_HEAD_ENTRY(&s_threads_list); - while (list_item != list_end) { - esp_pthread_t *pthread = listGET_LIST_ITEM_OWNER(list_item); - if ((pthread_t)pthread == thread) { - return (TaskHandle_t)listGET_LIST_ITEM_VALUE(list_item); - } - list_item = listGET_NEXT(list_item); - } - return NULL; + ListItem_t const *list_end = listGET_END_MARKER(&s_threads_list); + ListItem_t *list_item = listGET_HEAD_ENTRY(&s_threads_list); + while (list_item != list_end) { + void *val = item_check(list_item, check_arg); + if (val) { + return val; + } + list_item = listGET_NEXT(list_item); + } + return NULL; } +static void *pthread_get_handle_by_desc(ListItem_t *item, void *arg) +{ + esp_pthread_t *pthread = listGET_LIST_ITEM_OWNER(item); + if (pthread == arg) { + return (void *)listGET_LIST_ITEM_VALUE(item); + } + return NULL; +} +static inline TaskHandle_t pthread_find_handle(pthread_t thread) +{ + return pthread_find_list_item(pthread_get_handle_by_desc, (void *)thread); +} + +static void *pthread_get_desc_by_handle(ListItem_t *item, void *arg) +{ + TaskHandle_t task_handle = arg; + TaskHandle_t cur_handle = (TaskHandle_t)listGET_LIST_ITEM_VALUE(item); + if (task_handle == cur_handle) { + return (esp_pthread_t *)listGET_LIST_ITEM_OWNER(item); + } + return NULL; +} static esp_pthread_t *pthread_find(TaskHandle_t task_handle) { - ListItem_t const *list_end = listGET_END_MARKER(&s_threads_list); - ListItem_t *list_item = listGET_HEAD_ENTRY(&s_threads_list); - while (list_item != list_end) { - TaskHandle_t cur_handle = (TaskHandle_t)listGET_LIST_ITEM_VALUE(list_item); - if (task_handle == cur_handle) { - return (esp_pthread_t *)listGET_LIST_ITEM_OWNER(list_item); - } - list_item = listGET_NEXT(list_item); - } - return NULL; + return pthread_find_list_item(pthread_get_desc_by_handle, task_handle); } static void pthread_delete(esp_pthread_t *pthread) { - uxListRemove(&pthread->list_item); - free(pthread); + uxListRemove(&pthread->list_item); + free(pthread); } static void pthread_task_func(void *arg) { - esp_pthread_task_arg_t *task_arg = (esp_pthread_task_arg_t *)arg; + esp_pthread_task_arg_t *task_arg = (esp_pthread_task_arg_t *)arg; - ESP_PTHREAD_LOGV(TAG, "%s ENTER %p", __FUNCTION__, task_arg->func); + ESP_LOGV(TAG, "%s ENTER %p", __FUNCTION__, task_arg->func); - // wait for start - xTaskNotifyWait(0, 0, NULL, portMAX_DELAY); + // wait for start + xTaskNotifyWait(0, 0, NULL, portMAX_DELAY); - ESP_PTHREAD_LOGV(TAG, "%s START %p", __FUNCTION__, task_arg->func); - task_arg->func(task_arg->arg); - ESP_PTHREAD_LOGV(TAG, "%s END %p", __FUNCTION__, task_arg->func); - free(task_arg); + ESP_LOGV(TAG, "%s START %p", __FUNCTION__, task_arg->func); + task_arg->func(task_arg->arg); + ESP_LOGV(TAG, "%s END %p", __FUNCTION__, task_arg->func); + free(task_arg); if (xSemaphoreTake(s_threads_mux, portMAX_DELAY) != pdTRUE) { - assert(false && "Failed to lock threads list!"); + assert(false && "Failed to lock threads list!"); } - esp_pthread_t *pthread = pthread_find(xTaskGetCurrentTaskHandle()); - if (!pthread) { - assert(false && "Failed to find pthread for current task!"); + esp_pthread_t *pthread = pthread_find(xTaskGetCurrentTaskHandle()); + if (!pthread) { + assert(false && "Failed to find pthread for current task!"); + } + if (pthread->detached) { + // auto-free for detached threads + pthread_delete(pthread); + } else { + // Remove from list, it indicates that task has exited + if (pthread->join_task) { + // notify join + xTaskNotify(pthread->join_task, 0, eNoAction); + } else { + pthread->state = PTHREAD_TASK_STATE_EXIT; + } } - if (pthread->detached) { - // auto-free for detached threads - pthread_delete(pthread); - } else { - // Remove from list, it indicates that task has exited - if (pthread->join_task) { - // notify join - xTaskNotify(pthread->join_task, 0, eNoAction); - } else { - pthread->state = PTHREAD_TASK_STATE_EXIT; - } - } xSemaphoreGive(s_threads_mux); - vTaskDelete(NULL); + vTaskDelete(NULL); - ESP_PTHREAD_LOGV(TAG, "%s EXIT", __FUNCTION__); + ESP_LOGV(TAG, "%s EXIT", __FUNCTION__); } int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) { - TaskHandle_t xHandle = NULL; + TaskHandle_t xHandle = NULL; - ESP_PTHREAD_LOGV(TAG, "%s", __FUNCTION__); - if (attr) { - ESP_PTHREAD_LOGE(TAG, "Attrs not supported!"); - return EINVAL; - } - esp_pthread_task_arg_t *task_arg = malloc(sizeof(esp_pthread_task_arg_t)); - if (task_arg == NULL) { - ESP_PTHREAD_LOGE(TAG, "Failed to allocate task args!"); - errno = ENOMEM; - return ENOMEM; - } - memset(task_arg, 0, sizeof(esp_pthread_task_arg_t)); - esp_pthread_t *pthread = malloc(sizeof(esp_pthread_t)); - if (pthread == NULL) { - ESP_PTHREAD_LOGE(TAG, "Failed to allocate pthread data!"); - free(task_arg); - errno = ENOMEM; - return ENOMEM; - } - memset(pthread, 0, sizeof(esp_pthread_t)); - task_arg->func = start_routine; - task_arg->arg = arg; + ESP_LOGV(TAG, "%s", __FUNCTION__); + if (attr) { + assert(false && "pthread_create: attrs not supported!"); + } + esp_pthread_task_arg_t *task_arg = malloc(sizeof(esp_pthread_task_arg_t)); + if (task_arg == NULL) { + ESP_LOGE(TAG, "Failed to allocate task args!"); + errno = ENOMEM; + return ENOMEM; + } + memset(task_arg, 0, sizeof(esp_pthread_task_arg_t)); + esp_pthread_t *pthread = malloc(sizeof(esp_pthread_t)); + if (pthread == NULL) { + ESP_LOGE(TAG, "Failed to allocate pthread data!"); + free(task_arg); + errno = ENOMEM; + return ENOMEM; + } + memset(pthread, 0, sizeof(esp_pthread_t)); + task_arg->func = start_routine; + task_arg->arg = arg; BaseType_t res = xTaskCreate(&pthread_task_func, "pthread", CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT, - task_arg, CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT, &xHandle); - if(res != pdPASS) { - ESP_PTHREAD_LOGE(TAG, "Failed to create task!"); - free(pthread); - free(task_arg); - if (res == errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY) { - errno = ENOMEM; - return ENOMEM; - } else { - errno = EAGAIN; - return EAGAIN; - } - } - vListInitialiseItem((ListItem_t *)&pthread->list_item); - listSET_LIST_ITEM_OWNER((ListItem_t *)&pthread->list_item, pthread); - listSET_LIST_ITEM_VALUE((ListItem_t *)&pthread->list_item, (TickType_t)xHandle); + task_arg, CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT, &xHandle); + if(res != pdPASS) { + ESP_LOGE(TAG, "Failed to create task!"); + free(pthread); + free(task_arg); + if (res == errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY) { + errno = ENOMEM; + return ENOMEM; + } else { + errno = EAGAIN; + return EAGAIN; + } + } + vListInitialiseItem((ListItem_t *)&pthread->list_item); + listSET_LIST_ITEM_OWNER((ListItem_t *)&pthread->list_item, pthread); + listSET_LIST_ITEM_VALUE((ListItem_t *)&pthread->list_item, (TickType_t)xHandle); if (xSemaphoreTake(s_threads_mux, portMAX_DELAY) != pdTRUE) { - assert(false && "Failed to lock threads list!"); + assert(false && "Failed to lock threads list!"); } - vListInsertEnd((List_t *)&s_threads_list, (ListItem_t *)&pthread->list_item); + vListInsertEnd((List_t *)&s_threads_list, (ListItem_t *)&pthread->list_item); xSemaphoreGive(s_threads_mux); - // start task - xTaskNotify(xHandle, 0, eNoAction); + // start task + xTaskNotify(xHandle, 0, eNoAction); - *thread = (pthread_t)pthread; // pointer value fit into pthread_t (uint32_t) + *thread = (pthread_t)pthread; // pointer value fit into pthread_t (uint32_t) - ESP_PTHREAD_LOGV(TAG, "Created task %x", (uint32_t)xHandle); + ESP_LOGV(TAG, "Created task %x", (uint32_t)xHandle); - return 0; + return 0; } int pthread_join(pthread_t thread, void **retval) { - esp_pthread_t *pthread = (esp_pthread_t *)thread; - int ret = 0; + esp_pthread_t *pthread = (esp_pthread_t *)thread; + int ret = 0; - ESP_PTHREAD_LOGV(TAG, "%s %p", __FUNCTION__, pthread); + ESP_LOGV(TAG, "%s %p", __FUNCTION__, pthread); - // find task + // find task if (xSemaphoreTake(s_threads_mux, portMAX_DELAY) != pdTRUE) { - assert(false && "Failed to lock threads list!"); + assert(false && "Failed to lock threads list!"); } TaskHandle_t handle = pthread_find_handle(thread); if (!handle) { - errno = ESRCH; // not found - ret = ESRCH; + errno = ESRCH; // not found + ret = ESRCH; } else if (pthread->join_task) { - errno = EINVAL; // already have waiting task to join - ret = EINVAL; + errno = EINVAL; // already have waiting task to join + ret = EINVAL; } else if (handle == xTaskGetCurrentTaskHandle()) { - errno = EDEADLK; // join to self not allowed - ret = EDEADLK; + errno = EDEADLK; // join to self not allowed + ret = EDEADLK; } else { - esp_pthread_t *cur_pthread = pthread_find(xTaskGetCurrentTaskHandle()); - if (cur_pthread && cur_pthread->join_task == handle) { - errno = EDEADLK; // join to each other not allowed - ret = EDEADLK; - } else { - if (pthread->state == PTHREAD_TASK_STATE_RUN) { - pthread->join_task = xTaskGetCurrentTaskHandle(); - } else { - pthread_delete(pthread); - } - } + esp_pthread_t *cur_pthread = pthread_find(xTaskGetCurrentTaskHandle()); + if (cur_pthread && cur_pthread->join_task == handle) { + errno = EDEADLK; // join to each other not allowed + ret = EDEADLK; + } else { + if (pthread->state == PTHREAD_TASK_STATE_RUN) { + pthread->join_task = xTaskGetCurrentTaskHandle(); + } else { + pthread_delete(pthread); + } + } } xSemaphoreGive(s_threads_mux); if (ret == 0 && pthread->join_task) { - xTaskNotifyWait(0, 0, NULL, portMAX_DELAY); - if (xSemaphoreTake(s_threads_mux, portMAX_DELAY) != pdTRUE) { - assert(false && "Failed to lock threads list!"); - } - pthread_delete(pthread); + xTaskNotifyWait(0, 0, NULL, portMAX_DELAY); + if (xSemaphoreTake(s_threads_mux, portMAX_DELAY) != pdTRUE) { + assert(false && "Failed to lock threads list!"); + } + pthread_delete(pthread); xSemaphoreGive(s_threads_mux); } if (retval) { - *retval = 0; // no exit code in FreeRTOS + *retval = 0; // no exit code in FreeRTOS } - ESP_PTHREAD_LOGV(TAG, "%s %p EXIT %d", __FUNCTION__, pthread, ret); - return ret; + ESP_LOGV(TAG, "%s %p EXIT %d", __FUNCTION__, pthread, ret); + return ret; } int pthread_detach(pthread_t thread) { - esp_pthread_t *pthread = (esp_pthread_t *)thread; - int ret = 0; + esp_pthread_t *pthread = (esp_pthread_t *)thread; + int ret = 0; if (xSemaphoreTake(s_threads_mux, portMAX_DELAY) != pdTRUE) { - assert(false && "Failed to lock threads list!"); + assert(false && "Failed to lock threads list!"); } TaskHandle_t handle = pthread_find_handle(thread); if (!handle) { - errno = ESRCH; // not found - ret = ESRCH; - } else { - pthread->detached = true; - } + errno = ESRCH; // not found + ret = ESRCH; + } else { + pthread->detached = true; + } xSemaphoreGive(s_threads_mux); - ESP_PTHREAD_LOGV(TAG, "%s %p EXIT %d", __FUNCTION__, pthread, ret); - return ret; + ESP_LOGV(TAG, "%s %p EXIT %d", __FUNCTION__, pthread, ret); + return ret; } int pthread_cancel(pthread_t thread) { - assert(false && "pthread_cancel not supported!"); - return -1; + assert(false && "pthread_cancel not supported!"); + return -1; } int sched_yield( void ) { - vTaskDelay(0); - return 0; + vTaskDelay(0); + return 0; } pthread_t pthread_self(void) { if (xSemaphoreTake(s_threads_mux, portMAX_DELAY) != pdTRUE) { - assert(false && "Failed to lock threads list!"); + assert(false && "Failed to lock threads list!"); + } + esp_pthread_t *pthread = pthread_find(xTaskGetCurrentTaskHandle()); + if (!pthread) { + assert(false && "Failed to find current thread ID!"); } - esp_pthread_t *pthread = pthread_find(xTaskGetCurrentTaskHandle()); - if (!pthread) { - assert(false && "Failed to find current thread ID!"); - } xSemaphoreGive(s_threads_mux); - return (pthread_t)pthread; + return (pthread_t)pthread; } int pthread_equal(pthread_t t1, pthread_t t2) { - return t1 == t2 ? 1 : 0; + return t1 == t2 ? 1 : 0; } /***************** KEY ******************/ int pthread_key_create(pthread_key_t *key, void (*destructor)(void*)) { - static int s_created; + static int s_created; - //TODO: Key destructors not suppoted! - if (s_created) { - // key API supports just one key necessary by libstdcxx threading implementation - return ENOMEM; - } - *key = 1; - s_created = 1; - return 0; + //TODO: Key destructors not suppoted! + if (s_created) { + // key API supports just one key necessary by libstdcxx threading implementation + assert(false && "pthread_key_create: multiple keys not supported!"); + } + *key = 1; + s_created = 1; + return 0; } int pthread_key_delete(pthread_key_t key) { - assert(false && "pthread_key_delete not supported!"); - return -1; + assert(false && "pthread_key_delete not supported!"); + return -1; } void *pthread_getspecific(pthread_key_t key) { - assert(false && "pthread_getspecific not supported!"); - return NULL; + assert(false && "pthread_getspecific not supported!"); + return NULL; } int pthread_setspecific(pthread_key_t key, const void *value) { - assert(false && "pthread_setspecific not supported!"); - return -1; + assert(false && "pthread_setspecific not supported!"); + return -1; } /***************** ONCE ******************/ int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) { - if (once_control == NULL || init_routine == NULL || !once_control->is_initialized) { - ESP_PTHREAD_LOGE(TAG, "%s: Invalid args!", __FUNCTION__); - return EINVAL; - } + if (once_control == NULL || init_routine == NULL || !once_control->is_initialized) { + ESP_LOGE(TAG, "%s: Invalid args!", __FUNCTION__); + return EINVAL; + } - TaskHandle_t cur_task = xTaskGetCurrentTaskHandle(); - // do not take mutex if OS is not running yet + TaskHandle_t cur_task = xTaskGetCurrentTaskHandle(); + // do not take mutex if OS is not running yet if (!cur_task || xSemaphoreTake(s_once_mux, portMAX_DELAY) == pdTRUE) { - if (!once_control->init_executed) { - ESP_PTHREAD_LOGV(TAG, "%s: call init_routine %p", __FUNCTION__, once_control); - init_routine(); - once_control->init_executed = 1; - } - if (cur_task) { - xSemaphoreGive(s_once_mux); - } + if (!once_control->init_executed) { + ESP_LOGV(TAG, "%s: call init_routine %p", __FUNCTION__, once_control); + init_routine(); + once_control->init_executed = 1; + } + if (cur_task) { + xSemaphoreGive(s_once_mux); + } } else { - ESP_PTHREAD_LOGE(TAG, "%s: Failed to lock!", __FUNCTION__); - return EBUSY; + ESP_LOGE(TAG, "%s: Failed to lock!", __FUNCTION__); + return EBUSY; } - return 0; + return 0; } /***************** MUTEX ******************/ static int mutexattr_check(const pthread_mutexattr_t *attr) { - if (attr->type < PTHREAD_MUTEX_NORMAL || attr->type > PTHREAD_MUTEX_RECURSIVE) { - return EINVAL; - } - return 0; + if (attr->type < PTHREAD_MUTEX_NORMAL || attr->type > PTHREAD_MUTEX_RECURSIVE) { + return EINVAL; + } + return 0; } int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) { - int type = PTHREAD_MUTEX_NORMAL; + int type = PTHREAD_MUTEX_NORMAL; - if (!mutex) { - errno = EINVAL; - return EINVAL; - } + if (!mutex) { + errno = EINVAL; + return EINVAL; + } - if (attr) { - if (!attr->is_initialized) { - errno = EINVAL; - return EINVAL; - } - int res = mutexattr_check(attr); - if (res) { - errno = res; - return res; - } - type = attr->type; - } + if (attr) { + if (!attr->is_initialized) { + errno = EINVAL; + return EINVAL; + } + int res = mutexattr_check(attr); + if (res) { + errno = res; + return res; + } + type = attr->type; + } - esp_pthread_mutex_t *mux = (esp_pthread_mutex_t *)malloc(sizeof(esp_pthread_mutex_t)); + esp_pthread_mutex_t *mux = (esp_pthread_mutex_t *)malloc(sizeof(esp_pthread_mutex_t)); if (!mux) { errno = ENOMEM; return ENOMEM; - } - mux->type = type; + } + mux->type = type; - if (mux->type == PTHREAD_MUTEX_RECURSIVE) { + if (mux->type == PTHREAD_MUTEX_RECURSIVE) { mux->sem = xSemaphoreCreateRecursiveMutex(); } else { mux->sem = xSemaphoreCreateMutex(); @@ -410,24 +423,24 @@ int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) free(mux); errno = EAGAIN; return EAGAIN; - } + } - *mutex = (pthread_mutex_t)mux; // pointer value fit into pthread_mutex_t (uint32_t) + *mutex = (pthread_mutex_t)mux; // pointer value fit into pthread_mutex_t (uint32_t) - return 0; + return 0; } int pthread_mutex_destroy(pthread_mutex_t *mutex) { - esp_pthread_mutex_t *mux; + esp_pthread_mutex_t *mux; - ESP_PTHREAD_LOGV(TAG, "%s %p", __FUNCTION__, mutex); + ESP_LOGV(TAG, "%s %p", __FUNCTION__, mutex); - if (!mutex) { - errno = EINVAL; - return EINVAL; - } - mux = (esp_pthread_mutex_t *)*mutex; + if (!mutex) { + errno = EINVAL; + return EINVAL; + } + mux = (esp_pthread_mutex_t *)*mutex; // check if mux is busy int res = pthread_mutex_lock_internal(mux, 0); @@ -436,10 +449,10 @@ int pthread_mutex_destroy(pthread_mutex_t *mutex) return EBUSY; } - vSemaphoreDelete(mux->sem); - free(mux); + vSemaphoreDelete(mux->sem); + free(mux); - return 0; + return 0; } static int IRAM_ATTR pthread_mutex_lock_internal(esp_pthread_mutex_t *mux, TickType_t tmo) @@ -461,88 +474,79 @@ static int IRAM_ATTR pthread_mutex_lock_internal(esp_pthread_mutex_t *mux, TickT int IRAM_ATTR pthread_mutex_lock(pthread_mutex_t *mutex) { - if (!mutex) { - errno = EINVAL; - return EINVAL; - } + if (!mutex) { + errno = EINVAL; + return EINVAL; + } return pthread_mutex_lock_internal((esp_pthread_mutex_t *)*mutex, portMAX_DELAY); } int IRAM_ATTR pthread_mutex_trylock(pthread_mutex_t *mutex) { - if (!mutex) { - errno = EINVAL; - return EINVAL; - } + if (!mutex) { + errno = EINVAL; + return EINVAL; + } return pthread_mutex_lock_internal((esp_pthread_mutex_t *)*mutex, 0); } int IRAM_ATTR pthread_mutex_unlock(pthread_mutex_t *mutex) { - esp_pthread_mutex_t *mux; + esp_pthread_mutex_t *mux; - if (!mutex) { - errno = EINVAL; - return EINVAL; - } - mux = (esp_pthread_mutex_t *)*mutex; + if (!mutex) { + errno = EINVAL; + return EINVAL; + } + mux = (esp_pthread_mutex_t *)*mutex; - if (mux->type == PTHREAD_MUTEX_RECURSIVE) { + if (mux->type == PTHREAD_MUTEX_RECURSIVE) { xSemaphoreGiveRecursive(mux->sem); } else { xSemaphoreGive(mux->sem); - } - return 0; + } + return 0; } int pthread_mutexattr_init(pthread_mutexattr_t *attr) { - if (!attr) { - errno = EINVAL; - return EINVAL; - } - attr->type = PTHREAD_MUTEX_NORMAL; - attr->is_initialized = 1; - return 0; + if (!attr) { + errno = EINVAL; + return EINVAL; + } + attr->type = PTHREAD_MUTEX_NORMAL; + attr->is_initialized = 1; + return 0; } int pthread_mutexattr_destroy(pthread_mutexattr_t *attr) { - if (!attr) { - errno = EINVAL; - return EINVAL; - } - attr->is_initialized = 0; - return 0; + if (!attr) { + errno = EINVAL; + return EINVAL; + } + attr->is_initialized = 0; + return 0; } int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type) { - assert(false && "pthread_mutexattr_gettype not supported!"); - return -1; + assert(false && "pthread_mutexattr_gettype not supported!"); + return -1; } int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) { - if (!attr) { - errno = EINVAL; - return EINVAL; - } - pthread_mutexattr_t tmp_attr = {.type = type}; - int res = mutexattr_check(&tmp_attr); - if (res) { - errno = res; - } else { - attr->type = type; - } - return res; -} - -/***************** AUX ******************/ -// TODO: move to newlib/time.c???? -// needed for std::this_thread::sleep_for -unsigned int sleep(unsigned int seconds) -{ - usleep(seconds*1000000UL); - return 0; + if (!attr) { + errno = EINVAL; + return EINVAL; + } + pthread_mutexattr_t tmp_attr = {.type = type}; + int res = mutexattr_check(&tmp_attr); + if (res) { + errno = res; + } else { + attr->type = type; + } + return res; } diff --git a/components/pthread/test/test_pthread_cxx.cpp b/components/pthread/test/test_pthread_cxx.cpp index 2cdaf18cf..287a1da1b 100644 --- a/components/pthread/test/test_pthread_cxx.cpp +++ b/components/pthread/test/test_pthread_cxx.cpp @@ -3,9 +3,11 @@ #include #include "unity.h" -std::shared_ptr global_sp; -std::mutex mtx; -std::recursive_mutex recur_mtx; +#if __GTHREADS && __GTHREADS_CXX0X + +static std::shared_ptr global_sp; +static std::mutex mtx; +static std::recursive_mutex recur_mtx; static void thread_do_nothing() {} @@ -17,20 +19,20 @@ static void thread_main() while (i < 3) { int old_val, new_val; - // mux test - mtx.lock(); + // mux test + mtx.lock(); old_val = *global_sp; - std::this_thread::yield(); - (*global_sp)++; + std::this_thread::yield(); + (*global_sp)++; std::this_thread::yield(); new_val = *global_sp; - mtx.unlock(); + mtx.unlock(); std::cout << "thread " << std::hex << std::this_thread::get_id() << ": " << i++ << " val= " << *global_sp << std::endl; TEST_ASSERT_TRUE(new_val == old_val + 1); // sleep_for test std::chrono::milliseconds dur(300); - std::this_thread::sleep_for(dur); + std::this_thread::sleep_for(dur); // recursive mux test recur_mtx.lock(); @@ -46,11 +48,11 @@ static void thread_main() TEST_ASSERT_TRUE(new_val == old_val + 1); // sleep_until test - using std::chrono::system_clock; - std::time_t tt = system_clock::to_time_t(system_clock::now()); - struct std::tm *ptm = std::localtime(&tt); - ptm->tm_sec++; - std::this_thread::sleep_until(system_clock::from_time_t (mktime(ptm))); + using std::chrono::system_clock; + std::time_t tt = system_clock::to_time_t(system_clock::now()); + struct std::tm *ptm = std::localtime(&tt); + ptm->tm_sec++; + std::this_thread::sleep_until(system_clock::from_time_t (mktime(ptm))); } } @@ -69,11 +71,13 @@ TEST_CASE("pthread CXX", "[pthread]") std::thread t3(thread_main); std::thread t4(thread_main); if (t3.joinable()) { - std::cout << "Join thread " << std::hex << t3.get_id() << std::endl; - t3.join(); + std::cout << "Join thread " << std::hex << t3.get_id() << std::endl; + t3.join(); } if (t4.joinable()) { - std::cout << "Join thread " << std::hex << t4.get_id() << std::endl; - t4.join(); + std::cout << "Join thread " << std::hex << t4.get_id() << std::endl; + t4.join(); } } + +#endif