Author: hhinnant Date: Tue May 24 17:01:16 2011 New Revision: 132009 URL: http://llvm.org/viewvc/llvm-project?rev=132009&view=rev Log: Introduce cxa_virtual.cpp and cxa_guard.cpp. Contributed by Nick Lewycky, Howard Hinnant and John McCall
Added: libcxxabi/trunk/src/cxa_guard.cpp libcxxabi/trunk/src/cxa_virtual.cpp libcxxabi/trunk/test/test_guard.cpp Modified: libcxxabi/trunk/include/cxxabi.h Modified: libcxxabi/trunk/include/cxxabi.h URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/include/cxxabi.h?rev=132009&r1=132008&r2=132009&view=diff ============================================================================== --- libcxxabi/trunk/include/cxxabi.h (original) +++ libcxxabi/trunk/include/cxxabi.h Tue May 24 17:01:16 2011 @@ -55,6 +55,9 @@ // 3.2.6 Pure Virtual Function API extern void __cxa_pure_virtual(void); +// 3.2.7 Deleted Virtual Function API +extern void __cxa_deleted_virtual(void); + // 3.3.2 One-time Construction API extern int __cxa_guard_acquire(uint64_t*); extern void __cxa_guard_release(uint64_t*); Added: libcxxabi/trunk/src/cxa_guard.cpp URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/cxa_guard.cpp?rev=132009&view=auto ============================================================================== --- libcxxabi/trunk/src/cxa_guard.cpp (added) +++ libcxxabi/trunk/src/cxa_guard.cpp Tue May 24 17:01:16 2011 @@ -0,0 +1,174 @@ +//===---------------------------- cxa_guard.cpp ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "cxxabi.h" + +#include <pthread.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> + +namespace __cxxabiv1 +{ + +namespace +{ + +void abort_message(const char* s) +{ + fputs(s, stderr); + ::abort(); +} + +pthread_mutex_t guard_mut = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t guard_cv = PTHREAD_COND_INITIALIZER; + +#if __APPLE__ + +typedef uint32_t lock_type; + +#if __LITTLE_ENDIAN__ + +inline +lock_type +get_lock(uint64_t x) +{ + return static_cast<lock_type>(x >> 32); +} + +inline +void +set_lock(uint64_t& x, lock_type y) +{ + x = static_cast<uint64_t>(y) << 32; +} + +#else // __LITTLE_ENDIAN__ + +inline +lock_type +get_lock(uint64_t x) +{ + return static_cast<lock_type>(x); +} + +inline +void +set_lock(uint64_t& x, lock_type y) +{ + x = y; +} + +#endif // __LITTLE_ENDIAN__ + +#else // __APPLE__ + +typedef bool lock_type; + +inline +lock_type +get_lock(uint64_t x) +{ + union + { + uint64_t guard; + uint8_t lock[2]; + } f = {x}; + return f.lock[1] != 0; +} + +inline +void +set_lock(uint64_t& x, lock_type y) +{ + union + { + uint64_t guard; + uint8_t lock[2]; + } f = {0}; + f.lock[1] = y; + x = f.guard; +} + +#endif // __APPLE__ + +} // unnamed namespace + +extern "C" +{ + +int __cxa_guard_acquire(uint64_t* guard_object) +{ + char* initialized = (char*)guard_object; + if (pthread_mutex_lock(&guard_mut)) + abort_message("__cxa_guard_acquire failed to acquire mutex"); + int result = *initialized == 0; + if (result) + { +#if __APPLE__ + const lock_type id = pthread_mach_thread_np(pthread_self()); + lock_type lock = get_lock(*guard_object); + if (lock) + { + // if this thread set lock for this same guard_object, abort + if (lock == id) + abort_message("__cxa_guard_acquire detected deadlock"); + do + { + if (pthread_cond_wait(&guard_cv, &guard_mut)) + abort_message("__cxa_guard_acquire condition variable wait failed"); + lock = get_lock(*guard_object); + } while (lock); + result = *initialized == 0; + if (result) + set_lock(*guard_object, id); + } + else + set_lock(*guard_object, id); +#else // __APPLE__ + while (get_lock(*guard_object)) + if (pthread_cond_wait(&guard_cv, &guard_mut)) + abort_message("__cxa_guard_acquire condition variable wait failed"); + result = *initialized == 0; + if (result) + set_lock(*guard_object, true); +#endif // __APPLE__ + } + if (pthread_mutex_unlock(&guard_mut)) + abort_message("__cxa_guard_acquire failed to release mutex"); + return result; +} + +void __cxa_guard_release(uint64_t* guard_object) +{ + char* initialized = (char*)guard_object; + if (pthread_mutex_lock(&guard_mut)) + abort_message("__cxa_guard_release failed to acquire mutex"); + *guard_object = 0; + *initialized = 1; + if (pthread_mutex_unlock(&guard_mut)) + abort_message("__cxa_guard_release failed to release mutex"); + if (pthread_cond_broadcast(&guard_cv)) + abort_message("__cxa_guard_release failed to broadcast condition variable"); +} + +void __cxa_guard_abort(uint64_t* guard_object) +{ + if (pthread_mutex_lock(&guard_mut)) + abort_message("__cxa_guard_abort failed to acquire mutex"); + *guard_object = 0; + if (pthread_mutex_unlock(&guard_mut)) + abort_message("__cxa_guard_abort failed to release mutex"); + if (pthread_cond_broadcast(&guard_cv)) + abort_message("__cxa_guard_abort failed to broadcast condition variable"); +} + +} // extern "C" + +} // __cxxabiv1 Added: libcxxabi/trunk/src/cxa_virtual.cpp URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/cxa_virtual.cpp?rev=132009&view=auto ============================================================================== --- libcxxabi/trunk/src/cxa_virtual.cpp (added) +++ libcxxabi/trunk/src/cxa_virtual.cpp Tue May 24 17:01:16 2011 @@ -0,0 +1,33 @@ +//===-------------------------- cxa_virtual.cpp ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "cxxabi.h" + +#include <stdio.h> +#include <stdlib.h> + +namespace __cxxabiv1 +{ + +extern "C" +{ + +void __cxa_pure_virtual(void) { + fputs("Pure virtual function called!\n", stderr); + abort(); +} + +void __cxa_deleted_virtual(void) { + fputs("Deleted virtual function called!\n", stderr); + abort(); +} + +} // extern "C" + +} // abi Added: libcxxabi/trunk/test/test_guard.cpp URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/test/test_guard.cpp?rev=132009&view=auto ============================================================================== --- libcxxabi/trunk/test/test_guard.cpp (added) +++ libcxxabi/trunk/test/test_guard.cpp Tue May 24 17:01:16 2011 @@ -0,0 +1,59 @@ +//===----------------------------- test_guard.cpp -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "cxxabi.h" + +#include <cassert> + +namespace test1 { + static int run_count = 0; + int increment() { + ++run_count; + return 0; + } + void helper() { + static int a = increment(); + } + void test() { + static int a = increment(); + assert(run_count == 1); + static int b = increment(); + assert(run_count == 2); + helper(); + assert(run_count == 3); + helper(); + assert(run_count == 3); + } +} + +namespace test2 { + static int run_count = 0; + int increment() { + ++run_count; + throw 0; + } + void helper() { + try { + static int a = increment(); + assert(0); + } catch (...) {} + } + void test() { + helper(); + assert(run_count == 1); + helper(); + assert(run_count == 2); + } +} + +int main() +{ + test1::test(); + test2::test(); +} _______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits