py/modthread: Use system-provided mutexs for _thread locks.

It's more efficient using the system mutexs instead of synthetic ones with
a busy-wait loop.  The system can do proper scheduling and blocking of the
threads waiting on the mutex.
This commit is contained in:
Damien George 2017-02-06 10:47:20 +11:00
parent 06a12ada48
commit 234f07f16c

View File

@ -44,24 +44,19 @@
/****************************************************************/ /****************************************************************/
// Lock object // Lock object
// Note: with the GIL enabled we can easily synthesise a lock object
STATIC const mp_obj_type_t mp_type_thread_lock; STATIC const mp_obj_type_t mp_type_thread_lock;
typedef struct _mp_obj_thread_lock_t { typedef struct _mp_obj_thread_lock_t {
mp_obj_base_t base; mp_obj_base_t base;
#if !MICROPY_PY_THREAD_GIL
mp_thread_mutex_t mutex; mp_thread_mutex_t mutex;
#endif
volatile bool locked; volatile bool locked;
} mp_obj_thread_lock_t; } mp_obj_thread_lock_t;
STATIC mp_obj_thread_lock_t *mp_obj_new_thread_lock(void) { STATIC mp_obj_thread_lock_t *mp_obj_new_thread_lock(void) {
mp_obj_thread_lock_t *self = m_new_obj(mp_obj_thread_lock_t); mp_obj_thread_lock_t *self = m_new_obj(mp_obj_thread_lock_t);
self->base.type = &mp_type_thread_lock; self->base.type = &mp_type_thread_lock;
#if !MICROPY_PY_THREAD_GIL
mp_thread_mutex_init(&self->mutex); mp_thread_mutex_init(&self->mutex);
#endif
self->locked = false; self->locked = false;
return self; return self;
} }
@ -73,20 +68,9 @@ STATIC mp_obj_t thread_lock_acquire(size_t n_args, const mp_obj_t *args) {
wait = mp_obj_get_int(args[1]); wait = mp_obj_get_int(args[1]);
// TODO support timeout arg // TODO support timeout arg
} }
#if MICROPY_PY_THREAD_GIL MP_THREAD_GIL_EXIT();
if (self->locked) {
if (!wait) {
return mp_const_false;
}
do {
MP_THREAD_GIL_EXIT();
MP_THREAD_GIL_ENTER();
} while (self->locked);
}
self->locked = true;
return mp_const_true;
#else
int ret = mp_thread_mutex_lock(&self->mutex, wait); int ret = mp_thread_mutex_lock(&self->mutex, wait);
MP_THREAD_GIL_ENTER();
if (ret == 0) { if (ret == 0) {
return mp_const_false; return mp_const_false;
} else if (ret == 1) { } else if (ret == 1) {
@ -95,7 +79,6 @@ STATIC mp_obj_t thread_lock_acquire(size_t n_args, const mp_obj_t *args) {
} else { } else {
mp_raise_OSError(-ret); mp_raise_OSError(-ret);
} }
#endif
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(thread_lock_acquire_obj, 1, 3, thread_lock_acquire); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(thread_lock_acquire_obj, 1, 3, thread_lock_acquire);
@ -103,9 +86,9 @@ STATIC mp_obj_t thread_lock_release(mp_obj_t self_in) {
mp_obj_thread_lock_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_thread_lock_t *self = MP_OBJ_TO_PTR(self_in);
// TODO check if already unlocked // TODO check if already unlocked
self->locked = false; self->locked = false;
#if !MICROPY_PY_THREAD_GIL MP_THREAD_GIL_EXIT();
mp_thread_mutex_unlock(&self->mutex); mp_thread_mutex_unlock(&self->mutex);
#endif MP_THREAD_GIL_ENTER();
return mp_const_none; return mp_const_none;
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_1(thread_lock_release_obj, thread_lock_release); STATIC MP_DEFINE_CONST_FUN_OBJ_1(thread_lock_release_obj, thread_lock_release);