diff options
author | anonymous <local@localhost> | 2010-06-27 17:13:07 +0000 |
---|---|---|
committer | anonymous <local@localhost> | 2010-06-27 17:13:07 +0000 |
commit | 7ca18cb7c08bf92db5946a66e312678c480eb819 (patch) | |
tree | 22dfcc5cf05ecad955cd15d9feb952f204a4b32b /src/guard.cc | |
download | libcxxrt-7ca18cb7c08bf92db5946a66e312678c480eb819.tar.gz libcxxrt-7ca18cb7c08bf92db5946a66e312678c480eb819.tar.bz2 libcxxrt-7ca18cb7c08bf92db5946a66e312678c480eb819.tar.xz |
Initial import.
Diffstat (limited to 'src/guard.cc')
-rw-r--r-- | src/guard.cc | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/src/guard.cc b/src/guard.cc new file mode 100644 index 0000000..172af47 --- /dev/null +++ b/src/guard.cc @@ -0,0 +1,44 @@ +#include <stdint.h> +#include <pthread.h> + +static int32_t *low_32_bits(int64_t *ptr) +{ + int32_t *low= (int32_t*)ptr; + // Test if the machine is big endian - constant propagation at compile time + // should eliminate this completely. + int one = 1; + if (*(char*)&one != 1) + { + low++; + } + return low; +} + +extern "C" int __cxa_guard_acquire(int64_t *guard_object) +{ + char first_byte = (*guard_object) >> 56; + if (1 == first_byte) { return 0; } + int32_t *lock = low_32_bits(guard_object); + while (!__sync_bool_compare_and_swap(lock, 0, 1)) + { + // TODO: Use some of the remaining 24 bits to define a mutex to sleep + // on. Whether this is actually worth bothering with depends on + // whether there is likely to be any contention. + sched_yield(); + } + return 1; +} + +extern "C" void __cxa_guard_abort(int64_t *guard_object) +{ + int32_t *lock = low_32_bits(guard_object); + *lock = 0; +} +extern "C" void __cxa_guard_release(int64_t *guard_object) +{ + // Set the first byte to 1 + *guard_object |= ((int64_t)1) << 57; + __cxa_guard_abort(guard_object); +} + + |