Commit Graph

43 Commits

Author SHA1 Message Date
Angus Gratton
0cf1e7c059 tests/thread: Rename thread_lock4 test to thread_lock4_intbig.
Relies on arbitrary precision math, so won't run on a port which
has threads & limited bigint support.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2025-07-18 00:11:34 +10:00
Angus Gratton
5d8878b582 shared/tinyusb: Only run TinyUSB on the main thread if GIL is disabled.
If GIL is disabled then there's threat of a race condition if some other
code specifically requests USB processing (i.e. to unblock stdio), while
a scheduled TinyUSB callback is already running on another thread.

Relies on the change in the parent commit, where scheduler is restricted
to main thread if GIL is disabled.

Fixes #15390 - "TinyUSB callback can't recurse" exceptions on rp2 when
using _thread module and USB serial I/O.

Adds a unit test for stdin functioning correctly in threads (fails on rp2
port without this fix).

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-09-19 13:17:01 +10:00
danicampora
935fcd1329 tests/thread: Adapt stress_aes.py to run on zephyr.
Signed-off-by: danicampora <danicampora@gmail.com>
2024-09-06 20:42:57 +10:00
Angus Gratton
337742f6c7 esp32/mpthreadport: Fix uneven GIL allocation between Python threads.
Explicitly yield each time a thread mutex is unlocked.

Key to understanding this bug is that Python threads run at equal RTOS
priority, and although ESP-IDF FreeRTOS (and I think vanilla FreeRTOS)
scheduler will round-robin equal priority tasks in the ready state it does
not make a similar guarantee for tasks moving between ready and waiting.

The pathological case of this bug is when one Python thread task is busy
(i.e. never blocks) it will hog the CPU more than expected, sometimes for
an unbounded amount of time. This happens even though it periodically
unlocks the GIL to allow another task to run.

Assume T1 is busy and T2 is blocked waiting for the GIL. T1 is executing
and hits a condition to yield execution:

1. T1 calls MP_THREAD_GIL_EXIT
2. FreeRTOS sees T2 is waiting for the GIL and moves it to the Ready list
   (but does not preempt, as T2 is same priority, so T1 keeps running).
3. T1 immediately calls MP_THREAD_GIL_ENTER and re-takes the GIL.
4. Pre-emptive context switch happens, T2 wakes up, sees GIL is not
   available, and goes on the waiting list for the GIL again.

To break this cycle step 4 must happen before step 3, but this may be a
very narrow window of time so it may not happen regularly - and
quantisation of the timing of the tick interrupt to trigger a context
switch may mean it never happens.

Yielding at the end of step 2 maximises the chance for another task to run.

Adds a test that fails on esp32 before this fix and passes afterwards.

Fixes issue #15423.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-07-23 12:33:19 +10:00
Damien George
633586a716 tests/thread/stress_aes.py: Fix logic waiting for finished threads.
Because the main thread executes `thread_entry()` it means there's an
additional one added to `count`, so the test must wait for the count to
reach `n_thread + 1`.

Signed-off-by: Damien George <damien@micropython.org>
2024-07-05 17:07:27 +10:00
Angus Gratton
cfa55b4ca1 rp2: Fix recursive atomic sections when core1 is active.
mp_thread_begin_atomic_section() is expected to be recursive (i.e. for
nested machine.disable_irq() calls, or if Python code calls disable_irq()
and then the Python runtime calls mp_handle_pending() which also enters an
atomic section to check the scheduler state).

On rp2 when not using core1 the atomic sections are recursive.

However when core1 was active (i.e. _thread) then there was a bug that
caused the core to live-lock if an atomic section recursed.

Adds a test case specifically for mutual exclusion and recursive atomic
sections when using two threads. Without this fix the test immediately
hangs on rp2.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-06-25 11:01:25 +10:00
Angus Gratton
5a778ebc37 tests/thread: Re-enable GC before stress_schedule test ends.
Otherwise GC stays disabled (not re-enabled by soft reset) and later test
runs fail with MemoryError.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-06-21 14:45:59 +10:00
Damien George
a003ac2f73 tests/thread: Add a test for accuracy of sleep within a thread.
The existing thread_sleep1.py test only tests execution, not accuracy, of
time.sleep.  Also the existing test only tests sleep(0) on targets like rp2
that can only create a single thread.

The new test in this commit checks for timing accuracy on the main thread
and one other thread when they run at the same time.

Signed-off-by: Damien George <damien@micropython.org>
2024-01-05 10:35:34 +11:00
Damien George
2265d70add tests/thread: Adjust thread tests so most are able to run on rp2 port.
The aim of this commit is to make it so that the existing thread tests can
be used to test the _thread module on the rp2 port.  The rp2 port only
allows up to one thread to be created at a time, and does not have the GIL
enabled.

