mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
pthread: Allow configuration of priority and stacksize
The expected usage is: esp_pthread_set_cfg(cfg); pthread_create() If the inherit flag is set, then all subsequent threads forked by this thread will also inherit this configuration. This avoids having to change/prefix this for each and every pthread_create() call.
This commit is contained in:
parent
7594127ca3
commit
7a0cab0a5b
@ -4,6 +4,6 @@
|
|||||||
|
|
||||||
COMPONENT_SRCDIRS := .
|
COMPONENT_SRCDIRS := .
|
||||||
|
|
||||||
#COMPONENT_ADD_INCLUDEDIRS := include
|
COMPONENT_ADD_INCLUDEDIRS := include
|
||||||
|
|
||||||
COMPONENT_ADD_LDFLAGS := -lpthread
|
COMPONENT_ADD_LDFLAGS := -lpthread
|
||||||
|
57
components/pthread/include/esp_pthread.h
Normal file
57
components/pthread/include/esp_pthread.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// 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);
|
||||||
|
|
@ -29,6 +29,7 @@
|
|||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
|
|
||||||
#include "pthread_internal.h"
|
#include "pthread_internal.h"
|
||||||
|
#include "esp_pthread.h"
|
||||||
|
|
||||||
#define LOG_LOCAL_LEVEL CONFIG_LOG_DEFAULT_LEVEL
|
#define LOG_LOCAL_LEVEL CONFIG_LOG_DEFAULT_LEVEL
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
@ -53,6 +54,7 @@ typedef struct esp_pthread_entry {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
void *(*func)(void *); ///< user task entry
|
void *(*func)(void *); ///< user task entry
|
||||||
void *arg; ///< user task argument
|
void *arg; ///< user task argument
|
||||||
|
esp_pthread_cfg_t cfg; ///< pthread configuration
|
||||||
} esp_pthread_task_arg_t;
|
} esp_pthread_task_arg_t;
|
||||||
|
|
||||||
/** pthread mutex FreeRTOS wrapper */
|
/** pthread mutex FreeRTOS wrapper */
|
||||||
@ -66,14 +68,24 @@ static SemaphoreHandle_t s_threads_mux = NULL;
|
|||||||
static portMUX_TYPE s_mutex_init_lock = portMUX_INITIALIZER_UNLOCKED;
|
static portMUX_TYPE s_mutex_init_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||||
static SLIST_HEAD(esp_thread_list_head, esp_pthread_entry) s_threads_list
|
static SLIST_HEAD(esp_thread_list_head, esp_pthread_entry) s_threads_list
|
||||||
= SLIST_HEAD_INITIALIZER(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 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)
|
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();
|
s_threads_mux = xSemaphoreCreateMutex();
|
||||||
if (s_threads_mux == NULL) {
|
if (s_threads_mux == NULL) {
|
||||||
|
pthread_key_delete(s_pthread_cfg_key);
|
||||||
return ESP_ERR_NO_MEM;
|
return ESP_ERR_NO_MEM;
|
||||||
}
|
}
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
@ -123,15 +135,46 @@ static void pthread_delete(esp_pthread_t *pthread)
|
|||||||
free(pthread);
|
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)
|
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_LOGV(TAG, "%s ENTER %p", __FUNCTION__, task_arg->func);
|
ESP_LOGV(TAG, "%s ENTER %p", __FUNCTION__, task_arg->func);
|
||||||
|
|
||||||
// wait for start
|
// wait for start
|
||||||
xTaskNotifyWait(0, 0, NULL, portMAX_DELAY);
|
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);
|
ESP_LOGV(TAG, "%s START %p", __FUNCTION__, task_arg->func);
|
||||||
task_arg->func(task_arg->arg);
|
task_arg->func(task_arg->arg);
|
||||||
ESP_LOGV(TAG, "%s END %p", __FUNCTION__, task_arg->func);
|
ESP_LOGV(TAG, "%s END %p", __FUNCTION__, task_arg->func);
|
||||||
@ -190,11 +233,23 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
|||||||
free(task_arg);
|
free(task_arg);
|
||||||
return ENOMEM;
|
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));
|
memset(pthread, 0, sizeof(esp_pthread_t));
|
||||||
task_arg->func = start_routine;
|
task_arg->func = start_routine;
|
||||||
task_arg->arg = arg;
|
task_arg->arg = arg;
|
||||||
BaseType_t res = xTaskCreate(&pthread_task_func, "pthread", CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT,
|
BaseType_t res = xTaskCreate(&pthread_task_func, "pthread", stack_size,
|
||||||
task_arg, CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT, &xHandle);
|
task_arg, prio, &xHandle);
|
||||||
if(res != pdPASS) {
|
if(res != pdPASS) {
|
||||||
ESP_LOGE(TAG, "Failed to create task!");
|
ESP_LOGE(TAG, "Failed to create task!");
|
||||||
free(pthread);
|
free(pthread);
|
||||||
|
@ -155,6 +155,8 @@ INPUT = \
|
|||||||
../../components/esp32/include/esp32/pm.h \
|
../../components/esp32/include/esp32/pm.h \
|
||||||
### esp_timer, High Resolution Timer
|
### esp_timer, High Resolution Timer
|
||||||
../../components/esp32/include/esp_timer.h \
|
../../components/esp32/include/esp_timer.h \
|
||||||
|
### ESP Pthread parameters
|
||||||
|
../../components/pthread/include/esp_pthread.h \
|
||||||
###
|
###
|
||||||
### FreeRTOS
|
### FreeRTOS
|
||||||
###
|
###
|
||||||
|
65
docs/en/api-reference/system/esp_pthread.rst
Normal file
65
docs/en/api-reference/system/esp_pthread.rst
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
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
|
||||||
|
|
@ -18,6 +18,7 @@ System API
|
|||||||
Sleep Modes <sleep_modes>
|
Sleep Modes <sleep_modes>
|
||||||
Base MAC address <base_mac_address>
|
Base MAC address <base_mac_address>
|
||||||
Over The Air Updates (OTA) <ota>
|
Over The Air Updates (OTA) <ota>
|
||||||
|
ESP pthread <esp_pthread>
|
||||||
|
|
||||||
|
|
||||||
Example code for this API section is provided in :example:`system` directory of ESP-IDF examples.
|
Example code for this API section is provided in :example:`system` directory of ESP-IDF examples.
|
||||||
|
1
docs/zh_CN/api-reference/system/esp_pthread.rst
Normal file
1
docs/zh_CN/api-reference/system/esp_pthread.rst
Normal file
@ -0,0 +1 @@
|
|||||||
|
.. include:: ../../../en/api-reference/system/esp_pthread.rst
|
Loading…
x
Reference in New Issue
Block a user