| 
									
										
										
										
											2021-08-27 13:00:10 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2023-03-12 21:49:57 +01:00
										 |  |  |  * SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD | 
					
						
							| 
									
										
										
										
											2021-08-27 13:00:10 +08:00
										 |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: Apache-2.0 | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | #include <time.h>
 | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | #include <errno.h>
 | 
					
						
							|  |  |  | #include <pthread.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include "esp_err.h"
 | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | #include "esp_attr.h"
 | 
					
						
							| 
									
										
										
										
											2022-07-21 19:14:41 +08:00
										 |  |  | #include "esp_cpu.h"
 | 
					
						
							| 
									
										
										
										
											2019-03-14 17:29:32 +08:00
										 |  |  | #include "sys/queue.h"
 | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | #include "freertos/FreeRTOS.h"
 | 
					
						
							|  |  |  | #include "freertos/task.h"
 | 
					
						
							|  |  |  | #include "freertos/semphr.h"
 | 
					
						
							| 
									
										
											  
											
												global: move the soc component out of the common list
This MR removes the common dependency from every IDF components to the SOC component.
Currently, in the ``idf_functions.cmake`` script, we include the header path of SOC component by default for all components.
But for better code organization (or maybe also benifits to the compiling speed), we may remove the dependency to SOC components for most components except the driver and kernel related components.
In CMAKE, we have two kinds of header visibilities (set by include path visibility):
(Assume component A --(depends on)--> B, B is the current component)
1. public (``COMPONENT_ADD_INCLUDEDIRS``): means this path is visible to other depending components (A) (visible to A and B)
2. private (``COMPONENT_PRIV_INCLUDEDIRS``): means this path is only visible to source files inside the component (visible to B only)
and we have two kinds of depending ways:
(Assume component A --(depends on)--> B --(depends on)--> C, B is the current component)
1. public (```COMPONENT_REQUIRES```): means B can access to public include path of C. All other components rely on you (A) will also be available for the public headers. (visible to A, B)
2. private (``COMPONENT_PRIV_REQUIRES``): means B can access to public include path of C, but don't propagate this relation to other components (A). (visible to B)
1. remove the common requirement in ``idf_functions.cmake``, this makes the SOC components invisible to all other components by default.
2. if a component (for example, DRIVER) really needs the dependency to SOC, add a private dependency to SOC for it.
3. some other components that don't really depends on the SOC may still meet some errors saying "can't find header soc/...", this is because it's depended component (DRIVER) incorrectly include the header of SOC in its public headers. Moving all this kind of #include into source files, or private headers
4. Fix the include requirements for some file which miss sufficient #include directives. (Previously they include some headers by the long long long header include link)
This is a breaking change. Previous code may depends on the long include chain.
You may need to include the following headers for some files after this commit:
- soc/soc.h
- soc/soc_memory_layout.h
- driver/gpio.h
- esp_sleep.h
The major broken include chain includes:
1. esp_system.h no longer includes esp_sleep.h. The latter includes driver/gpio.h and driver/touch_pad.h.
2. ets_sys.h no longer includes soc/soc.h
3. freertos/portmacro.h no longer includes soc/soc_memory_layout.h
some peripheral headers no longer includes their hw related headers, e.g. rom/gpio.h no longer includes soc/gpio_pins.h and soc/gpio_reg.h
BREAKING CHANGE
											
										 
											2019-04-03 13:17:38 +08:00
										 |  |  | #include "soc/soc_memory_layout.h"
 | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-04 15:52:19 +11:00
										 |  |  | #include "pthread_internal.h"
 | 
					
						
							| 
									
										
										
										
											2018-02-25 14:56:04 +05:30
										 |  |  | #include "esp_pthread.h"
 | 
					
						
							| 
									
										
										
										
											2017-10-04 15:52:19 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | #include "esp_log.h"
 | 
					
						
							| 
									
										
										
										
											2017-11-14 11:43:32 +03:00
										 |  |  | const static char *TAG = "pthread"; | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  | /** task state */ | 
					
						
							|  |  |  | enum esp_pthread_task_state { | 
					
						
							|  |  |  |     PTHREAD_TASK_STATE_RUN, | 
					
						
							|  |  |  |     PTHREAD_TASK_STATE_EXIT | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  | /** pthread thread FreeRTOS wrapper */ | 
					
						
							| 
									
										
										
										
											2017-11-14 11:43:32 +03:00
										 |  |  | typedef struct esp_pthread_entry { | 
					
						
							|  |  |  |     SLIST_ENTRY(esp_pthread_entry)  list_node;  ///< Tasks list node struct.
 | 
					
						
							|  |  |  |     TaskHandle_t                handle;         ///< FreeRTOS task handle
 | 
					
						
							|  |  |  |     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
 | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |     void                       *retval;         ///< Value supplied to calling thread during join
 | 
					
						
							|  |  |  |     void                       *task_arg;       ///< Task arguments
 | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | } esp_pthread_t; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  | /** pthread wrapper task arg */ | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     void *(*func)(void *);  ///< user task entry
 | 
					
						
							|  |  |  |     void *arg;              ///< user task argument
 | 
					
						
							| 
									
										
										
										
											2018-02-25 14:56:04 +05:30
										 |  |  |     esp_pthread_cfg_t cfg;  ///< pthread configuration
 | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | } esp_pthread_task_arg_t; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  | /** pthread mutex FreeRTOS wrapper */ | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     SemaphoreHandle_t   sem;        ///< Handle of the task waiting to join
 | 
					
						
							| 
									
										
										
										
											2017-09-04 21:46:16 +03:00
										 |  |  |     int                 type;       ///< Mutex type. Currently supported PTHREAD_MUTEX_NORMAL and PTHREAD_MUTEX_RECURSIVE
 | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | } esp_pthread_mutex_t; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-14 11:43:32 +03:00
										 |  |  | static SemaphoreHandle_t s_threads_mux  = NULL; | 
					
						
							| 
									
										
										
										
											2021-08-27 13:00:10 +08:00
										 |  |  | portMUX_TYPE pthread_lazy_init_lock  = portMUX_INITIALIZER_UNLOCKED; // Used for mutexes and cond vars and rwlocks
 | 
					
						
							| 
									
										
										
										
											2017-11-14 11:43:32 +03:00
										 |  |  | static SLIST_HEAD(esp_thread_list_head, esp_pthread_entry) s_threads_list | 
					
						
							|  |  |  |                                         = SLIST_HEAD_INITIALIZER(s_threads_list); | 
					
						
							| 
									
										
										
										
											2018-02-25 14:56:04 +05:30
										 |  |  | static pthread_key_t s_pthread_cfg_key; | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-20 09:25:43 +07:00
										 |  |  | static int pthread_mutex_lock_internal(esp_pthread_mutex_t *mux, TickType_t tmo); | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 14:56:04 +05:30
										 |  |  | static void esp_pthread_cfg_key_destructor(void *value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     free(value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-05 20:37:31 +03:00
										 |  |  | esp_err_t esp_pthread_init(void) | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-25 14:56:04 +05:30
										 |  |  |     if (pthread_key_create(&s_pthread_cfg_key, esp_pthread_cfg_key_destructor) != 0) { | 
					
						
							|  |  |  |         return ESP_ERR_NO_MEM; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     s_threads_mux = xSemaphoreCreateMutex(); | 
					
						
							|  |  |  |     if (s_threads_mux == NULL) { | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |         pthread_key_delete(s_pthread_cfg_key); | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |         return ESP_ERR_NO_MEM; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return ESP_OK; | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-14 11:43:32 +03:00
										 |  |  | static void *pthread_list_find_item(void *(*item_check)(esp_pthread_t *, void *arg), void *check_arg) | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-11-14 11:43:32 +03:00
										 |  |  |     esp_pthread_t *it; | 
					
						
							|  |  |  |     SLIST_FOREACH(it, &s_threads_list, list_node) { | 
					
						
							|  |  |  |         void *val = item_check(it, check_arg); | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |         if (val) { | 
					
						
							|  |  |  |             return val; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-14 11:43:32 +03:00
										 |  |  | static void *pthread_get_handle_by_desc(esp_pthread_t *item, void *desc) | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-11-14 11:43:32 +03:00
										 |  |  |     if (item == desc) { | 
					
						
							|  |  |  |         return item->handle; | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     } | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-14 11:43:32 +03:00
										 |  |  | static void *pthread_get_desc_by_handle(esp_pthread_t *item, void *hnd) | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-11-14 11:43:32 +03:00
										 |  |  |     if (hnd == item->handle) { | 
					
						
							|  |  |  |         return item; | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     } | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-11-14 11:43:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | static inline TaskHandle_t pthread_find_handle(pthread_t thread) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return pthread_list_find_item(pthread_get_handle_by_desc, (void *)thread); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | static esp_pthread_t *pthread_find(TaskHandle_t task_handle) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-11-14 11:43:32 +03:00
										 |  |  |     return pthread_list_find_item(pthread_get_desc_by_handle, task_handle); | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  | static void pthread_delete(esp_pthread_t *pthread) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-11-14 11:43:32 +03:00
										 |  |  |     SLIST_REMOVE(&s_threads_list, pthread, esp_pthread_entry, list_node); | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     free(pthread); | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 14:56:04 +05:30
										 |  |  | /* Call this function to configure pthread stacks in Pthreads */ | 
					
						
							|  |  |  | esp_err_t esp_pthread_set_cfg(const esp_pthread_cfg_t *cfg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |     if (cfg->stack_size < PTHREAD_STACK_MIN) { | 
					
						
							|  |  |  |         return ESP_ERR_INVALID_ARG; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 14:56:04 +05:30
										 |  |  |     /* If a value is already set, update that value */ | 
					
						
							|  |  |  |     esp_pthread_cfg_t *p = pthread_getspecific(s_pthread_cfg_key); | 
					
						
							|  |  |  |     if (!p) { | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |         p = malloc(sizeof(esp_pthread_cfg_t)); | 
					
						
							|  |  |  |         if (!p) { | 
					
						
							|  |  |  |             return ESP_ERR_NO_MEM; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-02-25 14:56:04 +05:30
										 |  |  |     } | 
					
						
							|  |  |  |     *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) { | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |         *p = *cfg; | 
					
						
							|  |  |  |         return ESP_OK; | 
					
						
							| 
									
										
										
										
											2018-02-25 14:56:04 +05:30
										 |  |  |     } | 
					
						
							|  |  |  |     memset(p, 0, sizeof(*p)); | 
					
						
							|  |  |  |     return ESP_ERR_NOT_FOUND; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-16 16:33:30 +07:00
										 |  |  | static int get_default_pthread_core(void) | 
					
						
							| 
									
										
										
										
											2018-11-28 20:40:32 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-07-28 11:22:51 +02:00
										 |  |  |     return CONFIG_PTHREAD_TASK_CORE_DEFAULT == -1 ? tskNO_AFFINITY : CONFIG_PTHREAD_TASK_CORE_DEFAULT; | 
					
						
							| 
									
										
										
										
											2018-11-28 20:40:32 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-16 16:33:30 +07:00
										 |  |  | esp_pthread_cfg_t esp_pthread_get_default_config(void) | 
					
						
							| 
									
										
										
										
											2018-11-28 20:40:32 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     esp_pthread_cfg_t cfg = { | 
					
						
							| 
									
										
										
										
											2019-07-28 11:22:51 +02:00
										 |  |  |         .stack_size = CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT, | 
					
						
							|  |  |  |         .prio = CONFIG_PTHREAD_TASK_PRIO_DEFAULT, | 
					
						
							| 
									
										
										
										
											2018-11-28 20:40:32 +01:00
										 |  |  |         .inherit_cfg = false, | 
					
						
							|  |  |  |         .thread_name = NULL, | 
					
						
							|  |  |  |         .pin_to_core = get_default_pthread_core() | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return cfg; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | static void pthread_task_func(void *arg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |     void *rval = NULL; | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     esp_pthread_task_arg_t *task_arg = (esp_pthread_task_arg_t *)arg; | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     ESP_LOGV(TAG, "%s ENTER %p", __FUNCTION__, task_arg->func); | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     // wait for start
 | 
					
						
							|  |  |  |     xTaskNotifyWait(0, 0, NULL, portMAX_DELAY); | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 14:56:04 +05:30
										 |  |  |     if (task_arg->cfg.inherit_cfg) { | 
					
						
							| 
									
										
										
										
											2018-11-28 20:40:32 +01:00
										 |  |  |         /* If inherit option is set, then do a set_cfg() ourselves for future forks,
 | 
					
						
							|  |  |  |         but first set thread_name to NULL to enable inheritance of the name too. | 
					
						
							|  |  |  |         (This also to prevents dangling pointers to name of tasks that might | 
					
						
							|  |  |  |         possibly have been deleted when we use the configuration).*/ | 
					
						
							|  |  |  |         esp_pthread_cfg_t *cfg = &task_arg->cfg; | 
					
						
							|  |  |  |         cfg->thread_name = NULL; | 
					
						
							|  |  |  |         esp_pthread_set_cfg(cfg); | 
					
						
							| 
									
										
										
										
											2018-02-25 14:56:04 +05:30
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     ESP_LOGV(TAG, "%s START %p", __FUNCTION__, task_arg->func); | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |     rval = task_arg->func(task_arg->arg); | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     ESP_LOGV(TAG, "%s END %p", __FUNCTION__, task_arg->func); | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |     pthread_exit(rval); | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     ESP_LOGV(TAG, "%s EXIT", __FUNCTION__); | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int pthread_create(pthread_t *thread, const pthread_attr_t *attr, | 
					
						
							|  |  |  |                    void *(*start_routine) (void *), void *arg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     TaskHandle_t xHandle = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ESP_LOGV(TAG, "%s", __FUNCTION__); | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |     esp_pthread_task_arg_t *task_arg = calloc(1, sizeof(esp_pthread_task_arg_t)); | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     if (task_arg == NULL) { | 
					
						
							|  |  |  |         ESP_LOGE(TAG, "Failed to allocate task args!"); | 
					
						
							|  |  |  |         return ENOMEM; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  |     esp_pthread_t *pthread = calloc(1, sizeof(esp_pthread_t)); | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     if (pthread == NULL) { | 
					
						
							|  |  |  |         ESP_LOGE(TAG, "Failed to allocate pthread data!"); | 
					
						
							|  |  |  |         free(task_arg); | 
					
						
							|  |  |  |         return ENOMEM; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-28 11:22:51 +02:00
										 |  |  |     uint32_t stack_size = CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT; | 
					
						
							|  |  |  |     BaseType_t prio = CONFIG_PTHREAD_TASK_PRIO_DEFAULT; | 
					
						
							| 
									
										
										
										
											2018-11-28 20:40:32 +01:00
										 |  |  |     BaseType_t core_id = get_default_pthread_core(); | 
					
						
							| 
									
										
										
										
											2019-07-28 11:22:51 +02:00
										 |  |  |     const char *task_name = CONFIG_PTHREAD_TASK_NAME_DEFAULT; | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 14:56:04 +05:30
										 |  |  |     esp_pthread_cfg_t *pthread_cfg = pthread_getspecific(s_pthread_cfg_key); | 
					
						
							|  |  |  |     if (pthread_cfg) { | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |         if (pthread_cfg->stack_size) { | 
					
						
							|  |  |  |             stack_size = pthread_cfg->stack_size; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (pthread_cfg->prio && pthread_cfg->prio < configMAX_PRIORITIES) { | 
					
						
							|  |  |  |             prio = pthread_cfg->prio; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-11-28 20:40:32 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (pthread_cfg->inherit_cfg) { | 
					
						
							|  |  |  |             if (pthread_cfg->thread_name == NULL) { | 
					
						
							|  |  |  |                 // Inherit task name from current task.
 | 
					
						
							| 
									
										
										
										
											2022-02-08 17:39:38 +08:00
										 |  |  |                 task_name = pcTaskGetName(NULL); | 
					
						
							| 
									
										
										
										
											2018-11-28 20:40:32 +01:00
										 |  |  |             } else { | 
					
						
							|  |  |  |                 // Inheriting, but new task name.
 | 
					
						
							|  |  |  |                 task_name = pthread_cfg->thread_name; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else if (pthread_cfg->thread_name == NULL) { | 
					
						
							| 
									
										
										
										
											2019-07-28 11:22:51 +02:00
										 |  |  |             task_name = CONFIG_PTHREAD_TASK_NAME_DEFAULT; | 
					
						
							| 
									
										
										
										
											2018-11-28 20:40:32 +01:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             task_name = pthread_cfg->thread_name; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (pthread_cfg->pin_to_core >= 0 && pthread_cfg->pin_to_core < portNUM_PROCESSORS) { | 
					
						
							|  |  |  |             core_id = pthread_cfg->pin_to_core; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |         task_arg->cfg = *pthread_cfg; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (attr) { | 
					
						
							|  |  |  |         /* Overwrite attributes */ | 
					
						
							|  |  |  |         stack_size = attr->stacksize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch (attr->detachstate) { | 
					
						
							|  |  |  |         case PTHREAD_CREATE_DETACHED: | 
					
						
							|  |  |  |             pthread->detached = true; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case PTHREAD_CREATE_JOINABLE: | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             pthread->detached = false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     task_arg->func = start_routine; | 
					
						
							|  |  |  |     task_arg->arg = arg; | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |     pthread->task_arg = task_arg; | 
					
						
							| 
									
										
										
										
											2018-11-28 20:40:32 +01:00
										 |  |  |     BaseType_t res = xTaskCreatePinnedToCore(&pthread_task_func, | 
					
						
							|  |  |  |                                              task_name, | 
					
						
							| 
									
										
										
										
											2019-02-26 16:55:20 +01:00
										 |  |  |                                              // stack_size is in bytes. This transformation ensures that the units are
 | 
					
						
							|  |  |  |                                              // transformed to the units used in FreeRTOS.
 | 
					
						
							|  |  |  |                                              // Note: float division of ceil(m / n) ==
 | 
					
						
							|  |  |  |                                              //       integer division of (m + n - 1) / n
 | 
					
						
							|  |  |  |                                              (stack_size + sizeof(StackType_t) - 1) / sizeof(StackType_t), | 
					
						
							| 
									
										
										
										
											2018-11-28 20:40:32 +01:00
										 |  |  |                                              task_arg, | 
					
						
							|  |  |  |                                              prio, | 
					
						
							|  |  |  |                                              &xHandle, | 
					
						
							|  |  |  |                                              core_id); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (res != pdPASS) { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |         ESP_LOGE(TAG, "Failed to create task!"); | 
					
						
							|  |  |  |         free(pthread); | 
					
						
							|  |  |  |         free(task_arg); | 
					
						
							|  |  |  |         if (res == errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY) { | 
					
						
							|  |  |  |             return ENOMEM; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             return EAGAIN; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-11-14 11:43:32 +03:00
										 |  |  |     pthread->handle = xHandle; | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  |     if (xSemaphoreTake(s_threads_mux, portMAX_DELAY) != pdTRUE) { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |         assert(false && "Failed to lock threads list!"); | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-11-14 11:43:32 +03:00
										 |  |  |     SLIST_INSERT_HEAD(&s_threads_list, pthread, list_node); | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  |     xSemaphoreGive(s_threads_mux); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     // start task
 | 
					
						
							|  |  |  |     xTaskNotify(xHandle, 0, eNoAction); | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     *thread = (pthread_t)pthread; // pointer value fit into pthread_t (uint32_t)
 | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 21:49:57 +01:00
										 |  |  |     ESP_LOGV(TAG, "Created task %"PRIx32, (uint32_t)xHandle); | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int pthread_join(pthread_t thread, void **retval) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     esp_pthread_t *pthread = (esp_pthread_t *)thread; | 
					
						
							|  |  |  |     int ret = 0; | 
					
						
							| 
									
										
										
										
											2017-09-28 17:55:17 +03:00
										 |  |  |     bool wait = false; | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |     void *child_task_retval = 0; | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     ESP_LOGV(TAG, "%s %p", __FUNCTION__, pthread); | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     // find task
 | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  |     if (xSemaphoreTake(s_threads_mux, portMAX_DELAY) != pdTRUE) { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |         assert(false && "Failed to lock threads list!"); | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  |     } | 
					
						
							|  |  |  |     TaskHandle_t handle = pthread_find_handle(thread); | 
					
						
							|  |  |  |     if (!handle) { | 
					
						
							| 
									
										
										
										
											2017-09-04 21:46:16 +03:00
										 |  |  |         // not found
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |         ret = ESRCH; | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |     } else if (pthread->detached) { | 
					
						
							|  |  |  |         // Thread is detached
 | 
					
						
							|  |  |  |         ret = EDEADLK; | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  |     } else if (pthread->join_task) { | 
					
						
							| 
									
										
										
										
											2017-09-04 21:46:16 +03:00
										 |  |  |         // already have waiting task to join
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |         ret = EINVAL; | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  |     } else if (handle == xTaskGetCurrentTaskHandle()) { | 
					
						
							| 
									
										
										
										
											2017-09-04 21:46:16 +03:00
										 |  |  |         // join to self not allowed
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |         ret = EDEADLK; | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |         esp_pthread_t *cur_pthread = pthread_find(xTaskGetCurrentTaskHandle()); | 
					
						
							|  |  |  |         if (cur_pthread && cur_pthread->join_task == handle) { | 
					
						
							| 
									
										
										
										
											2017-09-04 21:46:16 +03:00
										 |  |  |             // join to each other not allowed
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |             ret = EDEADLK; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             if (pthread->state == PTHREAD_TASK_STATE_RUN) { | 
					
						
							|  |  |  |                 pthread->join_task = xTaskGetCurrentTaskHandle(); | 
					
						
							| 
									
										
										
										
											2017-09-28 17:55:17 +03:00
										 |  |  |                 wait = true; | 
					
						
							| 
									
										
										
										
											2021-05-05 14:12:13 +10:00
										 |  |  |             } else { // thread has exited and task is already suspended, or about to be suspended
 | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |                 child_task_retval = pthread->retval; | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |                 pthread_delete(pthread); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  |     xSemaphoreGive(s_threads_mux); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |     if (ret == 0) { | 
					
						
							|  |  |  |         if (wait) { | 
					
						
							|  |  |  |             xTaskNotifyWait(0, 0, NULL, portMAX_DELAY); | 
					
						
							|  |  |  |             if (xSemaphoreTake(s_threads_mux, portMAX_DELAY) != pdTRUE) { | 
					
						
							|  |  |  |                 assert(false && "Failed to lock threads list!"); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             child_task_retval = pthread->retval; | 
					
						
							|  |  |  |             pthread_delete(pthread); | 
					
						
							|  |  |  |             xSemaphoreGive(s_threads_mux); | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-10-31 10:02:03 +01:00
										 |  |  |         /* clean up thread local storage before task deletion */ | 
					
						
							|  |  |  |         pthread_internal_local_storage_destructor_callback(handle); | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |         vTaskDelete(handle); | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  |     if (retval) { | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |         *retval = child_task_retval; | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     ESP_LOGV(TAG, "%s %p EXIT %d", __FUNCTION__, pthread, ret); | 
					
						
							|  |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int pthread_detach(pthread_t thread) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     esp_pthread_t *pthread = (esp_pthread_t *)thread; | 
					
						
							|  |  |  |     int ret = 0; | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (xSemaphoreTake(s_threads_mux, portMAX_DELAY) != pdTRUE) { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |         assert(false && "Failed to lock threads list!"); | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  |     } | 
					
						
							|  |  |  |     TaskHandle_t handle = pthread_find_handle(thread); | 
					
						
							|  |  |  |     if (!handle) { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |         ret = ESRCH; | 
					
						
							| 
									
										
										
										
											2018-12-27 18:32:14 +05:30
										 |  |  |     } else if (pthread->detached) { | 
					
						
							|  |  |  |         // already detached
 | 
					
						
							|  |  |  |         ret = EINVAL; | 
					
						
							|  |  |  |     } else if (pthread->join_task) { | 
					
						
							|  |  |  |         // already have waiting task to join
 | 
					
						
							|  |  |  |         ret = EINVAL; | 
					
						
							|  |  |  |     } else if (pthread->state == PTHREAD_TASK_STATE_RUN) { | 
					
						
							|  |  |  |         // pthread still running
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |         pthread->detached = true; | 
					
						
							| 
									
										
										
										
											2018-12-27 18:32:14 +05:30
										 |  |  |     } else { | 
					
						
							|  |  |  |         // pthread already stopped
 | 
					
						
							|  |  |  |         pthread_delete(pthread); | 
					
						
							| 
									
										
										
										
											2022-10-31 10:02:03 +01:00
										 |  |  |         /* clean up thread local storage before task deletion */ | 
					
						
							|  |  |  |         pthread_internal_local_storage_destructor_callback(handle); | 
					
						
							| 
									
										
										
										
											2018-12-27 18:32:14 +05:30
										 |  |  |         vTaskDelete(handle); | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  |     xSemaphoreGive(s_threads_mux); | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     ESP_LOGV(TAG, "%s %p EXIT %d", __FUNCTION__, pthread, ret); | 
					
						
							|  |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  | void pthread_exit(void *value_ptr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     bool detached = false; | 
					
						
							| 
									
										
										
										
											2022-10-31 10:02:03 +01:00
										 |  |  |     /* clean up thread local storage before task deletion */ | 
					
						
							|  |  |  |     pthread_internal_local_storage_destructor_callback(NULL); | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  |     if (xSemaphoreTake(s_threads_mux, portMAX_DELAY) != pdTRUE) { | 
					
						
							|  |  |  |         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!"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (pthread->task_arg) { | 
					
						
							|  |  |  |         free(pthread->task_arg); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (pthread->detached) { | 
					
						
							|  |  |  |         // auto-free for detached threads
 | 
					
						
							|  |  |  |         pthread_delete(pthread); | 
					
						
							|  |  |  |         detached = true; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         // Set return value
 | 
					
						
							|  |  |  |         pthread->retval = value_ptr; | 
					
						
							|  |  |  |         // 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; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-19 15:51:40 +08:00
										 |  |  |     ESP_LOGD(TAG, "Task stk_wm = %d", (int)uxTaskGetStackHighWaterMark(NULL)); | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-05 14:12:13 +10:00
										 |  |  |     xSemaphoreGive(s_threads_mux); | 
					
						
							|  |  |  |     // note: if this thread is joinable then after giving back s_threads_mux
 | 
					
						
							|  |  |  |     // this task could be deleted at any time, so don't take another lock or
 | 
					
						
							|  |  |  |     // do anything that might lock (such as printing to stdout)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |     if (detached) { | 
					
						
							|  |  |  |         vTaskDelete(NULL); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         vTaskSuspend(NULL); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-28 19:22:37 +08:00
										 |  |  |     // Should never be reached
 | 
					
						
							|  |  |  |     abort(); | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | int pthread_cancel(pthread_t thread) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-09-04 21:46:16 +03:00
										 |  |  |     ESP_LOGE(TAG, "%s: not supported!", __FUNCTION__); | 
					
						
							|  |  |  |     return ENOSYS; | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | int sched_yield( void ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     vTaskDelay(0); | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | pthread_t pthread_self(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  |     if (xSemaphoreTake(s_threads_mux, portMAX_DELAY) != pdTRUE) { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |         assert(false && "Failed to lock threads list!"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     esp_pthread_t *pthread = pthread_find(xTaskGetCurrentTaskHandle()); | 
					
						
							|  |  |  |     if (!pthread) { | 
					
						
							|  |  |  |         assert(false && "Failed to find current thread ID!"); | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  |     } | 
					
						
							|  |  |  |     xSemaphoreGive(s_threads_mux); | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     return (pthread_t)pthread; | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int pthread_equal(pthread_t t1, pthread_t t2) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     return t1 == t2 ? 1 : 0; | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /***************** ONCE ******************/ | 
					
						
							|  |  |  | int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     if (once_control == NULL || init_routine == NULL || !once_control->is_initialized) { | 
					
						
							|  |  |  |         ESP_LOGE(TAG, "%s: Invalid args!", __FUNCTION__); | 
					
						
							|  |  |  |         return EINVAL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-03 14:49:04 +05:30
										 |  |  |     // Check if compare and set was successful
 | 
					
						
							| 
									
										
										
										
											2022-07-21 19:14:41 +08:00
										 |  |  |     if (esp_cpu_compare_and_set((volatile uint32_t *)&once_control->init_executed, 0, 1)) { | 
					
						
							| 
									
										
										
										
											2017-11-03 14:49:04 +05:30
										 |  |  |         ESP_LOGV(TAG, "%s: call init_routine %p", __FUNCTION__, once_control); | 
					
						
							|  |  |  |         init_routine(); | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /***************** MUTEX ******************/ | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  | static int mutexattr_check(const pthread_mutexattr_t *attr) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |     if (attr->type != PTHREAD_MUTEX_NORMAL && | 
					
						
							|  |  |  |         attr->type != PTHREAD_MUTEX_RECURSIVE && | 
					
						
							|  |  |  |         attr->type != PTHREAD_MUTEX_ERRORCHECK) { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |         return EINVAL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     int type = PTHREAD_MUTEX_NORMAL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!mutex) { | 
					
						
							|  |  |  |         return EINVAL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (attr) { | 
					
						
							|  |  |  |         if (!attr->is_initialized) { | 
					
						
							|  |  |  |             return EINVAL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         int res = mutexattr_check(attr); | 
					
						
							|  |  |  |         if (res) { | 
					
						
							|  |  |  |             return res; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         type = attr->type; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     esp_pthread_mutex_t *mux = (esp_pthread_mutex_t *)malloc(sizeof(esp_pthread_mutex_t)); | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  |     if (!mux) { | 
					
						
							|  |  |  |         return ENOMEM; | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     } | 
					
						
							|  |  |  |     mux->type = type; | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     if (mux->type == PTHREAD_MUTEX_RECURSIVE) { | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  |         mux->sem = xSemaphoreCreateRecursiveMutex(); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         mux->sem = xSemaphoreCreateMutex(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!mux->sem) { | 
					
						
							|  |  |  |         free(mux); | 
					
						
							|  |  |  |         return EAGAIN; | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     *mutex = (pthread_mutex_t)mux; // pointer value fit into pthread_mutex_t (uint32_t)
 | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | int pthread_mutex_destroy(pthread_mutex_t *mutex) | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     esp_pthread_mutex_t *mux; | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     ESP_LOGV(TAG, "%s %p", __FUNCTION__, mutex); | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     if (!mutex) { | 
					
						
							|  |  |  |         return EINVAL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-04-23 10:01:37 +10:00
										 |  |  |     if ((intptr_t) *mutex == PTHREAD_MUTEX_INITIALIZER) { | 
					
						
							|  |  |  |         return 0; // Static mutex was never initialized
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     mux = (esp_pthread_mutex_t *)*mutex; | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |     if (!mux) { | 
					
						
							|  |  |  |         return EINVAL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // check if mux is busy
 | 
					
						
							|  |  |  |     int res = pthread_mutex_lock_internal(mux, 0); | 
					
						
							|  |  |  |     if (res == EBUSY) { | 
					
						
							|  |  |  |         return EBUSY; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-19 17:42:49 +08:00
										 |  |  |     if (mux->type == PTHREAD_MUTEX_RECURSIVE) { | 
					
						
							|  |  |  |         res = xSemaphoreGiveRecursive(mux->sem); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         res = xSemaphoreGive(mux->sem); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (res != pdTRUE) { | 
					
						
							|  |  |  |         assert(false && "Failed to release mutex!"); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     vSemaphoreDelete(mux->sem); | 
					
						
							|  |  |  |     free(mux); | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-12 18:31:32 +08:00
										 |  |  | static int pthread_mutex_lock_internal(esp_pthread_mutex_t *mux, TickType_t tmo) | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |     if (!mux) { | 
					
						
							|  |  |  |         return EINVAL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((mux->type == PTHREAD_MUTEX_ERRORCHECK) && | 
					
						
							|  |  |  |         (xSemaphoreGetMutexHolder(mux->sem) == xTaskGetCurrentTaskHandle())) { | 
					
						
							|  |  |  |         return EDEADLK; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  |     if (mux->type == PTHREAD_MUTEX_RECURSIVE) { | 
					
						
							|  |  |  |         if (xSemaphoreTakeRecursive(mux->sem, tmo) != pdTRUE) { | 
					
						
							|  |  |  |             return EBUSY; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         if (xSemaphoreTake(mux->sem, tmo) != pdTRUE) { | 
					
						
							|  |  |  |             return EBUSY; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  | static int pthread_mutex_init_if_static(pthread_mutex_t *mutex) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-09-01 12:31:04 +08:00
										 |  |  |     int res = 0; | 
					
						
							|  |  |  |     if ((intptr_t) *mutex == PTHREAD_MUTEX_INITIALIZER) { | 
					
						
							| 
									
										
										
										
											2021-04-23 10:01:37 +10:00
										 |  |  |         portENTER_CRITICAL(&pthread_lazy_init_lock); | 
					
						
							| 
									
										
										
										
											2017-09-01 12:31:04 +08:00
										 |  |  |         if ((intptr_t) *mutex == PTHREAD_MUTEX_INITIALIZER) { | 
					
						
							|  |  |  |             res = pthread_mutex_init(mutex, NULL); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-04-23 10:01:37 +10:00
										 |  |  |         portEXIT_CRITICAL(&pthread_lazy_init_lock); | 
					
						
							| 
									
										
										
										
											2017-09-01 12:31:04 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-12 18:31:32 +08:00
										 |  |  | int pthread_mutex_lock(pthread_mutex_t *mutex) | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     if (!mutex) { | 
					
						
							|  |  |  |         return EINVAL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-09-01 12:31:04 +08:00
										 |  |  |     int res = pthread_mutex_init_if_static(mutex); | 
					
						
							|  |  |  |     if (res != 0) { | 
					
						
							|  |  |  |         return res; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  |     return pthread_mutex_lock_internal((esp_pthread_mutex_t *)*mutex, portMAX_DELAY); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-12 18:31:32 +08:00
										 |  |  | int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *timeout) | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  | { | 
					
						
							|  |  |  |     if (!mutex) { | 
					
						
							|  |  |  |         return EINVAL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     int res = pthread_mutex_init_if_static(mutex); | 
					
						
							|  |  |  |     if (res != 0) { | 
					
						
							|  |  |  |         return res; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     struct timespec currtime; | 
					
						
							|  |  |  |     clock_gettime(CLOCK_REALTIME, &currtime); | 
					
						
							|  |  |  |     TickType_t tmo = ((timeout->tv_sec - currtime.tv_sec)*1000 + | 
					
						
							|  |  |  |                      (timeout->tv_nsec - currtime.tv_nsec)/1000000)/portTICK_PERIOD_MS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     res = pthread_mutex_lock_internal((esp_pthread_mutex_t *)*mutex, tmo); | 
					
						
							|  |  |  |     if (res == EBUSY) { | 
					
						
							|  |  |  |         return ETIMEDOUT; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-12 18:31:32 +08:00
										 |  |  | int pthread_mutex_trylock(pthread_mutex_t *mutex) | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     if (!mutex) { | 
					
						
							|  |  |  |         return EINVAL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-09-01 12:31:04 +08:00
										 |  |  |     int res = pthread_mutex_init_if_static(mutex); | 
					
						
							|  |  |  |     if (res != 0) { | 
					
						
							|  |  |  |         return res; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  |     return pthread_mutex_lock_internal((esp_pthread_mutex_t *)*mutex, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-12 18:31:32 +08:00
										 |  |  | int pthread_mutex_unlock(pthread_mutex_t *mutex) | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     esp_pthread_mutex_t *mux; | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     if (!mutex) { | 
					
						
							|  |  |  |         return EINVAL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     mux = (esp_pthread_mutex_t *)*mutex; | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |     if (!mux) { | 
					
						
							|  |  |  |         return EINVAL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (((mux->type == PTHREAD_MUTEX_RECURSIVE) || | 
					
						
							|  |  |  |         (mux->type == PTHREAD_MUTEX_ERRORCHECK)) && | 
					
						
							|  |  |  |         (xSemaphoreGetMutexHolder(mux->sem) != xTaskGetCurrentTaskHandle())) { | 
					
						
							|  |  |  |         return EPERM; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |     int ret; | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     if (mux->type == PTHREAD_MUTEX_RECURSIVE) { | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |         ret = xSemaphoreGiveRecursive(mux->sem); | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |         ret = xSemaphoreGive(mux->sem); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (ret != pdTRUE) { | 
					
						
							|  |  |  |         assert(false && "Failed to unlock mutex!"); | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2017-08-24 02:53:20 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  | int pthread_mutexattr_init(pthread_mutexattr_t *attr) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     if (!attr) { | 
					
						
							|  |  |  |         return EINVAL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-04-23 10:02:08 +10:00
										 |  |  |     memset(attr, 0, sizeof(*attr)); | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     attr->type = PTHREAD_MUTEX_NORMAL; | 
					
						
							|  |  |  |     attr->is_initialized = 1; | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int pthread_mutexattr_destroy(pthread_mutexattr_t *attr) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     if (!attr) { | 
					
						
							|  |  |  |         return EINVAL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     attr->is_initialized = 0; | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |     if (!attr) { | 
					
						
							|  |  |  |         return EINVAL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     *type = attr->type; | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2017-08-25 21:24:17 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |     if (!attr) { | 
					
						
							|  |  |  |         return EINVAL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     pthread_mutexattr_t tmp_attr = {.type = type}; | 
					
						
							|  |  |  |     int res = mutexattr_check(&tmp_attr); | 
					
						
							| 
									
										
										
										
											2017-09-04 21:46:16 +03:00
										 |  |  |     if (!res) { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:18:14 +03:00
										 |  |  |         attr->type = type; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return res; | 
					
						
							| 
									
										
										
										
											2017-08-24 22:52:49 +03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | /***************** ATTRIBUTES ******************/ | 
					
						
							|  |  |  | int pthread_attr_init(pthread_attr_t *attr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (attr) { | 
					
						
							|  |  |  |         /* Nothing to allocate. Set everything to default */ | 
					
						
							| 
									
										
										
										
											2021-04-23 10:02:08 +10:00
										 |  |  |         memset(attr, 0, sizeof(*attr)); | 
					
						
							| 
									
										
										
										
											2019-07-28 11:22:51 +02:00
										 |  |  |         attr->stacksize   = CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT; | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  |         attr->detachstate = PTHREAD_CREATE_JOINABLE; | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return EINVAL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int pthread_attr_destroy(pthread_attr_t *attr) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-04-23 10:02:08 +10:00
										 |  |  |     /* Nothing to deallocate. Reset everything to default */ | 
					
						
							|  |  |  |     return pthread_attr_init(attr); | 
					
						
							| 
									
										
										
										
											2018-08-10 16:22:27 +05:30
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (attr) { | 
					
						
							|  |  |  |         *stacksize = attr->stacksize; | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return EINVAL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (attr && !(stacksize < PTHREAD_STACK_MIN)) { | 
					
						
							|  |  |  |         attr->stacksize = stacksize; | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return EINVAL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (attr) { | 
					
						
							|  |  |  |         *detachstate = attr->detachstate; | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return EINVAL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (attr) { | 
					
						
							|  |  |  |         switch (detachstate) { | 
					
						
							|  |  |  |         case PTHREAD_CREATE_DETACHED: | 
					
						
							|  |  |  |             attr->detachstate = PTHREAD_CREATE_DETACHED; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case PTHREAD_CREATE_JOINABLE: | 
					
						
							|  |  |  |             attr->detachstate = PTHREAD_CREATE_JOINABLE; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             return EINVAL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return EINVAL; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-07-28 11:22:08 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Hook function to force linking this file */ | 
					
						
							| 
									
										
										
										
											2019-07-16 16:33:30 +07:00
										 |  |  | void pthread_include_pthread_impl(void) | 
					
						
							| 
									
										
										
										
											2019-07-28 11:22:08 +02:00
										 |  |  | { | 
					
						
							|  |  |  | } |