The following changes have been made:
- run-tests.py skips mutation tests on rp2, because there's no GIL.
- run-tests.py skips other tests on rp2 that require more than one thread.
- The tests stop trying to start a new thread after there is an OSError,
  which indicates that the system cannot create more threads.
- Some of these tests also now run the test function on the main thread,
  not just the spawned threads.
- In some tests the output printing is adjusted so it's the same regardless
  of how many threads were spawned.
- Some time.sleep(1) are replaced with time.sleep(0) to make the tests run
  a little faster (finish sooner when the work is done).

For the most part the tests are unchanged for existing platforms like esp32
and unix.

Signed-off-by: Damien George <damien@micropython.org>
2024-01-05 10:02:27 +11:00
David Lechner
ffb43b2dd3 py/modthread: Return thread id from start_new_thread().
In CPython, `_thread.start_new_thread()` returns an ID that is the same ID
that is returned by `_thread.get_ident()`.  The current MicroPython
implementation of `_thread.start_new_thread()` always returns `None`.

This modifies the required functions to return a value. The native thread
id is returned since this can be used for interop with other functions, for
example, `pthread_kill()` on *nix. `_thread.get_ident()` is also modified
to return the native thread id so that the values match and avoids the need
for a separate `native_id` attribute.

Fixes issue #12153.

Signed-off-by: David Lechner <david@pybricks.com>
2023-09-03 18:49:18 +10:00
Jim Mussared
4216bc7d13 tests: Replace umodule with module everywhere.
This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-06-08 17:54:24 +10:00
Damien George
b1229efbd1 all: Fix spelling mistakes based on codespell check.
Signed-off-by: Damien George <damien@micropython.org>
2023-04-27 18:03:06 +10:00
Jim Mussared
8b27482692 top: Update Python formatting to black "2023 stable style".
See https://black.readthedocs.io/en/stable/the_black_code_style/index.html

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-02-02 12:51:03 +11:00
Damien George
5f650b7b7a tests/thread: Use less resources for stress_aes if settrace enabled.
Signed-off-by: Damien George <damien@micropython.org>
2022-05-17 14:25:51 +10:00
Damien George
4cdcbdb753 tests/thread: Make exc1,exit1,exit2,stacksize1,start1 tests run on rp2.
The RP2040 has 2 cores and supports running at most 2 Python threads (the
main one plus another), and will raise OSError if a thread cannot be
created because core1 is already in use.  This commit adjusts some thread
tests to be robust against such OSError's.  These tests now pass on rp2
boards.

Signed-off-by: Damien George <damien@micropython.org>
2021-05-10 13:07:16 +10:00
Damien George
b6b39bff47 py/gc: Make gc_lock_depth have a count per thread.
This commit makes gc_lock_depth have one counter per thread, instead of one
global counter.  This makes threads properly independent with respect to
the GC, in particular threads can now independently lock the GC for
themselves without locking it for other threads.  It also means a given
thread can run a hard IRQ without temporarily locking the GC for all other
threads and potentially making them have MemoryError exceptions at random
locations (this really only occurs on MCUs with multiple cores and no GIL,
eg on the rp2 port).

The commit also removes protection of the GC lock/unlock functions, which
is no longer needed when the counter is per thread (and this also fixes the
cas where a hard IRQ calling gc_lock() may stall waiting for the mutex).

It also puts the check for `gc_lock_depth > 0` outside the GC mutex in
gc_alloc, gc_realloc and gc_free, to potentially prevent a hard IRQ from
waiting on a mutex if it does attempt to allocate heap memory (and putting
the check outside the GC mutex is now safe now that there is a
gc_lock_depth per thread).

Signed-off-by: Damien George <damien@micropython.org>
2021-05-10 13:07:16 +10:00
Damien George
7b923d6c72 tests/thread: Make stress_aes.py test run on bare-metal ports.
This is a long-running test, so make it run in reasonable time on slower,
bare-metal ports.

Signed-off-by: Damien George <damien@micropython.org>
2021-05-08 22:47:03 +10:00
Damien George
9340cfe774 tests/thread: Make stress_create.py test run on esp32.
The esp32 port needs to be idle for finished threads and their resources to
be freed up.

Signed-off-by: Damien George <damien@micropython.org>
2021-05-08 22:47:03 +10:00
Damien George
864e4ecc47 esp32/mpthreadport: Use binary semaphore instead of mutex.
So a lock can be acquired on one Python thread and then released on
another.  A test for this is added.

Signed-off-by: Damien George <damien@micropython.org>
2021-05-08 22:47:03 +10:00
Damien George
368c1a0961 tests/thread/stress_schedule.py: Assign globals before running test.
When threading is enabled without the GIL then there can be races between
the threads accessing the globals dict.  Avoid this issue by making sure
all globals variables are allocated before starting the threads.

