mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-10 05:50:26 +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
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -26,12 +26,14 @@
|
||||||
#include "libguile/arbiters.h"
|
#include "libguile/arbiters.h"
|
||||||
|
|
||||||
|
|
||||||
/* {Arbiters}
|
/* 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.
|
||||||
* These procedures implement synchronization primitives. Processors
|
|
||||||
* with an atomic test-and-set instruction can use it here (and not
|
For the i386 family, cmpxchg would suit but it's only available on 80486
|
||||||
* SCM_DEFER_INTS).
|
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;
|
static scm_t_bits scm_tc16_arbiter;
|
||||||
|
|
||||||
|
@ -62,6 +64,12 @@ SCM_DEFINE (scm_make_arbiter, "make-arbiter", 1, 0, 0,
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#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_DEFINE (scm_try_arbiter, "try-arbiter", 1, 0, 0,
|
||||||
(SCM arb),
|
(SCM arb),
|
||||||
"Return @code{#t} and lock the arbiter @var{arb} if the arbiter\n"
|
"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
|
#define FUNC_NAME s_scm_try_arbiter
|
||||||
{
|
{
|
||||||
SCM_VALIDATE_SMOB (1, arb, arbiter);
|
SCM_VALIDATE_SMOB (1, arb, arbiter);
|
||||||
SCM_DEFER_INTS;
|
|
||||||
|
scm_mutex_lock (&scm_i_misc_mutex);
|
||||||
if (SCM_ARB_LOCKED(arb))
|
if (SCM_ARB_LOCKED(arb))
|
||||||
arb = SCM_BOOL_F;
|
arb = SCM_BOOL_F;
|
||||||
else
|
else
|
||||||
|
@ -77,23 +86,38 @@ SCM_DEFINE (scm_try_arbiter, "try-arbiter", 1, 0, 0,
|
||||||
SCM_LOCK_ARB(arb);
|
SCM_LOCK_ARB(arb);
|
||||||
arb = SCM_BOOL_T;
|
arb = SCM_BOOL_T;
|
||||||
}
|
}
|
||||||
SCM_ALLOW_INTS;
|
scm_mutex_unlock (&scm_i_misc_mutex);
|
||||||
return arb;
|
return arb;
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
|
||||||
|
/* 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_DEFINE (scm_release_arbiter, "release-arbiter", 1, 0, 0,
|
||||||
(SCM arb),
|
(SCM arb),
|
||||||
"Return @code{#t} and unlock the arbiter @var{arb} if the\n"
|
"Return @code{#t} and unlock the arbiter @var{arb} if the\n"
|
||||||
"arbiter was locked. Otherwise, return @code{#f}.")
|
"arbiter was locked. Otherwise, return @code{#f}.")
|
||||||
#define FUNC_NAME s_scm_release_arbiter
|
#define FUNC_NAME s_scm_release_arbiter
|
||||||
{
|
{
|
||||||
|
SCM ret;
|
||||||
SCM_VALIDATE_SMOB (1, arb, arbiter);
|
SCM_VALIDATE_SMOB (1, arb, arbiter);
|
||||||
|
|
||||||
|
scm_mutex_lock (&scm_i_misc_mutex);
|
||||||
if (!SCM_ARB_LOCKED(arb))
|
if (!SCM_ARB_LOCKED(arb))
|
||||||
return SCM_BOOL_F;
|
ret = SCM_BOOL_F;
|
||||||
SCM_UNLOCK_ARB (arb);
|
else
|
||||||
return SCM_BOOL_T;
|
{
|
||||||
|
SCM_UNLOCK_ARB (arb);
|
||||||
|
ret = SCM_BOOL_T;
|
||||||
|
}
|
||||||
|
scm_mutex_unlock (&scm_i_misc_mutex);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue