--- /dev/null
+// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include <pthread.h>
+
+/** pthread configuration structure that influences pthread creation */
+typedef struct {
+ size_t stack_size; ///< the stack size of the pthread
+ size_t prio; ///< the thread's priority
+ bool inherit_cfg; ///< inherit this configuration further
+} esp_pthread_cfg_t;
+
+/**
+ * @brief Configure parameters for creating pthread
+ *
+ * This API allows you to configure how the subsequent
+ * pthread_create() call will behave. This call can be used to setup
+ * configuration parameters like stack size, priority, configuration
+ * inheritance etc.
+ *
+ * If the 'inherit' flag in the configuration structure is enabled,
+ * then the same configuration is also inherited in the thread
+ * subtree.
+ *
+ * @param cfg The pthread config parameters
+ *
+ * @return
+ * - ESP_OK if configuration was successfully set
+ * - ESP_ERR_NO_MEM if out of memory
+ */
+esp_err_t esp_pthread_set_cfg(const esp_pthread_cfg_t *cfg);
+
+/**
+ * @brief Get current pthread creation configuration
+ *
+ * This will retrieve the current configuration that will be used for
+ * creating threads.
+ *
+ * @param p Pointer to the pthread config structure that will be
+ * updated with the currently configured parameters
+ *
+ * @return
+ * - ESP_OK if the configuration was available
+ * - ESP_ERR_NOT_FOUND if a configuration wasn't previously set
+ */
+esp_err_t esp_pthread_get_cfg(esp_pthread_cfg_t *p);
+
#include "freertos/semphr.h"
#include "pthread_internal.h"
+#include "esp_pthread.h"
#define LOG_LOCAL_LEVEL CONFIG_LOG_DEFAULT_LEVEL
#include "esp_log.h"
typedef struct {
void *(*func)(void *); ///< user task entry
void *arg; ///< user task argument
+ esp_pthread_cfg_t cfg; ///< pthread configuration
} esp_pthread_task_arg_t;
/** pthread mutex FreeRTOS wrapper */
static portMUX_TYPE s_mutex_init_lock = portMUX_INITIALIZER_UNLOCKED;
static SLIST_HEAD(esp_thread_list_head, esp_pthread_entry) s_threads_list
= SLIST_HEAD_INITIALIZER(s_threads_list);
+static pthread_key_t s_pthread_cfg_key;
static int IRAM_ATTR pthread_mutex_lock_internal(esp_pthread_mutex_t *mux, TickType_t tmo);
+static void esp_pthread_cfg_key_destructor(void *value)
+{
+ free(value);
+}
+
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;
+ }
s_threads_mux = xSemaphoreCreateMutex();
if (s_threads_mux == NULL) {
+ pthread_key_delete(s_pthread_cfg_key);
return ESP_ERR_NO_MEM;
}
return ESP_OK;
free(pthread);
}
+
+/* Call this function to configure pthread stacks in Pthreads */
+esp_err_t esp_pthread_set_cfg(const esp_pthread_cfg_t *cfg)
+{
+ /* 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;
+ pthread_setspecific(s_pthread_cfg_key, p);
+ return 0;
+}
+
+esp_err_t esp_pthread_get_cfg(esp_pthread_cfg_t *p)
+{
+ 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;
+}
+
static void pthread_task_func(void *arg)
{
esp_pthread_task_arg_t *task_arg = (esp_pthread_task_arg_t *)arg;
ESP_LOGV(TAG, "%s ENTER %p", __FUNCTION__, task_arg->func);
-
// wait for start
xTaskNotifyWait(0, 0, NULL, portMAX_DELAY);
+ if (task_arg->cfg.inherit_cfg) {
+ /* If inherit option is set, then do a set_cfg() ourselves for future forks */
+ esp_pthread_set_cfg(&task_arg->cfg);
+ }
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);
return ENOMEM;
}
+ uint32_t stack_size = CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT;
+ BaseType_t prio = CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT;
+ esp_pthread_cfg_t *pthread_cfg = pthread_getspecific(s_pthread_cfg_key);
+ if (pthread_cfg) {
+ if (pthread_cfg->stack_size) {
+ stack_size = pthread_cfg->stack_size;
+ }
+ if (pthread_cfg->prio && pthread_cfg->prio < configMAX_PRIORITIES) {
+ prio = pthread_cfg->prio;
+ }
+ task_arg->cfg = *pthread_cfg;
+ }
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);
+ BaseType_t res = xTaskCreate(&pthread_task_func, "pthread", stack_size,
+ task_arg, prio, &xHandle);
if(res != pdPASS) {
ESP_LOGE(TAG, "Failed to create task!");
free(pthread);
--- /dev/null
+ESP-pthread
+===========
+
+Overview
+--------
+
+This module offers Espressif specific extensions to the pthread library that can be used to influence the behaviour of pthreads. Currently the following configuration can be tuned:
+ * Stack size of the pthreads
+ * Priority of the created pthreads
+ * Inheriting this configuration across threads
+
+Example to tune the stack size of the pthread:
+
+.. highlight:: c
+
+::
+
+ main()
+ {
+ pthread_t t1;
+
+ esp_pthread_cfg_t cfg;
+ cfg.stack_size = (4 * 1024);
+ esp_pthread_set_cfg(&cfg);
+
+ pthread_create(&t1, NULL, thread_func);
+ }
+
+The API can also be used for inheriting the settings across threads. For example:
+
+.. highlight:: c
+
+::
+
+ void * my_thread2(void * p)
+ {
+ /* This thread will inherit the stack size of 4K */
+ printf("In my_thread2\n");
+ }
+
+ void * my_thread1(void * p)
+ {
+ printf("In my_thread1\n");
+ pthread_t t2;
+ pthread_create(&t2, NULL, my_thread2);
+ }
+
+ main()
+ {
+
+ pthread_t t1;
+
+ esp_pthread_cfg_t cfg;
+ cfg.stack_size = (4 * 1024);
+ cfg.inherit_cfg = true;
+ esp_pthread_set_cfg(&cfg);
+
+ pthread_create(&t1, NULL, my_thread1);
+ }
+
+API Reference
+-------------
+
+.. include:: /_build/inc/esp_pthread.inc
+