Signed-off-by: Damien George <damien@micropython.org>
2020-10-28 00:54:30 +11:00
stijn
40ad8f1666 all: Rename "sys" module to "usys".
This is consistent with the other 'micro' modules and allows implementing
additional features in Python via e.g. micropython-lib's sys.

Note this is a breaking change (not backwards compatible) for ports which
do not enable weak links, as "import sys" must now be replaced with
"import usys".
2020-09-04 00:10:24 +10:00
yangfl
138a28dc07 tests/thread/thread_stacksize1.py: Increase stack size for CPython.
On arm64 with CPython:

  >>> _thread.stack_size(32*1024)
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
  ValueError: size not valid: 32768 bytes

So increase the CPython value in the test to 512k so it runs on more
systems (on modern Linux the default stack size is usually 8MB).
2020-05-05 00:43:24 +10:00
Jim Mussared
8470cd0be9 py/scheduler: Add assert that scheduler is locked when unlocking.
And add a test that shows how this can happen when multiple threads are
accessing the scheduler, which fails if atomic sections are not used.
2020-04-13 21:55:47 +10:00
David Lechner
3dc324d3f1 tests: Format all Python code with black, except tests in basics subdir.
This adds the Python files in the tests/ directory to be formatted with
./tools/codeformat.py.  The basics/ subdirectory is excluded for now so we
aren't changing too much at once.

In a few places `# fmt: off`/`# fmt: on` was used where the code had
special formatting for readability or where the test was actually testing
the specific formatting.
2020-03-30 13:21:58 +11:00
Damien George
e374cfff80 py/modthread: Raise RuntimeError in release() if lock is not acquired. 2017-06-14 14:43:50 +10:00
Ville Skyttä
ca16c38210 various: Spelling fixes 2017-05-29 11:36:05 +03:00
Damien George
06a12ada48 tests/thread: Add stress-test for creating many threads. 2017-02-15 11:12:37 +11:00
Damien George
2847d7431d tests/thread: Replace busy waiting loops with a loop that sleeps.
Depending on the thread scheduler, a busy-wait loop can hog the CPU and
make the tests very slow.  So convert such loops to loops that have an
explicit sleep, allowing the worker threads to do their job.
2017-02-15 11:12:37 +11:00
Damien George
28185bb81b tests/thread: Fix stack size test so tests run reliably on baremetal. 2017-02-01 17:21:35 +11:00
Damien George
bebb3a6160 tests/thread: Make thread_exc2 runable on baremetal. 2017-01-31 13:59:20 +11:00
Rami Ali
f397e1fdf0 tests/thread: Improve modthread.c test coverage. 2016-12-29 13:27:50 +11:00
Damien George
8b9ddf4031 tests/thread: Allow some tests to run on ports with not much heap. 2016-06-28 11:28:52 +01:00
Damien George
63d05228a3 tests/thread: Allow thread_sleep1 to run without floating point. 2016-06-28 11:28:52 +01:00
Damien George
15e68277c1 tests/thread: Make sure that thread tests don't rely on floating point. 2016-06-28 11:28:52 +01:00
Damien George
5b7789d519 tests/thread: Make stack-size test run correctly and reliable on uPy. 2016-06-28 11:28:52 +01:00
Damien George
b7274e91bc tests/thread: Add test for concurrent mutating of user instance. 2016-06-28 11:28:50 +01:00
Damien George
2e4cdae4fd tests/thread: Add test for concurrent interning of strings.
Qstr code accesses global state and needs to be made thread safe.
2016-06-28 11:28:50 +01:00
Damien George
094a0dd11a tests/thread: Add tests that mutate shared objects.
Tests concurrent mutating access to: list, dict, set, bytearray.
2016-06-28 11:28:50 +01:00
Damien George
c73cf9d931 tests/thread: Rename thread_stress_XXX.py to stress_XXX.py. 2016-06-28 11:28:50 +01:00
Damien George
dcc7c5bd89 tests/thread: Add tests for running GC within a thread, and heap stress. 2016-06-28 11:28:49 +01:00
Damien George
3545ef8bb4 tests/thread: Remove need to sleep to wait for completion in some tests.
Use a lock and a counter instead, and busy wait for all threads to
complete.  This makes test run faster and they no longer rely on the time
module.
2016-06-28 11:09:31 +01:00
Damien George
2d5ea38b49 tests: Add 3 more tests for _thread module. 2016-06-28 11:09:31 +01:00
Damien George
ed36632c6c tests: Add tests for _thread module.
Includes functionality and stress tests.
2016-06-28 11:09:31 +01:00