diff options
author | David Chisnall <dchisnall@pathscale.com> | 2011-11-25 11:24:48 +0000 |
---|---|---|
committer | David Chisnall <dchisnall@pathscale.com> | 2011-11-25 11:24:48 +0000 |
commit | c996267251a83097aa4bac0b350801e92d6fc20a (patch) | |
tree | dc56a57a0c2c412a83526273eb315c98cb902c65 /src | |
parent | 75ca8259acea380d867f136738e3835250ea0855 (diff) | |
download | libcxxrt-c996267251a83097aa4bac0b350801e92d6fc20a.tar.gz libcxxrt-c996267251a83097aa4bac0b350801e92d6fc20a.tar.bz2 libcxxrt-c996267251a83097aa4bac0b350801e92d6fc20a.tar.xz |
ARM expects 32-bit guards for static variables.
Diffstat (limited to 'src')
-rw-r--r-- | src/guard.cc | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/src/guard.cc b/src/guard.cc index 23a4bae..f236053 100644 --- a/src/guard.cc +++ b/src/guard.cc @@ -16,6 +16,59 @@ */ #include <stdint.h> #include <pthread.h> +#include <assert.h> + +#ifdef __arm__ +// ARM ABI - 32-bit guards. + +/** + * Acquires a lock on a guard, returning 0 if the object has already been + * initialised, and 1 if it has not. If the object is already constructed then + * this function just needs to read a byte from memory and return. + */ +extern "C" int __cxa_guard_acquire(volatile int32_t *guard_object) +{ + if ((1<<31) == *guard_object) { return 0; } + // If we can atomically move the value from 0 -> 1, then this is + // uninitialised. + if (__sync_bool_compare_and_swap(guard_object, 0, 1)) + { + return 1; + } + // If the value is not 0, some other thread was initialising this. Spin + // until it's finished. + while (__sync_bool_compare_and_swap(guard_object, (1<<31), (1<<31))) + { + // If the other thread aborted, then we grab the lock + if (__sync_bool_compare_and_swap(guard_object, 0, 1)) + { + return 1; + } + sched_yield(); + } + return 0; +} + +/** + * Releases the lock without marking the object as initialised. This function + * is called if initialising a static causes an exception to be thrown. + */ +extern "C" void __cxa_guard_abort(int32_t *guard_object) +{ + assert(__sync_bool_compare_and_swap(guard_object, 1, 0)); +} +/** + * Releases the guard and marks the object as initialised. This function is + * called after successful initialisation of a static. + */ +extern "C" void __cxa_guard_release(int32_t *guard_object) +{ + assert(__sync_bool_compare_and_swap(guard_object, 1, (1<<31))); +} + + +#else +// Itanium ABI: 64-bit guards /** * Returns a pointer to the low 32 bits in a 64-bit value, respecting the @@ -78,3 +131,4 @@ extern "C" void __cxa_guard_release(int64_t *guard_object) __cxa_guard_abort(guard_object); } +#endif |