mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2026-01-16 06:12:25 -08:00
The owner of a lock now passes ownership to the first waiting process.
This commit is contained in:
parent
14d2960135
commit
7a4a98d020
3 changed files with 54 additions and 7 deletions
|
|
@ -113,12 +113,15 @@ mp_giveup_lock(cl_object lock)
|
|||
FEerror_not_owned(lock);
|
||||
}
|
||||
if (--lock->lock.counter == 0) {
|
||||
lock->lock.owner = ECL_NIL;
|
||||
print_lock("releasing %p\t", lock, lock);
|
||||
ecl_wakeup_waiters(env, lock, ECL_WAKEUP_ONE);
|
||||
} else {
|
||||
print_lock("released %p\t", lock, lock);
|
||||
}
|
||||
cl_object first = ecl_waiter_pop(env, lock);;
|
||||
if (first == ECL_NIL) {
|
||||
lock->lock.owner = ECL_NIL;
|
||||
} else {
|
||||
lock->lock.counter = 1;
|
||||
lock->lock.owner = first;
|
||||
ecl_wakeup_process(first);
|
||||
}
|
||||
}
|
||||
ecl_return1(env, ECL_T);
|
||||
}
|
||||
|
||||
|
|
@ -158,6 +161,26 @@ mp_get_lock_nowait(cl_object lock)
|
|||
ecl_return1(env, get_lock_inner(env, lock));
|
||||
}
|
||||
|
||||
static cl_object
|
||||
own_or_get_lock(cl_env_ptr env, cl_object lock)
|
||||
{
|
||||
cl_object output;
|
||||
cl_object own_process = env->own_process;
|
||||
ecl_disable_interrupts_env(env);
|
||||
if (AO_compare_and_swap_full((AO_t*)&(lock->lock.owner),
|
||||
(AO_t)ECL_NIL, (AO_t)own_process)) {
|
||||
lock->lock.counter = 1;
|
||||
output = ECL_T;
|
||||
print_lock("acquired %p\t", lock, lock);
|
||||
} else if (lock->lock.owner == own_process) {
|
||||
output = ECL_T;
|
||||
} else {
|
||||
output = ECL_NIL;
|
||||
}
|
||||
ecl_enable_interrupts_env(env);
|
||||
return output;
|
||||
}
|
||||
|
||||
cl_object
|
||||
mp_get_lock_wait(cl_object lock)
|
||||
{
|
||||
|
|
@ -166,7 +189,7 @@ mp_get_lock_wait(cl_object lock)
|
|||
FEerror_not_a_lock(lock);
|
||||
}
|
||||
if (get_lock_inner(env, lock) == ECL_NIL) {
|
||||
ecl_wait_on(env, get_lock_inner, lock);
|
||||
ecl_wait_on(env, own_or_get_lock, lock);
|
||||
}
|
||||
@(return ECL_T)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -302,6 +302,29 @@ ecl_wait_on(cl_env_ptr env, cl_object (*condition)(cl_env_ptr, cl_object), cl_ob
|
|||
#endif
|
||||
}
|
||||
|
||||
cl_object
|
||||
ecl_waiter_pop(cl_env_ptr the_env, cl_object q)
|
||||
{
|
||||
cl_object output;
|
||||
ecl_disable_interrupts_env(the_env);
|
||||
ecl_get_spinlock(the_env, &q->queue.spinlock);
|
||||
{
|
||||
cl_object l;
|
||||
output = ECL_NIL;
|
||||
for (l = q->queue.list; l != ECL_NIL; l = ECL_CONS_CDR(l)) {
|
||||
cl_object p = ECL_CONS_CAR(l);
|
||||
if (p->process.phase != ECL_PROCESS_INACTIVE &&
|
||||
p->process.phase != ECL_PROCESS_EXITING) {
|
||||
output = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ecl_giveup_spinlock(&q->queue.spinlock);
|
||||
ecl_enable_interrupts_env(the_env);
|
||||
return output;
|
||||
}
|
||||
|
||||
void
|
||||
ecl_wakeup_waiters(cl_env_ptr the_env, cl_object q, int flags)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -497,6 +497,7 @@ extern void ecl_giveup_spinlock(cl_object *lock);
|
|||
extern cl_object ecl_wait_on(cl_env_ptr env, cl_object (*condition)(cl_env_ptr, cl_object), cl_object o);
|
||||
extern void ecl_wakeup_waiters(cl_env_ptr the_env, cl_object o, int flags);
|
||||
extern void ecl_wakeup_process(cl_object process);
|
||||
extern cl_object ecl_waiter_pop(cl_env_ptr the_env, cl_object q);
|
||||
#endif
|
||||
|
||||
/* threads/rwlock.d */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue