[waffle] [PATCH] wcore_error_unittest: Fix non-terminating loop

Chad Versace chad.versace at linux.intel.com
Thu May 31 16:14:21 PDT 2012


When compiled with `clang -O3`, the following code in
test_wcore_error_thread_local() is translated into a non-terminating loop:
    original source:
        int num_threads_waiting = 0;
        ...
        while (num_threads_waiting < NUM_THREADS)
            ;;

    assembly:
        5ac movl    $0x0,0x94(%rsp)
        ...
        66d cmpl    $0x2,0x94(%rsp)
        674 noop
        675 jle     740
        ...
        740 jmp     740

The problem is that the compiler 1) assumes that num_threads_waiting is
accessed only within the local scope, 2) concludes that value of
num_threads_waiting is always 0, 3) and therefore generates
a non-terminating loop.  Assumption (1) is false because others threads
asynchronously increment num_threads_waiting.

The solution is to declare num_threads_waiting as volatile. From the C99
spec:
    A volatile declaration may be used to describe [...] an object
    accessed by an asynchronously interrupting function. Actions on
    objects so declared shall not be ‘‘optimized out’’ by an
    implementation or reordered except as permitted by the rules for
    evaluating expressions.
This change forces the compiler to generate a memory access each time the
variable is read and prevents the compiler from making any assumptions
about the variable's value. Below is the fixed source and generated
assembly.
    original source:
        volatile int num_threads_waiting = 0;
        ...
        while (num_threads_waiting < NUM_THREADS)
            ;;

    assembly:
        5ac movl    $0x0,0x94(%rsp)
        ...
        670 cmpl    $0x3,0x94(%rsp)
        674 noop
        678 jl      670

CC: Justen Jordan <jljordan at gmail.com>
CC: Pauli Nieminen <pauli.nieminen at linux.intel.com>
Signed-off-by: Chad Versace <chad.versace at linux.intel.com>
---
 tests/unittests/waffle/core/wcore_error_unittest.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/unittests/waffle/core/wcore_error_unittest.c b/tests/unittests/waffle/core/wcore_error_unittest.c
index 06ebb78..134fdcd 100644
--- a/tests/unittests/waffle/core/wcore_error_unittest.c
+++ b/tests/unittests/waffle/core/wcore_error_unittest.c
@@ -148,7 +148,7 @@ struct thread_arg {
     pthread_cond_t *cond;
 
     /// Number of threads waiting on `cond`.
-    int *num_threads_waiting;
+    volatile int *num_threads_waiting;
 };
 
 /// The start routine given to threads in test wcore_error.thread_local.
@@ -190,7 +190,7 @@ TEST(wcore_error, thread_local)
 {
     pthread_mutex_t mutex;
     pthread_cond_t cond;
-    int num_threads_waiting = 0;
+    volatile int num_threads_waiting = 0;
 
     pthread_t threads[NUM_THREADS];
     struct thread_arg thread_args[NUM_THREADS];
-- 
1.7.10.3



More information about the waffle mailing list