]> granicus.if.org Git - esp-idf/commitdiff
pthread: Allow configuration of priority and stacksize
authorKedar Sovani <kedars@gmail.com>
Sun, 25 Feb 2018 09:26:04 +0000 (14:56 +0530)
committerKedar Sovani <kedars@gmail.com>
Tue, 20 Mar 2018 12:36:32 +0000 (18:06 +0530)
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.

components/pthread/component.mk
components/pthread/include/esp_pthread.h [new file with mode: 0644]
components/pthread/pthread.c
docs/Doxyfile
docs/en/api-reference/system/esp_pthread.rst [new file with mode: 0644]
docs/en/api-reference/system/index.rst
docs/zh_CN/api-reference/system/esp_pthread.rst [new file with mode: 0644]

index cd69bb33055cabdf5086545c0d27caa0e50ebe34..97ace4b78cdd73b79bf5ba50a4333a9ed01a88b1 100644 (file)
@@ -4,6 +4,6 @@
 
 COMPONENT_SRCDIRS := .
 
-#COMPONENT_ADD_INCLUDEDIRS := include
+COMPONENT_ADD_INCLUDEDIRS := include
 
 COMPONENT_ADD_LDFLAGS := -lpthread
diff --git a/components/pthread/include/esp_pthread.h b/components/pthread/include/esp_pthread.h
new file mode 100644 (file)
index 0000000..ae3c2d6
--- /dev/null
@@ -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);
+
index 0ce185425b755b389debc51ef94866706b516241..9d7822b8659ad115d2a8dab22fee65bef7af1886 100644 (file)
@@ -29,6 +29,7 @@
 #include "freertos/semphr.h"
 
 #include "pthread_internal.h"
+#include "esp_pthread.h"
 
 #define LOG_LOCAL_LEVEL CONFIG_LOG_DEFAULT_LEVEL
 #include "esp_log.h"
@@ -53,6 +54,7 @@ typedef struct esp_pthread_entry {
 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 */
@@ -66,14 +68,24 @@ static SemaphoreHandle_t s_threads_mux  = NULL;
 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;
@@ -123,15 +135,46 @@ static void pthread_delete(esp_pthread_t *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)
 {
     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);
@@ -190,11 +233,23 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
         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);
index 0eb59273777711c5053f0881dfad009c9031d5db..3cfb49d379dfb574876d22b7642e713cc06f9a6e 100644 (file)
@@ -155,6 +155,8 @@ INPUT = \
     ../../components/esp32/include/esp32/pm.h \
     ### esp_timer, High Resolution Timer
     ../../components/esp32/include/esp_timer.h \
+    ### ESP Pthread parameters
+    ../../components/pthread/include/esp_pthread.h \
     ###
     ### FreeRTOS
     ###
diff --git a/docs/en/api-reference/system/esp_pthread.rst b/docs/en/api-reference/system/esp_pthread.rst
new file mode 100644 (file)
index 0000000..7e43ce3
--- /dev/null
@@ -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
+
index 593fcc3d6975ad74ed238cd8d793d7ee6bc483a5..7dd9991c45a1ac9b28fce63feb91141486345aea 100644 (file)
@@ -18,6 +18,7 @@ System API
    Sleep Modes <sleep_modes>
    Base MAC address <base_mac_address>
    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.
diff --git a/docs/zh_CN/api-reference/system/esp_pthread.rst b/docs/zh_CN/api-reference/system/esp_pthread.rst
new file mode 100644 (file)
index 0000000..274bc26
--- /dev/null
@@ -0,0 +1 @@
+.. include:: ../../../en/api-reference/system/esp_pthread.rst