Fixing mutex-unlock! on a condition variable to both unlock and block.

This commit is contained in:
Alex Shinn 2012-05-12 22:43:46 +09:00
parent 1ab1008f20
commit 1aff449a48

View file

@ -218,36 +218,35 @@ sexp sexp_mutex_lock (sexp ctx, sexp self, sexp_sint_t n, sexp mutex, sexp timeo
sexp sexp_mutex_unlock (sexp ctx, sexp self, sexp_sint_t n, sexp mutex, sexp condvar, sexp timeout) { sexp sexp_mutex_unlock (sexp ctx, sexp self, sexp_sint_t n, sexp mutex, sexp condvar, sexp timeout) {
sexp ls1, ls2; sexp ls1, ls2;
if (sexp_not(condvar)) { /* first unlock and unblock threads */
/* normal unlock - always succeeds, just need to unblock threads */ if (sexp_truep(sexp_mutex_lockp(mutex))) {
if (sexp_truep(sexp_mutex_lockp(mutex))) { sexp_mutex_lockp(mutex) = SEXP_FALSE;
sexp_mutex_lockp(mutex) = SEXP_FALSE; sexp_mutex_thread(mutex) = ctx;
sexp_mutex_thread(mutex) = ctx; /* search for threads blocked on this mutex */
/* search for threads blocked on this mutex */ for (ls1=SEXP_NULL, ls2=sexp_global(ctx, SEXP_G_THREADS_PAUSED);
for (ls1=SEXP_NULL, ls2=sexp_global(ctx, SEXP_G_THREADS_PAUSED); sexp_pairp(ls2); ls1=ls2, ls2=sexp_cdr(ls2))
sexp_pairp(ls2); ls1=ls2, ls2=sexp_cdr(ls2)) if (sexp_context_event(sexp_car(ls2)) == mutex) {
if (sexp_context_event(sexp_car(ls2)) == mutex) { if (ls1==SEXP_NULL)
if (ls1==SEXP_NULL) sexp_global(ctx, SEXP_G_THREADS_PAUSED) = sexp_cdr(ls2);
sexp_global(ctx, SEXP_G_THREADS_PAUSED) = sexp_cdr(ls2); else
else sexp_cdr(ls1) = sexp_cdr(ls2);
sexp_cdr(ls1) = sexp_cdr(ls2); sexp_cdr(ls2) = sexp_global(ctx, SEXP_G_THREADS_FRONT);
sexp_cdr(ls2) = sexp_global(ctx, SEXP_G_THREADS_FRONT); sexp_global(ctx, SEXP_G_THREADS_FRONT) = ls2;
sexp_global(ctx, SEXP_G_THREADS_FRONT) = ls2; if (! sexp_pairp(sexp_cdr(ls2)))
if (! sexp_pairp(sexp_cdr(ls2))) sexp_global(ctx, SEXP_G_THREADS_BACK) = ls2;
sexp_global(ctx, SEXP_G_THREADS_BACK) = ls2; sexp_context_waitp(sexp_car(ls2))
sexp_context_waitp(sexp_car(ls2)) = sexp_context_timeoutp(sexp_car(ls2)) = 0;
= sexp_context_timeoutp(sexp_car(ls2)) = 0; break;
break; }
} }
} if (sexp_truep(condvar)) {
return SEXP_TRUE; /* wait on condition var if specified */
} else {
/* wait on condition var */
sexp_context_waitp(ctx) = 1; sexp_context_waitp(ctx) = 1;
sexp_context_event(ctx) = condvar; sexp_context_event(ctx) = condvar;
sexp_insert_timed(ctx, ctx, timeout); sexp_insert_timed(ctx, ctx, timeout);
return SEXP_FALSE; return SEXP_FALSE;
} }
return SEXP_TRUE;
} }
/**************************** condition variables *************************/ /**************************** condition variables *************************/