/* * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ /* * pthread port for Linux build */ #include #include #include "sdkconfig.h" #include "esp_pthread.h" #include "esp_heap_caps.h" #include #include "freertos/FreeRTOS.h" static pthread_key_t s_pthread_cfg_key; static void esp_pthread_cfg_key_destructor(void *value) { free(value); } static int get_default_pthread_core(void) { return CONFIG_PTHREAD_TASK_CORE_DEFAULT == -1 ? tskNO_AFFINITY : CONFIG_PTHREAD_TASK_CORE_DEFAULT; } /** * @brief Creates a default pthread configuration based * on the values set via menuconfig. * * @return * A default configuration structure. */ esp_pthread_cfg_t esp_pthread_get_default_config(void) { esp_pthread_cfg_t cfg = { .stack_size = CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT, .prio = CONFIG_PTHREAD_TASK_PRIO_DEFAULT, .inherit_cfg = false, .thread_name = NULL, .pin_to_core = get_default_pthread_core(), .stack_alloc_caps = MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT, }; return cfg; } esp_err_t esp_pthread_set_cfg(const esp_pthread_cfg_t *cfg) { // Not checking the stack size here since PTHREAD_STACK_MIN has two conflicting declarations on Linux if (cfg == NULL) { return ESP_ERR_INVALID_ARG; } // 0 is treated as default value, hence change caps to MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL in that case int heap_caps; if (cfg->stack_alloc_caps == 0) { heap_caps = MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL; } else { // Check that memory is 8-bit capable if (!(cfg->stack_alloc_caps & MALLOC_CAP_8BIT)) { return ESP_ERR_INVALID_ARG; } heap_caps = cfg->stack_alloc_caps; } /* If a value is already set, update that value */ esp_pthread_cfg_t *p = pthread_getspecific(s_pthread_cfg_key); if (!p) { p = malloc(sizeof(esp_pthread_cfg_t)); if (!p) { return ESP_ERR_NO_MEM; } } *p = *cfg; p->stack_alloc_caps = heap_caps; p->stack_size = MAX(p->stack_size, 0x4000); // make sure Linux minimal stack size is respected int __attribute((unused)) res = pthread_setspecific(s_pthread_cfg_key, p); assert(res == 0); return ESP_OK; } esp_err_t esp_pthread_get_cfg(esp_pthread_cfg_t *p) { if (p == NULL) { return ESP_ERR_INVALID_ARG; } esp_pthread_cfg_t *cfg = pthread_getspecific(s_pthread_cfg_key); if (cfg) { *p = *cfg; return ESP_OK; } memset(p, 0, sizeof(*p)); return ESP_ERR_NOT_FOUND; } __attribute__((constructor)) esp_err_t esp_pthread_init(void) { if (pthread_key_create(&s_pthread_cfg_key, esp_pthread_cfg_key_destructor) != 0) { return ESP_ERR_NO_MEM; } return ESP_OK; }