Skip to content

[ESP32] utime.sleep_ms does not free GIL on small intervals #5344

@nevercast

Description

@nevercast

When using multithreading on the ESP32 port, and using sleep_ms(1) to yield to another thread that may be waiting on the GIL, the sleep_ms implementation does not free the GIL when milliseconds is approximately less than 10ms. This is because there is an early break from the sleep loop that doesn't call MICROPY_EVENT_POLL_HOOK

https://github.com/micropython/micropython/blob/master/ports/esp32/mphalport.c#L120-L138

By changing the inner loop from

    for (;;) {
        uint64_t t1 = esp_timer_get_time();
        dt = t1 - t0;
        if (dt + portTICK_PERIOD_MS * 1000 >= us) {
            // doing a vTaskDelay would take us beyond requested delay time
            break;
        }
        MICROPY_EVENT_POLL_HOOK
        ulTaskNotifyTake(pdFALSE, 1);
    }

to

    for (;;) {
        MICROPY_EVENT_POLL_HOOK
        uint64_t t1 = esp_timer_get_time();
        dt = t1 - t0;
        if (dt + portTICK_PERIOD_MS * 1000 >= us) {
            // doing a vTaskDelay would take us beyond requested delay time
            break;
        }
        ulTaskNotifyTake(pdFALSE, 1);
    }

The GIL will always be freed from this thread, even if the sleep_ms duration is very small, allowing another thread to access python objects and perform work that the main thread may be waiting on.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions