[cfe-commits] [libcxxabi] r132009 - in /libcxxabi/trunk: include/cxxabi.h src/cxa_guard.cpp src/cxa_virtual.cpp test/test_guard.cpp
Howard Hinnant
hhinnant at apple.com
Tue May 24 15:01:16 PDT 2011
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();
+}
More information about the cfe-commits
mailing list