GSoC Project Updates, Threads!

Since my last update I have been busy with MicroPython tests- enabling new features and testing them, isolating problematic test cases, sometimes placing appropriate definitions and function calls in the C code.

I traced the failure of builtin_compile to the __globals__ attribute not being available for function objects. Enabling that fixed it.

I also now include the previously ignored float test group, giving us 9 more passing tests.

Turns out that the int_big_div and int_big_mul tests that I mentioned in my previous post were failing because of hardware flow control issues and I fixed it by enabling the IXON termios flag.

The latest update with test cases is that I have 588 passing test cases out of 591 executed. The failing test cases are:

I am tracking progress on test cases in this issue. Here is a list of all MicroPython modules that have been enabled so far:
array, builtins, cmath, collections, errno, gc, heapq, io, json, math, os, platform, random, re, struct, sys, time, machine, uctypes

The highlighted ones are either partially enabled, or have a failing testcase.

threads

I have also been able to get threads working on MicroPython. The threads use RTEMS Tasks internally. As for testing threads, I currently have five passing test cases. There are around 8 to 9 more tests but those need locks on the MicroPython side, which is still a work in progress.

I wanted to talk more about how threads are implemented in MicroPython. MicroPython doesn’t have documentation for the _thread module as it is “highly experimental and its API is not yet fully settled”, so I think that makes it a really good topic for a blog post. The thread functions are listed in py/mpthread.h. Ports that implement threads, i.e. the _thread module, need to implement these functions in a mpthreadport.c. Here’s a link to my current mpthreadport.c.

Here’s some debugging output that visualizes the order in which different functions are called:

MicroPython v1.26.0-preview.154.g0dbda0e0c.dirty on 2025-08-20; rtems-i386/pc686 with unknown-cpu
THREAD: get_state
>>> import _thread as th
THREAD: get_state
THREAD: get_state
...
THREAD: get_state
THREAD: get_state
THREAD: get_state
>>> x = lambda: print("thread!")
THREAD: get_state
...
THREAD: get_state
THREAD: get_state
>>> th.start_new_thread(x, ())
THREAD: get_state
...
THREAD: get_state
THREAD: get_state
167837698
THREAD: get_state
THREAD: get_state
>>> THREAD: set_state
THREAD: get_state
THREAD: mutex_lock
THREAD: thread_start
THREAD: get_state
thread!
THREAD: get_state
THREAD: thread_finish
THREAD: get_state
THREAD: get_state
...
>>>

The state for multiple threads is tracked using a linked list, access to which is protected by a mutex. An internal task is created for a new thread using the RTMS task API and a new node is added to the linked list. Here’s the structure of a node:

typedef struct _mp_thread_t {
    rtems_id id;               // RTEMS task ID
    bool ready;
    void *arg;                 // thread-entry args
    struct _mp_thread_t *next;
    mp_state_thread_t *state;  // pointer to this thread's mp state
} mp_thread_t;

I will document the threads implementation in detail when I’m able to get MicroPython locks working.

final work

GSoC coding period ends on 25th August! Here’s a list of action items I am currently working towards:

Thank you for your time :)