Thanks to visit codestin.com
Credit goes to github.com

Skip to content

tests/thread: Adjust thread tests so most are able to run on rp2 port. #13351

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions tests/run-tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -562,18 +562,23 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1):
skip_tests.add("cmdline/repl_sys_ps1_ps2.py")
skip_tests.add("extmod/ssl_poll.py")

# Some tests shouldn't be run on a PC
if args.target == "unix":
# unix build does not have the GIL so can't run thread mutation tests
# Skip thread mutation tests on targets that don't have the GIL.
if args.target in ("rp2", "unix"):
for t in tests:
if t.startswith("thread/mutate_"):
skip_tests.add(t)

# Skip thread tests that require many threads on targets that don't support multiple threads.
if args.target == "rp2":
skip_tests.add("thread/stress_heap.py")
skip_tests.add("thread/thread_lock2.py")
skip_tests.add("thread/thread_lock3.py")
skip_tests.add("thread/thread_shared2.py")

# Some tests shouldn't be run on pyboard
if args.target != "unix":
skip_tests.add("basics/exception_chain.py") # warning is not printed
skip_tests.add("micropython/meminfo.py") # output is very different to PC output
skip_tests.add("extmod/machine_mem.py") # raw memory access not supported

if args.target == "wipy":
skip_tests.add("misc/print_exception.py") # requires error reporting full
Expand Down Expand Up @@ -988,7 +993,7 @@ def main():
elif args.target in ("renesas-ra"):
test_dirs += ("float", "inlineasm", "renesas-ra")
elif args.target == "rp2":
test_dirs += ("float", "stress", "inlineasm")
test_dirs += ("float", "stress", "inlineasm", "thread")
elif args.target in ("esp8266", "esp32", "minimal", "nrf"):
test_dirs += ("float",)
elif args.target == "wipy":
Expand Down
13 changes: 11 additions & 2 deletions tests/thread/stress_schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

n = 0 # How many times the task successfully ran.
t = None # Start time of test, assigned here to preallocate entry in globals dict.
thread_run = True # If the thread should continue running.


def task(x):
Expand All @@ -27,7 +28,7 @@ def task(x):


def thread():
while True:
while thread_run:
try:
micropython.schedule(task, None)
except RuntimeError:
Expand All @@ -36,13 +37,21 @@ def thread():


for i in range(8):
_thread.start_new_thread(thread, ())
try:
_thread.start_new_thread(thread, ())
except OSError:
# System cannot create a new thead, so stop trying to create them.
break

# Wait up to 10 seconds for 10000 tasks to be scheduled.
t = time.ticks_ms()
while n < _NUM_TASKS and time.ticks_diff(time.ticks_ms(), t) < _TIMEOUT_MS:
pass

# Stop all threads.
thread_run = False
time.sleep_ms(20)

if n < _NUM_TASKS:
# Not all the tasks were scheduled, likely the scheduler stopped working.
print(n)
Expand Down
25 changes: 19 additions & 6 deletions tests/thread/thread_gc1.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,34 @@ def thread_entry(n):
data[i] = data[i]
gc.collect()

# print whether the data remains intact and indicate we are finished
# check whether the data remains intact and indicate we are finished
with lock:
print(list(data) == list(range(256)))
global n_finished
global n_correct, n_finished
n_correct += list(data) == list(range(256))
n_finished += 1


lock = _thread.allocate_lock()
n_thread = 4
n_thread = 0
n_thread_max = 4
n_correct = 0
n_finished = 0

# spawn threads
for i in range(n_thread):
_thread.start_new_thread(thread_entry, (10,))
for _ in range(n_thread_max):
try:
_thread.start_new_thread(thread_entry, (10,))
n_thread += 1
except OSError:
# System cannot create a new thead, so stop trying to create them.
break

# also run the function on this main thread
thread_entry(10)
n_thread += 1

# busy wait for threads to finish
while n_finished < n_thread:
pass

print(n_correct == n_finished)
6 changes: 5 additions & 1 deletion tests/thread/thread_ident1.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
import _thread


# Initialise variables (also preallocate their spot in the globals dict so the
# globals dict is not resized while threads are running).
tid = None
tid_main = None
new_tid = None
finished = False


