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:
dongheng
2019-08-27 10:33:38 +08:00
parent 8cf028873d
commit 24e53102bf
10 changed files with 170 additions and 84 deletions

View File

@ -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

View 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__

View 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 */

View File

@ -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
}

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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>

View File

@ -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;
}