[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