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);
|
||||
}
|
||||
|
||||
mp_uint_t mp_thread_get_id(void) {
|
||||
return (mp_uint_t)xTaskGetCurrentTaskHandle();
|
||||
}
|
||||
|
||||
void mp_thread_start(void) {
|
||||
mp_thread_mutex_lock(&thread_mutex, 1);
|
||||
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
|
||||
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
|
||||
*stack_size -= 512;
|
||||
|
||||
MP_STATIC_ASSERT(sizeof(mp_uint_t) >= sizeof(TaskHandle_t));
|
||||
return (mp_uint_t)id;
|
||||
}
|
||||
|
||||
void mp_thread_finish(void) {
|
||||
|
|
|
@ -98,6 +98,10 @@ void mp_thread_set_state(mp_state_thread_t *state) {
|
|||
vTaskSetThreadLocalStoragePointer(NULL, 1, state);
|
||||
}
|
||||
|
||||
mp_uint_t mp_thread_get_id(void) {
|
||||
return (mp_uint_t)xTaskGetCurrentTaskHandle();
|
||||
}
|
||||
|
||||
void mp_thread_start(void) {
|
||||
mp_thread_mutex_lock(&thread_mutex, 1);
|
||||
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
|
||||
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;
|
||||
|
||||
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_thread_create_ex(entry, arg, stack_size, MP_THREAD_PRIORITY, "mp_thread");
|
||||
mp_uint_t mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
|
||||
return mp_thread_create_ex(entry, arg, stack_size, MP_THREAD_PRIORITY, "mp_thread");
|
||||
}
|
||||
|
||||
void mp_thread_finish(void) {
|
||||
|
|
|
@ -54,7 +54,11 @@ void mp_thread_gc_others(void) {
|
|||
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) {
|
||||
*stack_size = 4096; // default stack size
|
||||
} 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
|
||||
*stack_size -= 1024;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void mp_thread_start(void) {
|
||||
|
|
|
@ -116,7 +116,13 @@ STATIC void core1_entry_wrapper(void) {
|
|||
// 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.
|
||||
if (core1_entry != NULL) {
|
||||
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.
|
||||
*stack_size -= 512;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void mp_thread_start(void) {
|
||||
|
|
|
@ -54,7 +54,11 @@ void mp_thread_gc_others(void) {
|
|||
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) {
|
||||
*stack_size = 4096; // default stack size
|
||||
} 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
|
||||
*stack_size -= 1024;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void mp_thread_start(void) {
|
||||
|
|
|
@ -191,6 +191,10 @@ void mp_thread_set_state(mp_state_thread_t *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) {
|
||||
// enable realtime priority if `-X realtime` command line parameter was set
|
||||
#if defined(__APPLE__)
|
||||
|
@ -210,7 +214,7 @@ void mp_thread_start(void) {
|
|||
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
|
||||
if (*stack_size == 0) {
|
||||
*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();
|
||||
|
||||
return;
|
||||
MP_STATIC_ASSERT(sizeof(mp_uint_t) >= sizeof(pthread_t));
|
||||
return (mp_uint_t)id;
|
||||
|
||||
er:
|
||||
mp_raise_OSError(ret);
|
||||
|
|
|
@ -129,7 +129,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE(
|
|||
STATIC size_t thread_stack_size = 0;
|
||||
|
||||
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);
|
||||
|
||||
|
@ -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];
|
||||
|
||||
// spawn the thread!
|
||||
mp_thread_create(thread_entry, th_args, &th_args->stack_size);
|
||||
|
||||
return mp_const_none;
|
||||
return mp_obj_new_int_from_uint(mp_thread_create(thread_entry, th_args, &th_args->stack_size));
|
||||
}
|
||||
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);
|
||||
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_finish(void);
|
||||
void mp_thread_mutex_init(mp_thread_mutex_t *mutex);
|
||||
|
|
|
@ -5,7 +5,11 @@
|
|||
import _thread
|
||||
|
||||
|
||||
tid = None
|
||||
|
||||
|
||||
def thread_entry():
|
||||
global tid
|
||||
tid = _thread.get_ident()
|
||||
print("thread", type(tid) == int, tid != 0, tid != tid_main)
|
||||
global finished
|
||||
|
@ -16,8 +20,9 @@ tid_main = _thread.get_ident()
|
|||
print("main", type(tid_main) == int, tid_main != 0)
|
||||
|
||||
finished = False
|
||||
_thread.start_new_thread(thread_entry, ())
|
||||
new_tid = _thread.start_new_thread(thread_entry, ())
|
||||
|
||||
while not finished:
|
||||
pass
|
||||
print("done")
|
||||
|
||||
print("done", type(new_tid) == int, new_tid == tid)
|
||||
|
|
Loading…
Reference in New Issue