[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