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>
This commit is contained in:
parent
c0d4c604e6
commit
ffb43b2dd3
@ -89,6 +89,10 @@ void mp_thread_set_state(mp_state_thread_t *state) {
|
|||||||
vTaskSetThreadLocalStoragePointer(NULL, 0, state);
|
vTaskSetThreadLocalStoragePointer(NULL, 0, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mp_uint_t mp_thread_get_id(void) {
|
||||||
|
return (mp_uint_t)xTaskGetCurrentTaskHandle();
|
||||||
|
}
|
||||||
|
|
||||||
void mp_thread_start(void) {
|
void mp_thread_start(void) {
|
||||||
mp_thread_mutex_lock(&thread_mutex, 1);
|
mp_thread_mutex_lock(&thread_mutex, 1);
|
||||||
for (mp_thread_t *th = thread; th != NULL; th = th->next) {
|
for (mp_thread_t *th = thread; th != NULL; th = th->next) {
|
||||||
@ -111,7 +115,7 @@ STATIC void freertos_entry(void *arg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
|
mp_uint_t mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
|
||||||
// store thread entry function into a global variable so we can access it
|
// store thread entry function into a global variable so we can access it
|
||||||
ext_thread_entry = entry;
|
ext_thread_entry = entry;
|
||||||
|
|
||||||
@ -148,6 +152,9 @@ void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
|
|||||||
|
|
||||||
// adjust stack_size to provide room to recover from hitting the limit
|
// adjust stack_size to provide room to recover from hitting the limit
|
||||||
*stack_size -= 512;
|
*stack_size -= 512;
|
||||||
|
|
||||||
|
MP_STATIC_ASSERT(sizeof(mp_uint_t) >= sizeof(TaskHandle_t));
|
||||||
|
return (mp_uint_t)id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_thread_finish(void) {
|
void mp_thread_finish(void) {
|
||||||
|
@ -98,6 +98,10 @@ void mp_thread_set_state(mp_state_thread_t *state) {
|
|||||||
vTaskSetThreadLocalStoragePointer(NULL, 1, state);
|
vTaskSetThreadLocalStoragePointer(NULL, 1, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mp_uint_t mp_thread_get_id(void) {
|
||||||
|
return (mp_uint_t)xTaskGetCurrentTaskHandle();
|
||||||
|
}
|
||||||
|
|
||||||
void mp_thread_start(void) {
|
void mp_thread_start(void) {
|
||||||
mp_thread_mutex_lock(&thread_mutex, 1);
|
mp_thread_mutex_lock(&thread_mutex, 1);
|
||||||
for (mp_thread_t *th = thread; th != NULL; th = th->next) {
|
for (mp_thread_t *th = thread; th != NULL; th = th->next) {
|
||||||
@ -120,7 +124,7 @@ STATIC void freertos_entry(void *arg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_thread_create_ex(void *(*entry)(void *), void *arg, size_t *stack_size, int priority, char *name) {
|
mp_uint_t mp_thread_create_ex(void *(*entry)(void *), void *arg, size_t *stack_size, int priority, char *name) {
|
||||||
// store thread entry function into a global variable so we can access it
|
// store thread entry function into a global variable so we can access it
|
||||||
ext_thread_entry = entry;
|
ext_thread_entry = entry;
|
||||||
|
|
||||||
@ -154,10 +158,12 @@ void mp_thread_create_ex(void *(*entry)(void *), void *arg, size_t *stack_size,
|
|||||||
*stack_size -= 1024;
|
*stack_size -= 1024;
|
||||||
|
|
||||||
mp_thread_mutex_unlock(&thread_mutex);
|
mp_thread_mutex_unlock(&thread_mutex);
|
||||||
|
|
||||||
|
return (mp_uint_t)th->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
|
mp_uint_t mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
|
||||||
mp_thread_create_ex(entry, arg, stack_size, MP_THREAD_PRIORITY, "mp_thread");
|
return mp_thread_create_ex(entry, arg, stack_size, MP_THREAD_PRIORITY, "mp_thread");
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_thread_finish(void) {
|
void mp_thread_finish(void) {
|
||||||
|
@ -54,7 +54,11 @@ void mp_thread_gc_others(void) {
|
|||||||
mp_thread_mutex_unlock(&thread_mutex);
|
mp_thread_mutex_unlock(&thread_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
|
mp_uint_t mp_thread_get_id(void) {
|
||||||
|
return (uint32_t)pyb_thread_cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_uint_t mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
|
||||||
if (*stack_size == 0) {
|
if (*stack_size == 0) {
|
||||||
*stack_size = 4096; // default stack size
|
*stack_size = 4096; // default stack size
|
||||||
} else if (*stack_size < 2048) {
|
} else if (*stack_size < 2048) {
|
||||||
@ -82,6 +86,8 @@ void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
|
|||||||
|
|
||||||
// adjust stack_size to provide room to recover from hitting the limit
|
// adjust stack_size to provide room to recover from hitting the limit
|
||||||
*stack_size -= 1024;
|
*stack_size -= 1024;
|
||||||
|
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_thread_start(void) {
|
void mp_thread_start(void) {
|
||||||
|
@ -116,7 +116,13 @@ STATIC void core1_entry_wrapper(void) {
|
|||||||
// returning from here will loop the core forever (WFI)
|
// returning from here will loop the core forever (WFI)
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
|
mp_uint_t mp_thread_get_id(void) {
|
||||||
|
// On RP2, there are only two threads, one for each core, so the thread id
|
||||||
|
// is the core number.
|
||||||
|
return get_core_num();
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_uint_t mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
|
||||||
// Check if core1 is already in use.
|
// Check if core1 is already in use.
|
||||||
if (core1_entry != NULL) {
|
if (core1_entry != NULL) {
|
||||||
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("core1 in use"));
|
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("core1 in use"));
|
||||||
@ -144,6 +150,8 @@ void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
|
|||||||
|
|
||||||
// Adjust stack_size to provide room to recover from hitting the limit.
|
// Adjust stack_size to provide room to recover from hitting the limit.
|
||||||
*stack_size -= 512;
|
*stack_size -= 512;
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_thread_start(void) {
|
void mp_thread_start(void) {
|
||||||
|
@ -54,7 +54,11 @@ void mp_thread_gc_others(void) {
|
|||||||
mp_thread_mutex_unlock(&thread_mutex);
|
mp_thread_mutex_unlock(&thread_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
|
mp_uint_t mp_thread_get_id(void) {
|
||||||
|
return (uint32_t)pyb_thread_cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_uint_t mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
|
||||||
if (*stack_size == 0) {
|
if (*stack_size == 0) {
|
||||||
*stack_size = 4096; // default stack size
|
*stack_size = 4096; // default stack size
|
||||||
} else if (*stack_size < 2048) {
|
} else if (*stack_size < 2048) {
|
||||||
@ -82,6 +86,8 @@ void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
|
|||||||
|
|
||||||
// adjust stack_size to provide room to recover from hitting the limit
|
// adjust stack_size to provide room to recover from hitting the limit
|
||||||
*stack_size -= 1024;
|
*stack_size -= 1024;
|
||||||
|
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_thread_start(void) {
|
void mp_thread_start(void) {
|
||||||
|
@ -191,6 +191,10 @@ void mp_thread_set_state(mp_state_thread_t *state) {
|
|||||||
pthread_setspecific(tls_key, state);
|
pthread_setspecific(tls_key, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mp_uint_t mp_thread_get_id(void) {
|
||||||
|
return (mp_uint_t)pthread_self();
|
||||||
|
}
|
||||||
|
|
||||||
void mp_thread_start(void) {
|
void mp_thread_start(void) {
|
||||||
// enable realtime priority if `-X realtime` command line parameter was set
|
// enable realtime priority if `-X realtime` command line parameter was set
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
@ -210,7 +214,7 @@ void mp_thread_start(void) {
|
|||||||
mp_thread_unix_end_atomic_section();
|
mp_thread_unix_end_atomic_section();
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
|
mp_uint_t mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
|
||||||
// default stack size is 8k machine-words
|
// default stack size is 8k machine-words
|
||||||
if (*stack_size == 0) {
|
if (*stack_size == 0) {
|
||||||
*stack_size = 8192 * sizeof(void *);
|
*stack_size = 8192 * sizeof(void *);
|
||||||
@ -265,7 +269,8 @@ void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
|
|||||||
|
|
||||||
mp_thread_unix_end_atomic_section();
|
mp_thread_unix_end_atomic_section();
|
||||||
|
|
||||||
return;
|
MP_STATIC_ASSERT(sizeof(mp_uint_t) >= sizeof(pthread_t));
|
||||||
|
return (mp_uint_t)id;
|
||||||
|
|
||||||
er:
|
er:
|
||||||
mp_raise_OSError(ret);
|
mp_raise_OSError(ret);
|
||||||
|
@ -129,7 +129,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE(
|
|||||||
STATIC size_t thread_stack_size = 0;
|
STATIC size_t thread_stack_size = 0;
|
||||||
|
|
||||||
STATIC mp_obj_t mod_thread_get_ident(void) {
|
STATIC mp_obj_t mod_thread_get_ident(void) {
|
||||||
return mp_obj_new_int_from_uint((uintptr_t)mp_thread_get_state());
|
return mp_obj_new_int_from_uint(mp_thread_get_id());
|
||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_get_ident_obj, mod_thread_get_ident);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_get_ident_obj, mod_thread_get_ident);
|
||||||
|
|
||||||
@ -268,9 +268,7 @@ STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args)
|
|||||||
th_args->fun = args[0];
|
th_args->fun = args[0];
|
||||||
|
|
||||||
// spawn the thread!
|
// spawn the thread!
|
||||||
mp_thread_create(thread_entry, th_args, &th_args->stack_size);
|
return mp_obj_new_int_from_uint(mp_thread_create(thread_entry, th_args, &th_args->stack_size));
|
||||||
|
|
||||||
return mp_const_none;
|
|
||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_start_new_thread_obj, 2, 3, mod_thread_start_new_thread);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_start_new_thread_obj, 2, 3, mod_thread_start_new_thread);
|
||||||
|
|
||||||
|
@ -40,7 +40,8 @@ struct _mp_state_thread_t;
|
|||||||
|
|
||||||
struct _mp_state_thread_t *mp_thread_get_state(void);
|
struct _mp_state_thread_t *mp_thread_get_state(void);
|
||||||
void mp_thread_set_state(struct _mp_state_thread_t *state);
|
void mp_thread_set_state(struct _mp_state_thread_t *state);
|
||||||
void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size);
|
mp_uint_t mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size);
|
||||||
|
mp_uint_t mp_thread_get_id(void);
|
||||||
void mp_thread_start(void);
|
void mp_thread_start(void);
|
||||||
void mp_thread_finish(void);
|
void mp_thread_finish(void);
|
||||||
void mp_thread_mutex_init(mp_thread_mutex_t *mutex);
|
void mp_thread_mutex_init(mp_thread_mutex_t *mutex);
|
||||||
|
@ -5,7 +5,11 @@
|
|||||||
import _thread
|
import _thread
|
||||||
|
|
||||||
|
|
||||||
|
tid = None
|
||||||
|
|
||||||
|
|
||||||
def thread_entry():
|
def thread_entry():
|
||||||
|
global tid
|
||||||
tid = _thread.get_ident()
|
tid = _thread.get_ident()
|
||||||
print("thread", type(tid) == int, tid != 0, tid != tid_main)
|
print("thread", type(tid) == int, tid != 0, tid != tid_main)
|
||||||
global finished
|
global finished
|
||||||
@ -16,8 +20,9 @@ tid_main = _thread.get_ident()
|
|||||||
print("main", type(tid_main) == int, tid_main != 0)
|
print("main", type(tid_main) == int, tid_main != 0)
|
||||||
|
|
||||||
finished = False
|
finished = False
|
||||||
_thread.start_new_thread(thread_entry, ())
|
new_tid = _thread.start_new_thread(thread_entry, ())
|
||||||
|
|
||||||
while not finished:
|
while not finished:
|
||||||
pass
|
pass
|
||||||
print("done")
|
|
||||||
|
print("done", type(new_tid) == int, new_tid == tid)
|
||||||
|
Loading…
Reference in New Issue
Block a user