===================================================================
--- recipe/files/gcc/libunixlib/gcccompat/atomics.c (revision 7723)
+++ recipe/files/gcc/libunixlib/gcccompat/atomics.c (working copy)
@@ -378,6 +378,28 @@
ATOMIC_OP_FETCH(or,(*ptr) |= val,unsigned)
ATOMIC_OP_FETCH(nand,(*ptr) = ~((*ptr) & val),unsigned)
+#define SYNC_LOCK_TEST_SET(size, type) \
+type \
+__builtin_sync_lock_test_and_set_##size (volatile type *ptr, type val) \
+{ \
+ type prev; \
+ \
+ __pthread_disable_ints (); \
+ \
+ prev = *ptr; \
+ *ptr = val; \
+ \
+ __pthread_enable_ints (); \
+ \
+ return prev; \
+} \
+__asm__(".hidden\t__builtin_sync_lock_test_and_set_"__STRING(size)"\n"); \
+__asm__(".global\t__sync_lock_test_and_set_"__STRING(size)"\n"); \
+__asm__("__sync_lock_test_and_set_"__STRING(size)"=__builtin_sync_lock_test_and_set_"__STRING(size));
+SYNC_LOCK_TEST_SET(1,char)
+SYNC_LOCK_TEST_SET(2,short)
+SYNC_LOCK_TEST_SET(8,long long)
+
#ifdef __ARM_EABI__
static int __cmpxchg (int oldval, int newval, volatile int *ptr)
@@ -397,25 +419,6 @@
return result;
}
-#else
-
-static int __cmpxchg (int oldval, int newval, volatile void *ptr)
-{
- int prev;
-
- __pthread_disable_ints();
-
- prev = *(int *)ptr;
- if (prev == oldval)
- *(int *)ptr = newval;
-
- __pthread_enable_ints();
-
- return prev;
-}
-
-#endif
-
int __builtin_sync_lock_test_and_set_4 (volatile int *ptr, int val)
{
int failure, oldval;
@@ -431,6 +434,12 @@
__asm__(".global\t__sync_lock_test_and_set_4\n"); \
__asm__("__sync_lock_test_and_set_4=__builtin_sync_lock_test_and_set_4");
+#else
+
+SYNC_LOCK_TEST_SET(4,int)
+
+#endif
+
void
__builtin_sync_synchronize (void)
{
#include <stdio.h>
int main(int argc, char *argv[]) {
static volatile int count;
int n;
setvbuf(stdout, NULL, _IONBF, 0);
printf("Testing __sync_lock_test_and_set...\n");
__sync_lock_test_and_set(&count, 5);
while ((n = __atomic_load_n(&count, __ATOMIC_SEQ_CST)) >= 0) {
printf("count = %d\n", n);
__sync_lock_test_and_set(&count, n - 1);
}
printf("done!\n");
return 0;
}
Hi
Attached is a patch that fixes the implementation of __sync_lock_test_and_set in non-EABI toolchains. Previously, __cmpxchg would return the previous value instead of a failure code, which would result in an endless loop if the previous value is non-zero. Implementations have also been provided for 1, 2 and 8 byte types.
A test program has also been attached which demonstrates the issue.
Regards
Cameron
No comments:
Post a Comment