def thread_entry():
Expand All @@ -19,7 +24,6 @@ def thread_entry():
tid_main = _thread.get_ident()
print("main", type(tid_main) == int, tid_main != 0)

finished = False
new_tid = _thread.start_new_thread(thread_entry, ())

while not finished:
Expand Down
8 changes: 6 additions & 2 deletions tests/thread/thread_lock4.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,18 @@ def thread_entry():

# spawn threads to do the jobs
for i in range(4):
_thread.start_new_thread(thread_entry, ())
try:
_thread.start_new_thread(thread_entry, ())
except OSError:
# System cannot create a new thead, so stop trying to create them.
break

# wait for the jobs to complete
while True:
with jobs_lock:
if len(output) == n_jobs:
break
time.sleep(1)
time.sleep(0)

# sort and print the results
output.sort(key=lambda x: x[0])
Expand Down
18 changes: 14 additions & 4 deletions tests/thread/thread_qstr1.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,26 @@ def th(base, n):


lock = _thread.allocate_lock()
n_thread = 4
n_thread = 0
n_thread_max = 4
n_finished = 0
n_qstr_per_thread = 100 # make 1000 for a more stressful test (uses more heap)

# spawn threads
for i in range(n_thread):
_thread.start_new_thread(th, (i * n_qstr_per_thread, n_qstr_per_thread))
for _ in range(n_thread_max):
try:
_thread.start_new_thread(th, (n_thread * n_qstr_per_thread, n_qstr_per_thread))
n_thread += 1
except OSError:
# System cannot create a new thead, so stop trying to create them.
break

# also run the function on this main thread
th(n_thread * n_qstr_per_thread, n_qstr_per_thread)
n_thread += 1

# wait for threads to finish
while n_finished < n_thread:
time.sleep(1)
time.sleep(0)

print("pass")
16 changes: 13 additions & 3 deletions tests/thread/thread_shared1.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,25 @@ def thread_entry(n, tup):


lock = _thread.allocate_lock()
n_thread = 2
n_thread = 0
n_thread_max = 2
n_finished = 0

# the shared data structure
tup = (1, 2, 3, 4)

# spawn threads
for i in range(n_thread):
_thread.start_new_thread(thread_entry, (100, tup))
for _ in range(n_thread_max):
try:
_thread.start_new_thread(thread_entry, (100, tup))
n_thread += 1
except OSError:
# System cannot create a new thead, so stop trying to create them.
break

# also run the function on this main thread
thread_entry(100, tup)
n_thread += 1

# busy wait for threads to finish
while n_finished < n_thread:
Expand Down
19 changes: 15 additions & 4 deletions tests/thread/thread_sleep1.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
import _thread

lock = _thread.allocate_lock()
n_thread = 4
n_thread = 0
n_thread_max = 4
n_finished = 0


Expand All @@ -24,10 +25,20 @@ def thread_entry(t):
n_finished += 1


for i in range(n_thread):
_thread.start_new_thread(thread_entry, (10 * i,))
# spawn threads
for _ in range(n_thread_max):
try:
_thread.start_new_thread(thread_entry, (10 * n_thread,))
n_thread += 1
except OSError:
# System cannot create a new thead, so stop trying to create them.
break

# also run the function on this main thread
thread_entry(10 * n_thread)
n_thread += 1

# wait for threads to finish
while n_finished < n_thread:
sleep_ms(100)
print("done", n_thread)
print("done")
31 changes: 31 additions & 0 deletions tests/thread/thread_sleep2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Test accuracy of sleep within a thread.

import time
import _thread


def sleep(t, valid_range):
t0 = time.time_ns()
time.sleep(t)
dt_ms = (time.time_ns() - t0) // 1_000_000
if dt_ms in valid_range:
print("dt in range", t)
else:
print("dt not in range:", dt_ms)


def thread_entry():
lock.acquire()
print("thread start")
sleep(0.2, range(180, 400))
print("thread end")


lock = _thread.allocate_lock()
lock.acquire()
_thread.start_new_thread(thread_entry, ())

print("main start")
lock.release()
sleep(0.5, range(480, 800))
print("main end")