Yet another iteration for condition variables: now the lock is only released only once the thread has been added to the queue.

This commit is contained in:
Juan Jose Garcia Ripoll 2012-07-13 21:35:38 +02:00
parent 8e853cdcce
commit 9287a516ff
3 changed files with 11 additions and 6 deletions

View file

@ -462,7 +462,6 @@ cl_object_mark_proc(void *addr, struct GC_ms_entry *msp, struct GC_ms_entry *msl
MAYBE_MARK(o->condition_variable.queue_spinlock);
MAYBE_MARK(o->condition_variable.queue_list);
MAYBE_MARK(o->condition_variable.lock);
MAYBE_MARK(o->condition_variable.signaled);
break;
case t_rwlock:
MAYBE_MARK(o->rwlock.name);
@ -1015,7 +1014,6 @@ init_alloc(void)
to_bitmap(&o, &(o.rwlock.mutex));
# endif
type_info[t_condition_variable].descriptor =
to_bitmap(&o, &(o.condition_variable.signaled)) |
to_bitmap(&o, &(o.condition_variable.lock)) |
to_bitmap(&o, &(o.condition_variable.queue_list)) |
to_bitmap(&o, &(o.condition_variable.queue_spinlock));

View file

@ -33,7 +33,14 @@ mp_make_condition_variable(void)
static cl_object
condition_variable_wait(cl_env_ptr env, cl_object cv)
{
return cv->condition_variable.signaled;
cl_object lock = cv->condition_variable.lock;
cl_object own_process = env->own_process;
/* We have entered the queue and still own the mutex? */
if (lock->lock.owner == own_process) {
mp_giveup_lock(lock);
}
/* We always return when we have been explicitly awaken */
return (own_process->process.waiting_for != cv)? ECL_T : ECL_NIL;
}
cl_object
@ -64,8 +71,9 @@ mp_condition_variable_wait(cl_object cv, cl_object lock)
FEerror("mp:condition-variable-wait can not be used with recursive"
" locks:~%~S", 1, lock);
}
print_lock("waiting cv %p", cv, env);
cv->condition_variable.lock = lock;
env->own_process->process.waiting_for = cv;
mp_giveup_lock(cv->condition_variable.lock = lock);
ecl_wait_on(env, condition_variable_wait, cv);
mp_get_lock_wait(lock);
@(return ECL_T)
@ -81,7 +89,6 @@ cl_object
mp_condition_variable_signal(cl_object cv)
{
cl_object lock = cv->condition_variable.lock;
cv->condition_variable.signaled = ECL_T;
ecl_wakeup_waiters(ecl_process_env(), cv,
ECL_WAKEUP_RESET_FLAG | ECL_WAKEUP_ONE);
@(return ECL_T)
@ -90,6 +97,7 @@ mp_condition_variable_signal(cl_object cv)
cl_object
mp_condition_variable_broadcast(cl_object cv)
{
print_lock("waking up cv", cv);
ecl_wakeup_waiters(ecl_process_env(), cv,
ECL_WAKEUP_RESET_FLAG | ECL_WAKEUP_ALL);
@(return ECL_T)

View file

@ -954,7 +954,6 @@ struct ecl_condition_variable {
cl_object queue_list;
cl_object queue_spinlock;
cl_object lock;
cl_object signaled;
};
#endif /* ECL_THREADS */