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> |
David 'Digit' Turner | d466780 | 2010-06-11 13:18:41 -0700 | [diff] [blame^] | 13 | #include <bionic_futex.h> |
| 14 | #include <bionic_atomic_inline.h> |
The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 15 | |
| 16 | extern "C" int __cxa_guard_acquire(int volatile * gv) |
| 17 | { |
| 18 | // 0 -> 2, return 1 |
| 19 | // 2 -> 6, wait and return 0 |
| 20 | // 6 untouched, wait and return 0 |
| 21 | // 1 untouched, return 0 |
| 22 | retry: |
David 'Digit' Turner | d466780 | 2010-06-11 13:18:41 -0700 | [diff] [blame^] | 23 | if (__atomic_cmpxchg(0, 0x2, gv) == 0) { |
| 24 | ANDROID_MEMBAR_FULL(); |
The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 25 | return 1; |
David 'Digit' Turner | d466780 | 2010-06-11 13:18:41 -0700 | [diff] [blame^] | 26 | } |
The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 27 | __atomic_cmpxchg(0x2, 0x6, gv); // Indicate there is a waiter |
| 28 | __futex_wait(gv, 0x6, NULL); |
David 'Digit' Turner | d466780 | 2010-06-11 13:18:41 -0700 | [diff] [blame^] | 29 | |
The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 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; |
David 'Digit' Turner | d466780 | 2010-06-11 13:18:41 -0700 | [diff] [blame^] | 32 | |
| 33 | ANDROID_MEMBAR_FULL(); |
The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 34 | return 0; |
| 35 | } |
| 36 | |
| 37 | extern "C" void __cxa_guard_release(int volatile * gv) |
| 38 | { |
| 39 | // 2 -> 1 |
| 40 | // 6 -> 1, and wake |
David 'Digit' Turner | d466780 | 2010-06-11 13:18:41 -0700 | [diff] [blame^] | 41 | ANDROID_MEMBAR_FULL(); |
| 42 | if (__atomic_cmpxchg(0x2, 0x1, gv) == 0) { |
The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 43 | return; |
David 'Digit' Turner | d466780 | 2010-06-11 13:18:41 -0700 | [diff] [blame^] | 44 | } |
The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 45 | |
| 46 | *gv = 0x1; |
| 47 | __futex_wake(gv, 0x7fffffff); |
| 48 | } |
| 49 | |
| 50 | extern "C" void __cxa_guard_abort(int volatile * gv) |
| 51 | { |
David 'Digit' Turner | d466780 | 2010-06-11 13:18:41 -0700 | [diff] [blame^] | 52 | ANDROID_MEMBAR_FULL(); |
The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 53 | *gv = 0; |
| 54 | __futex_wake(gv, 0x7fffffff); |
| 55 | } |