The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame^] | 1 | /* |
| 2 | * one_time_construction.cpp |
| 3 | * |
| 4 | * Copyright 2006 The Android Open Source Project |
| 5 | * |
| 6 | * This file contains C++ ABI support functions for one time |
| 7 | * constructors as defined in the "Run-time ABI for the ARM Architecture" |
| 8 | * section 4.4.2 |
| 9 | */ |
| 10 | |
| 11 | #include <stddef.h> |
| 12 | #include <sys/atomics.h> |
| 13 | |
| 14 | extern "C" int __futex_wait(volatile void *ftx, int val, const struct timespec *timeout); |
| 15 | extern "C" int __futex_wake(volatile void *ftx, int count); |
| 16 | |
| 17 | |
| 18 | extern "C" int __cxa_guard_acquire(int volatile * gv) |
| 19 | { |
| 20 | // 0 -> 2, return 1 |
| 21 | // 2 -> 6, wait and return 0 |
| 22 | // 6 untouched, wait and return 0 |
| 23 | // 1 untouched, return 0 |
| 24 | retry: |
| 25 | if (__atomic_cmpxchg(0, 0x2, gv) == 0) |
| 26 | return 1; |
| 27 | |
| 28 | __atomic_cmpxchg(0x2, 0x6, gv); // Indicate there is a waiter |
| 29 | __futex_wait(gv, 0x6, NULL); |
| 30 | if(*gv != 1) // __cxa_guard_abort was called, let every thread try since there is no return code for this condition |
| 31 | goto retry; |
| 32 | return 0; |
| 33 | } |
| 34 | |
| 35 | extern "C" void __cxa_guard_release(int volatile * gv) |
| 36 | { |
| 37 | // 2 -> 1 |
| 38 | // 6 -> 1, and wake |
| 39 | if (__atomic_cmpxchg(0x2, 0x1, gv) == 0) |
| 40 | return; |
| 41 | |
| 42 | *gv = 0x1; |
| 43 | __futex_wake(gv, 0x7fffffff); |
| 44 | } |
| 45 | |
| 46 | extern "C" void __cxa_guard_abort(int volatile * gv) |
| 47 | { |
| 48 | *gv = 0; |
| 49 | __futex_wake(gv, 0x7fffffff); |
| 50 | } |