esp32: Pin MicroPython tasks to a specific core.

On this port the GIL is enabled and everything works under the assumption
of the GIL, ie that a given task has exclusive access to the uPy state, and
any ISRs interrupt the current task and therefore the ISR inherits
exclusive access to the uPy state for the duration of its execution.

If the MicroPython tasks are not pinned to a specific core then an ISR may
be executed on a different core to the task, making it possible for the
main task and an ISR to execute in parallel, breaking the assumption of the
GIL.

The easiest and safest fix for this is to pin all MicroPython related code
to the same CPU core, as done by this patch.  Then any ISR that accesses
MicroPython state must be registered from a MicroPython task, to ensure it
is invoked on the same core.

See issue #4895.
This commit is contained in:
Amir Gonnen 2019-07-22 22:59:55 +03:00 committed by Damien George
parent e3e7e3a781
commit 995f9cfdfc
4 changed files with 7 additions and 5 deletions

View File

@ -151,7 +151,7 @@ soft_reset:
void app_main(void) { void app_main(void) {
nvs_flash_init(); nvs_flash_init();
xTaskCreate(mp_task, "mp_task", MP_TASK_STACK_LEN, NULL, MP_TASK_PRIORITY, &mp_main_task_handle); xTaskCreatePinnedToCore(mp_task, "mp_task", MP_TASK_STACK_LEN, NULL, MP_TASK_PRIORITY, &mp_main_task_handle, MP_TASK_COREID);
} }
void nlr_jump_fail(void *val) { void nlr_jump_fail(void *val) {

View File

@ -35,6 +35,9 @@
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
// The core that the MicroPython task(s) are pinned to
#define MP_TASK_COREID (1)
extern TaskHandle_t mp_main_task_handle; extern TaskHandle_t mp_main_task_handle;
extern ringbuf_t stdin_ringbuf; extern ringbuf_t stdin_ringbuf;

View File

@ -27,10 +27,9 @@
#include "stdio.h" #include "stdio.h"
#include "py/mpconfig.h"
#include "py/mpstate.h"
#include "py/gc.h" #include "py/gc.h"
#include "py/mpthread.h" #include "py/mpthread.h"
#include "py/mphal.h"
#include "mpthreadport.h" #include "mpthreadport.h"
#include "esp_task.h" #include "esp_task.h"
@ -130,7 +129,7 @@ void mp_thread_create_ex(void *(*entry)(void*), void *arg, size_t *stack_size, i
mp_thread_mutex_lock(&thread_mutex, 1); mp_thread_mutex_lock(&thread_mutex, 1);
// create thread // create thread
BaseType_t result = xTaskCreate(freertos_entry, name, *stack_size / sizeof(StackType_t), arg, priority, &th->id); BaseType_t result = xTaskCreatePinnedToCore(freertos_entry, name, *stack_size / sizeof(StackType_t), arg, priority, &th->id, MP_TASK_COREID);
if (result != pdPASS) { if (result != pdPASS) {
mp_thread_mutex_unlock(&thread_mutex); mp_thread_mutex_unlock(&thread_mutex);
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create thread")); nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create thread"));

View File

@ -133,7 +133,7 @@ STATIC mp_obj_t ppp_active(size_t n_args, const mp_obj_t *args) {
ppp_set_usepeerdns(self->pcb, 1); ppp_set_usepeerdns(self->pcb, 1);
pppapi_connect(self->pcb, 0); pppapi_connect(self->pcb, 0);
xTaskCreate(pppos_client_task, "ppp", 2048, self, 1, (TaskHandle_t*)&self->client_task_handle); xTaskCreatePinnedToCore(pppos_client_task, "ppp", 2048, self, 1, (TaskHandle_t*)&self->client_task_handle, MP_TASK_COREID);
self->active = true; self->active = true;
} else { } else {
if (!self->active) { if (!self->active) {