1 /* 2 * Copyright 2010-2012 PathScale, Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * 1. Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. 9 * 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 15 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 /** 28 * guard.cc: Functions for thread-safe static initialisation. 29 * 30 * Static values in C++ can be initialised lazily their first use. This file 31 * contains functions that are used to ensure that two threads attempting to 32 * initialize the same static do not call the constructor twice. This is 33 * important because constructors can have side effects, so calling the 34 * constructor twice may be very bad. 35 * 36 * Statics that require initialisation are protected by a 64-bit value. Any 37 * platform that can do 32-bit atomic test and set operations can use this 38 * value as a low-overhead lock. Because statics (in most sane code) are 39 * accessed far more times than they are initialised, this lock implementation 40 * is heavily optimised towards the case where the static has already been 41 * initialised. 42 */ 43 #include <stdint.h> 44 #include <pthread.h> 45 #include <assert.h> 46 47 #ifdef __arm__ 48 // ARM ABI - 32-bit guards. 49 50 /** 51 * Acquires a lock on a guard, returning 0 if the object has already been 52 * initialised, and 1 if it has not. If the object is already constructed then 53 * this function just needs to read a byte from memory and return. 54 */ 55 extern "C" int __cxa_guard_acquire(volatile int32_t *guard_object) 56 { 57 if ((1<<31) == *guard_object) { return 0; } 58 // If we can atomically move the value from 0 -> 1, then this is 59 // uninitialised. 60 if (__sync_bool_compare_and_swap(guard_object, 0, 1)) 61 { 62 return 1; 63 } 64 // If the value is not 0, some other thread was initialising this. Spin 65 // until it's finished. 66 while (__sync_bool_compare_and_swap(guard_object, (1<<31), (1<<31))) 67 { 68 // If the other thread aborted, then we grab the lock 69 if (__sync_bool_compare_and_swap(guard_object, 0, 1)) 70 { 71 return 1; 72 } 73 sched_yield(); 74 } 75 return 0; 76 } 77 78 /** 79 * Releases the lock without marking the object as initialised. This function 80 * is called if initialising a static causes an exception to be thrown. 81 */ 82 extern "C" void __cxa_guard_abort(int32_t *guard_object) 83 { 84 assert(__sync_bool_compare_and_swap(guard_object, 1, 0)); 85 } 86 /** 87 * Releases the guard and marks the object as initialised. This function is 88 * called after successful initialisation of a static. 89 */ 90 extern "C" void __cxa_guard_release(int32_t *guard_object) 91 { 92 assert(__sync_bool_compare_and_swap(guard_object, 1, (1<<31))); 93 } 94 95 96 #else 97 // Itanium ABI: 64-bit guards 98 99 /** 100 * Returns a pointer to the low 32 bits in a 64-bit value, respecting the 101 * platform's byte order. 102 */ 103 static int32_t *low_32_bits(volatile int64_t *ptr) 104 { 105 int32_t *low= (int32_t*)ptr; 106 // Test if the machine is big endian - constant propagation at compile time 107 // should eliminate this completely. 108 int one = 1; 109 if (*(char*)&one != 1) 110 { 111 low++; 112 } 113 return low; 114 } 115 116 /** 117 * Acquires a lock on a guard, returning 0 if the object has already been 118 * initialised, and 1 if it has not. If the object is already constructed then 119 * this function just needs to read a byte from memory and return. 120 */ 121 extern "C" int __cxa_guard_acquire(volatile int64_t *guard_object) 122 { 123 char first_byte = (*guard_object) >> 56; 124 if (1 == first_byte) { return 0; } 125 int32_t *lock = low_32_bits(guard_object); 126 // Simple spin lock using the low 32 bits. We assume that concurrent 127 // attempts to initialize statics are very rare, so we don't need to 128 // optimise for the case where we have lots of threads trying to acquire 129 // the lock at the same time. 130 while (!__sync_bool_compare_and_swap_4(lock, 0, 1)) 131 { 132 if (1 == ((*guard_object) >> 56)) 133 { 134 break; 135 } 136 sched_yield(); 137 } 138 // We have to test the guard again, in case another thread has performed 139 // the initialisation while we were trying to acquire the lock. 140 first_byte = (*guard_object) >> 56; 141 return (1 != first_byte); 142 } 143 144 /** 145 * Releases the lock without marking the object as initialised. This function 146 * is called if initialising a static causes an exception to be thrown. 147 */ 148 extern "C" void __cxa_guard_abort(int64_t *guard_object) 149 { 150 int32_t *lock = low_32_bits(guard_object); 151 *lock = 0; 152 } 153 /** 154 * Releases the guard and marks the object as initialised. This function is 155 * called after successful initialisation of a static. 156 */ 157 extern "C" void __cxa_guard_release(int64_t *guard_object) 158 { 159 // Set the first byte to 1 160 *guard_object |= ((int64_t)1) << 56; 161 __cxa_guard_abort(guard_object); 162 } 163 164 #endif 165