diff options
-rw-r--r-- | libguile/atomic.c | 19 | ||||
-rw-r--r-- | libguile/intrinsics.c | 18 |
2 files changed, 30 insertions, 7 deletions
diff --git a/libguile/atomic.c b/libguile/atomic.c index 604a21e5a..174d26b76 100644 --- a/libguile/atomic.c +++ b/libguile/atomic.c @@ -1,4 +1,4 @@ -/* Copyright 2016,2018 +/* Copyright 2016,2018-2019 Free Software Foundation, Inc. This file is part of Guile. @@ -102,10 +102,21 @@ SCM_DEFINE (scm_atomic_box_compare_and_swap_x, "if the return value is @code{eq?} to @var{expected}.") #define FUNC_NAME s_scm_atomic_box_compare_and_swap_x { + SCM result = expected; + SCM_VALIDATE_ATOMIC_BOX (1, box); - scm_atomic_compare_and_swap_scm (scm_atomic_box_loc (box), - &expected, desired); - return expected; + while (!scm_atomic_compare_and_swap_scm (scm_atomic_box_loc (box), + &result, desired) + && scm_is_eq (result, expected)) + { + /* 'scm_atomic_compare_and_swap_scm' has spuriously failed, + i.e. it has returned 0 to indicate failure, although the + observed value is 'eq?' to EXPECTED. In this case, we *must* + try again, because the API of 'atomic-box-compare-and-swap!' + provides no way to indicate to the caller that the exchange + failed when the observed value is 'eq?' to EXPECTED. */ + } + return result; } #undef FUNC_NAME diff --git a/libguile/intrinsics.c b/libguile/intrinsics.c index a619fda90..437441032 100644 --- a/libguile/intrinsics.c +++ b/libguile/intrinsics.c @@ -1,4 +1,4 @@ -/* Copyright 2018 +/* Copyright 2018-2019 Free Software Foundation, Inc. This file is part of Guile. @@ -459,8 +459,20 @@ atomic_swap_scm (SCM *loc, SCM val) static SCM atomic_compare_and_swap_scm (SCM *loc, SCM expected, SCM desired) { - scm_atomic_compare_and_swap_scm (loc, &expected, desired); - return expected; + SCM result = expected; + + while (!scm_atomic_compare_and_swap_scm (loc, &result, desired) + && scm_is_eq (result, expected)) + { + /* 'scm_atomic_compare_and_swap_scm' has spuriously failed, + i.e. it has returned 0 to indicate failure, although the + observed value is 'eq?' to EXPECTED. In this case, we *must* + try again, because the API of 'atomic-box-compare-and-swap!' + provides no way to indicate to the caller that the exchange + failed when the observed value is 'eq?' to EXPECTED. */ + } + + return result; } void |