mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-09 21:40:33 +02:00
(scm_try_arbiter): Use scm_i_misc_mutex instead of
SCM_DEFER_INTS. (scm_release_arbiter): Use scm_i_misc_mutex so return value can be guaranteed if multiple threads compete to unlock.
This commit is contained in:
parent
fcc3adc2f9
commit
9bebea882a
1 changed files with 37 additions and 13 deletions
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 1995,1996, 1997, 2000, 2001 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1995,1996, 1997, 2000, 2001, 2004 Free Software Foundation, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -26,12 +26,14 @@
|
|||
#include "libguile/arbiters.h"
|
||||
|
||||
|
||||
/* {Arbiters}
|
||||
*
|
||||
* These procedures implement synchronization primitives. Processors
|
||||
* with an atomic test-and-set instruction can use it here (and not
|
||||
* SCM_DEFER_INTS).
|
||||
*/
|
||||
/* ENHANCE-ME: If the cpu has an atomic test-and-set instruction it could be
|
||||
used instead of a mutex in try-arbiter and release-arbiter.
|
||||
|
||||
For the i386 family, cmpxchg would suit but it's only available on 80486
|
||||
and higher so that would have to be checked, perhaps at run-time when
|
||||
setting up the definitions of the scheme procedures, or at compile time
|
||||
if we interpret a host cpu type like "i686" to mean not less than that
|
||||
chip. */
|
||||
|
||||
static scm_t_bits scm_tc16_arbiter;
|
||||
|
||||
|
@ -62,6 +64,12 @@ SCM_DEFINE (scm_make_arbiter, "make-arbiter", 1, 0, 0,
|
|||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
||||
/* The mutex here is so two threads can't both see the arbiter unlocked and
|
||||
both proceed to lock and return #t. The arbiter itself wouldn't be
|
||||
corrupted by this, but two threads both getting #t would be entirely
|
||||
contrary to the intended semantics. */
|
||||
|
||||
SCM_DEFINE (scm_try_arbiter, "try-arbiter", 1, 0, 0,
|
||||
(SCM arb),
|
||||
"Return @code{#t} and lock the arbiter @var{arb} if the arbiter\n"
|
||||
|
@ -69,7 +77,8 @@ SCM_DEFINE (scm_try_arbiter, "try-arbiter", 1, 0, 0,
|
|||
#define FUNC_NAME s_scm_try_arbiter
|
||||
{
|
||||
SCM_VALIDATE_SMOB (1, arb, arbiter);
|
||||
SCM_DEFER_INTS;
|
||||
|
||||
scm_mutex_lock (&scm_i_misc_mutex);
|
||||
if (SCM_ARB_LOCKED(arb))
|
||||
arb = SCM_BOOL_F;
|
||||
else
|
||||
|
@ -77,23 +86,38 @@ SCM_DEFINE (scm_try_arbiter, "try-arbiter", 1, 0, 0,
|
|||
SCM_LOCK_ARB(arb);
|
||||
arb = SCM_BOOL_T;
|
||||
}
|
||||
SCM_ALLOW_INTS;
|
||||
scm_mutex_unlock (&scm_i_misc_mutex);
|
||||
return arb;
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
||||
SCM_DEFINE (scm_release_arbiter, "release-arbiter", 1, 0, 0,
|
||||
/* The mutex here is so two threads can't both see the arbiter locked and
|
||||
both proceed to unlock and return #t. The arbiter itself wouldn't be
|
||||
corrupted by this, but we don't want two threads both thinking they were
|
||||
the unlocker. The intended usage is for the code which locked to be
|
||||
responsible for unlocking, but we guarantee the return value even if
|
||||
multiple threads compete. */
|
||||
|
||||
SCM_DEFINE (scm_release_arbiter, "release-arbiter", 1, 0, 0,
|
||||
(SCM arb),
|
||||
"Return @code{#t} and unlock the arbiter @var{arb} if the\n"
|
||||
"arbiter was locked. Otherwise, return @code{#f}.")
|
||||
#define FUNC_NAME s_scm_release_arbiter
|
||||
{
|
||||
SCM ret;
|
||||
SCM_VALIDATE_SMOB (1, arb, arbiter);
|
||||
|
||||
scm_mutex_lock (&scm_i_misc_mutex);
|
||||
if (!SCM_ARB_LOCKED(arb))
|
||||
return SCM_BOOL_F;
|
||||
SCM_UNLOCK_ARB (arb);
|
||||
return SCM_BOOL_T;
|
||||
ret = SCM_BOOL_F;
|
||||
else
|
||||
{
|
||||
SCM_UNLOCK_ARB (arb);
|
||||
ret = SCM_BOOL_T;
|
||||
}
|
||||
scm_mutex_unlock (&scm_i_misc_mutex);
|
||||
return ret;
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue