mirror of
https://github.com/espressif/ESP8266_RTOS_SDK.git
synced 2025-05-21 00:56:38 +08:00
feat(pthread): modify for ESP8266
1. remove "IRAM_ATTR" from pthread function 2. modify "critical" function 3. remove SMP function 4. add platform support
This commit is contained in:
@ -103,6 +103,8 @@ to exclude the API function. */
|
||||
#define INCLUDE_xTaskGetCurrentTaskHandle 1
|
||||
#define INCLUDE_uxTaskGetStackHighWaterMark 1
|
||||
|
||||
#define INCLUDE_xSemaphoreGetMutexHolder 1
|
||||
|
||||
/* This is the raw value as per the Cortex-M3 NVIC. Values can be 255
|
||||
(lowest) to 0 (1?) (highest). */
|
||||
#define configKERNEL_INTERRUPT_PRIORITY 255
|
||||
|
40
components/newlib/newlib/port/include/pthread.h
Normal file
40
components/newlib/newlib/port/include/pthread.h
Normal file
@ -0,0 +1,40 @@
|
||||
// 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.
|
||||
#ifndef __ESP_PLATFORM_PTHREAD_H__
|
||||
#define __ESP_PLATFORM_PTHREAD_H__
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/features.h>
|
||||
|
||||
// Remove this when GCC 5.2.0 is no longer supported
|
||||
#ifndef _POSIX_TIMEOUTS
|
||||
#define _POSIX_TIMEOUTS // For pthread_mutex_timedlock
|
||||
#endif
|
||||
|
||||
#include_next <pthread.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int pthread_condattr_getclock(const pthread_condattr_t * attr, clockid_t * clock_id);
|
||||
|
||||
int pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clock_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __ESP_PLATFORM_PTHREAD_H__
|
35
components/newlib/newlib/port/include/time.h
Normal file
35
components/newlib/newlib/port/include/time.h
Normal file
@ -0,0 +1,35 @@
|
||||
// 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.
|
||||
|
||||
|
||||
#ifndef _ESP_TIME_H
|
||||
#define _ESP_TIME_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include_next <time.h>
|
||||
|
||||
#define _POSIX_TIMERS 1
|
||||
#define CLOCK_MONOTONIC (clockid_t)4
|
||||
#define CLOCK_BOOTTIME (clockid_t)4
|
||||
|
||||
int clock_settime(clockid_t clock_id, const struct timespec *tp);
|
||||
int clock_gettime(clockid_t clock_id, struct timespec *tp);
|
||||
int clock_getres(clockid_t clock_id, struct timespec *res);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* _ESP_TIME_H */
|
@ -16,6 +16,7 @@
|
||||
#include <reent.h>
|
||||
#include <sys/times.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
#include "esp_system.h"
|
||||
#include "esp_timer.h"
|
||||
@ -106,3 +107,38 @@ unsigned int sleep(unsigned int seconds)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clock_gettime (clockid_t clock_id, struct timespec *tp)
|
||||
{
|
||||
#if defined( WITH_FRC ) || defined( WITH_RTC )
|
||||
if (tp == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
struct timeval tv;
|
||||
uint64_t monotonic_time_us = 0;
|
||||
switch (clock_id) {
|
||||
case CLOCK_REALTIME:
|
||||
_gettimeofday_r(NULL, &tv, NULL);
|
||||
tp->tv_sec = tv.tv_sec;
|
||||
tp->tv_nsec = tv.tv_usec * 1000L;
|
||||
break;
|
||||
case CLOCK_MONOTONIC:
|
||||
#if defined( WITH_FRC )
|
||||
monotonic_time_us = (uint64_t) esp_timer_get_time();
|
||||
#elif defined( WITH_RTC )
|
||||
monotonic_time_us = get_rtc_time_us();
|
||||
#endif // WITH_FRC
|
||||
tp->tv_sec = monotonic_time_us / 1000000LL;
|
||||
tp->tv_nsec = (monotonic_time_us % 1000000LL) * 1000L;
|
||||
break;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
if(CONFIG_ENABLE_PTHREAD)
|
||||
idf_component_register(SRCS "pthread.c"
|
||||
"pthread_cond_var.c"
|
||||
"pthread_local_storage.c"
|
||||
INCLUDE_DIRS include)
|
||||
INCLUDE_DIRS include
|
||||
PRIV_REQUIRES newlib)
|
||||
|
||||
if(GCC_NOT_5_2_0)
|
||||
set(extra_link_flags "-u pthread_include_pthread_impl")
|
||||
@ -16,3 +18,6 @@ endif()
|
||||
if(extra_link_flags)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "${extra_link_flags}")
|
||||
endif()
|
||||
else()
|
||||
register_component()
|
||||
endif()
|
@ -1,49 +1,37 @@
|
||||
menu "PThreads"
|
||||
|
||||
config PTHREAD_TASK_PRIO_DEFAULT
|
||||
int "Default task priority"
|
||||
range 0 255
|
||||
default 5
|
||||
help
|
||||
Priority used to create new tasks with default pthread parameters.
|
||||
config ENABLE_PTHREAD
|
||||
bool "Enable Pthread"
|
||||
help
|
||||
Enable this option and then pthread is to be used.
|
||||
|
||||
config PTHREAD_TASK_STACK_SIZE_DEFAULT
|
||||
int "Default task stack size"
|
||||
default 3072
|
||||
help
|
||||
Stack size used to create new tasks with default pthread parameters.
|
||||
config PTHREAD_TASK_PRIO_DEFAULT
|
||||
int "Default task priority"
|
||||
range 0 255
|
||||
default 5
|
||||
depends on ENABLE_PTHREAD
|
||||
help
|
||||
Priority used to create new tasks with default pthread parameters.
|
||||
|
||||
config PTHREAD_STACK_MIN
|
||||
int "Minimum allowed pthread stack size"
|
||||
default 768
|
||||
help
|
||||
Minimum allowed pthread stack size set in attributes passed to pthread_create
|
||||
config PTHREAD_TASK_STACK_SIZE_DEFAULT
|
||||
int "Default task stack size"
|
||||
default 3072
|
||||
depends on ENABLE_PTHREAD
|
||||
help
|
||||
Stack size used to create new tasks with default pthread parameters.
|
||||
|
||||
choice PTHREAD_TASK_CORE_DEFAULT
|
||||
bool "Default pthread core affinity"
|
||||
default PTHREAD_DEFAULT_CORE_NO_AFFINITY
|
||||
depends on !FREERTOS_UNICORE
|
||||
help
|
||||
The default core to which pthreads are pinned.
|
||||
config PTHREAD_STACK_MIN
|
||||
int "Minimum allowed pthread stack size"
|
||||
default 768
|
||||
depends on ENABLE_PTHREAD
|
||||
help
|
||||
Minimum allowed pthread stack size set in attributes passed to pthread_create
|
||||
|
||||
config PTHREAD_DEFAULT_CORE_NO_AFFINITY
|
||||
bool "No affinity"
|
||||
config PTHREAD_DEFAULT_CORE_0
|
||||
bool "Core 0"
|
||||
config PTHREAD_DEFAULT_CORE_1
|
||||
bool "Core 1"
|
||||
endchoice
|
||||
|
||||
config PTHREAD_TASK_CORE_DEFAULT
|
||||
int
|
||||
default -1 if PTHREAD_DEFAULT_CORE_NO_AFFINITY || FREERTOS_UNICORE
|
||||
default 0 if PTHREAD_DEFAULT_CORE_0
|
||||
default 1 if PTHREAD_DEFAULT_CORE_1
|
||||
|
||||
config PTHREAD_TASK_NAME_DEFAULT
|
||||
string "Default name of pthreads"
|
||||
default "pthread"
|
||||
help
|
||||
The default name of pthreads.
|
||||
config PTHREAD_TASK_NAME_DEFAULT
|
||||
string "Default name of pthreads"
|
||||
default "pthread"
|
||||
depends on ENABLE_PTHREAD
|
||||
help
|
||||
The default name of pthreads.
|
||||
|
||||
endmenu
|
||||
|
@ -2,6 +2,7 @@
|
||||
# Component Makefile
|
||||
#
|
||||
|
||||
ifdef CONFIG_ENABLE_PTHREAD
|
||||
COMPONENT_SRCDIRS := .
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := include
|
||||
@ -19,3 +20,6 @@ COMPONENT_ADD_LDFLAGS += -u pthread_include_pthread_impl
|
||||
COMPONENT_ADD_LDFLAGS += -u pthread_include_pthread_cond_impl
|
||||
COMPONENT_ADD_LDFLAGS += -u pthread_include_pthread_local_storage_impl
|
||||
endif # GCC_NOT_5_2_0
|
||||
else
|
||||
COMPONENT_SRCDIRS :=
|
||||
endif
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
|
||||
#include "pthread_internal.h"
|
||||
#include "esp_pthread.h"
|
||||
@ -67,13 +66,12 @@ typedef struct {
|
||||
|
||||
|
||||
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 int pthread_mutex_lock_internal(esp_pthread_mutex_t *mux, TickType_t tmo);
|
||||
|
||||
static void esp_pthread_cfg_key_destructor(void *value)
|
||||
{
|
||||
@ -170,7 +168,7 @@ esp_err_t esp_pthread_get_cfg(esp_pthread_cfg_t *p)
|
||||
|
||||
static int get_default_pthread_core(void)
|
||||
{
|
||||
return CONFIG_PTHREAD_TASK_CORE_DEFAULT == -1 ? tskNO_AFFINITY : CONFIG_PTHREAD_TASK_CORE_DEFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
esp_pthread_cfg_t esp_pthread_get_default_config(void)
|
||||
@ -235,7 +233,6 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||
|
||||
uint32_t stack_size = CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT;
|
||||
BaseType_t prio = CONFIG_PTHREAD_TASK_PRIO_DEFAULT;
|
||||
BaseType_t core_id = get_default_pthread_core();
|
||||
const char *task_name = CONFIG_PTHREAD_TASK_NAME_DEFAULT;
|
||||
|
||||
esp_pthread_cfg_t *pthread_cfg = pthread_getspecific(s_pthread_cfg_key);
|
||||
@ -261,10 +258,6 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||
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;
|
||||
}
|
||||
|
||||
task_arg->cfg = *pthread_cfg;
|
||||
}
|
||||
|
||||
@ -295,7 +288,7 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||
task_arg,
|
||||
prio,
|
||||
&xHandle,
|
||||
core_id);
|
||||
0);
|
||||
|
||||
if (res != pdPASS) {
|
||||
ESP_LOGE(TAG, "Failed to create task!");
|
||||
@ -453,7 +446,7 @@ void pthread_exit(void *value_ptr)
|
||||
}
|
||||
xSemaphoreGive(s_threads_mux);
|
||||
|
||||
ESP_LOGD(TAG, "Task stk_wm = %d", uxTaskGetStackHighWaterMark(NULL));
|
||||
ESP_LOGD(TAG, "Task stk_wm = %ld", uxTaskGetStackHighWaterMark(NULL));
|
||||
|
||||
if (detached) {
|
||||
vTaskDelete(NULL);
|
||||
@ -503,21 +496,7 @@ int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
uint32_t res = 1;
|
||||
#if defined(CONFIG_ESP32_SPIRAM_SUPPORT)
|
||||
if (esp_ptr_external_ram(once_control)) {
|
||||
uxPortCompareSetExtram((uint32_t *) &once_control->init_executed, 0, &res);
|
||||
} else {
|
||||
#endif
|
||||
uxPortCompareSet((uint32_t *) &once_control->init_executed, 0, &res);
|
||||
#if defined(CONFIG_ESP32_SPIRAM_SUPPORT)
|
||||
}
|
||||
#endif
|
||||
// Check if compare and set was successful
|
||||
if (res == 0) {
|
||||
ESP_LOGV(TAG, "%s: call init_routine %p", __FUNCTION__, once_control);
|
||||
init_routine();
|
||||
}
|
||||
once_control->init_executed = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -599,7 +578,7 @@ int pthread_mutex_destroy(pthread_mutex_t *mutex)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int IRAM_ATTR pthread_mutex_lock_internal(esp_pthread_mutex_t *mux, TickType_t tmo)
|
||||
static int pthread_mutex_lock_internal(esp_pthread_mutex_t *mux, TickType_t tmo)
|
||||
{
|
||||
if (!mux) {
|
||||
return EINVAL;
|
||||
@ -627,16 +606,16 @@ static int pthread_mutex_init_if_static(pthread_mutex_t *mutex)
|
||||
{
|
||||
int res = 0;
|
||||
if ((intptr_t) *mutex == PTHREAD_MUTEX_INITIALIZER) {
|
||||
portENTER_CRITICAL(&s_mutex_init_lock);
|
||||
portENTER_CRITICAL();
|
||||
if ((intptr_t) *mutex == PTHREAD_MUTEX_INITIALIZER) {
|
||||
res = pthread_mutex_init(mutex, NULL);
|
||||
}
|
||||
portEXIT_CRITICAL(&s_mutex_init_lock);
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int IRAM_ATTR pthread_mutex_lock(pthread_mutex_t *mutex)
|
||||
int pthread_mutex_lock(pthread_mutex_t *mutex)
|
||||
{
|
||||
if (!mutex) {
|
||||
return EINVAL;
|
||||
@ -648,7 +627,7 @@ int IRAM_ATTR pthread_mutex_lock(pthread_mutex_t *mutex)
|
||||
return pthread_mutex_lock_internal((esp_pthread_mutex_t *)*mutex, portMAX_DELAY);
|
||||
}
|
||||
|
||||
int IRAM_ATTR pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *timeout)
|
||||
int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *timeout)
|
||||
{
|
||||
if (!mutex) {
|
||||
return EINVAL;
|
||||
@ -670,7 +649,7 @@ int IRAM_ATTR pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct times
|
||||
return res;
|
||||
}
|
||||
|
||||
int IRAM_ATTR pthread_mutex_trylock(pthread_mutex_t *mutex)
|
||||
int pthread_mutex_trylock(pthread_mutex_t *mutex)
|
||||
{
|
||||
if (!mutex) {
|
||||
return EINVAL;
|
||||
@ -682,7 +661,7 @@ int IRAM_ATTR pthread_mutex_trylock(pthread_mutex_t *mutex)
|
||||
return pthread_mutex_lock_internal((esp_pthread_mutex_t *)*mutex, 0);
|
||||
}
|
||||
|
||||
int IRAM_ATTR pthread_mutex_unlock(pthread_mutex_t *mutex)
|
||||
int pthread_mutex_unlock(pthread_mutex_t *mutex)
|
||||
{
|
||||
esp_pthread_mutex_t *mux;
|
||||
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/list.h"
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <sys/time.h>
|
||||
|
@ -42,8 +42,6 @@ typedef struct key_entry_t_ {
|
||||
// List of all keys created with pthread_key_create()
|
||||
SLIST_HEAD(key_list_t, key_entry_t_) s_keys = SLIST_HEAD_INITIALIZER(s_keys);
|
||||
|
||||
static portMUX_TYPE s_keys_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
// List of all value entries associated with a thread via pthread_setspecific()
|
||||
typedef struct value_entry_t_ {
|
||||
pthread_key_t key;
|
||||
@ -62,7 +60,7 @@ int pthread_key_create(pthread_key_t *key, pthread_destructor_t destructor)
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
portENTER_CRITICAL(&s_keys_lock);
|
||||
portENTER_CRITICAL();
|
||||
|
||||
const key_entry_t *head = SLIST_FIRST(&s_keys);
|
||||
new_key->key = (head == NULL) ? 1 : (head->key + 1);
|
||||
@ -71,27 +69,27 @@ int pthread_key_create(pthread_key_t *key, pthread_destructor_t destructor)
|
||||
|
||||
SLIST_INSERT_HEAD(&s_keys, new_key, next);
|
||||
|
||||
portEXIT_CRITICAL(&s_keys_lock);
|
||||
portEXIT_CRITICAL();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static key_entry_t *find_key(pthread_key_t key)
|
||||
{
|
||||
portENTER_CRITICAL(&s_keys_lock);
|
||||
portENTER_CRITICAL();
|
||||
key_entry_t *result = NULL;;
|
||||
SLIST_FOREACH(result, &s_keys, next) {
|
||||
if(result->key == key) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL(&s_keys_lock);
|
||||
portEXIT_CRITICAL();
|
||||
return result;
|
||||
}
|
||||
|
||||
int pthread_key_delete(pthread_key_t key)
|
||||
{
|
||||
|
||||
portENTER_CRITICAL(&s_keys_lock);
|
||||
portENTER_CRITICAL();
|
||||
|
||||
/* Ideally, we would also walk all tasks' thread local storage value_list here
|
||||
and delete any values associated with this key. We do not do this...
|
||||
@ -103,7 +101,7 @@ int pthread_key_delete(pthread_key_t key)
|
||||
free(entry);
|
||||
}
|
||||
|
||||
portEXIT_CRITICAL(&s_keys_lock);
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user