summaryrefslogtreecommitdiff
path: root/src/guard.cc
diff options
context:
space:
mode:
authoranonymous <local@localhost>2010-06-27 17:13:07 +0000
committeranonymous <local@localhost>2010-06-27 17:13:07 +0000
commit7ca18cb7c08bf92db5946a66e312678c480eb819 (patch)
tree22dfcc5cf05ecad955cd15d9feb952f204a4b32b /src/guard.cc
downloadlibcxxrt-7ca18cb7c08bf92db5946a66e312678c480eb819.tar.gz
libcxxrt-7ca18cb7c08bf92db5946a66e312678c480eb819.tar.bz2
libcxxrt-7ca18cb7c08bf92db5946a66e312678c480eb819.tar.xz
Initial import.
Diffstat (limited to 'src/guard.cc')
-rw-r--r--src/guard.cc44
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);
+}
+
+