diff options
Diffstat (limited to 'libguile/atomic.c')
-rw-r--r-- | libguile/atomic.c | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/libguile/atomic.c b/libguile/atomic.c index 950874030..180622b47 100644 --- a/libguile/atomic.c +++ b/libguile/atomic.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2016 Free Software Foundation, Inc. +/* Copyright (C) 2016, 2018 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 License @@ -95,10 +95,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 |