am fb8cc3b0: Ensure the correct happens-before relationship between set / get functions.

* commit 'fb8cc3b07be8677604df8df8e7b270edc2000aef':
  Ensure the correct happens-before relationship between set / get functions.
diff --git a/src/atomic.h b/src/atomic.h
new file mode 100644
index 0000000..bcd8a47
--- /dev/null
+++ b/src/atomic.h
@@ -0,0 +1,29 @@
+
+#ifndef __has_builtin
+#define __has_builtin(x) 0
+#endif
+#ifndef __has_feature
+#define __has_feature(x) 0
+#endif
+/**
+ * Swap macro that enforces a happens-before relationship with a corresponding
+ * ATOMIC_LOAD.
+ */
+#if __has_feature(cxx_atomic)
+#define ATOMIC_SWAP(addr, val)\
+	__atomic_exchange(addr, val, __ATOMIC_ACQ_REL)
+#elif __has_builtin(__sync_swap)
+#define ATOMIC_SWAP(addr, val)\
+	__sync_swap(addr, val)
+#else
+#define ATOMIC_SWAP(addr, val)\
+	__sync_lock_test_and_set(addr, val)
+#endif
+
+#if __has_feature(cxx_atomic)
+#define ATOMIC_LOAD(addr)\
+	__atomic_load(addr, __ATOMIC_ACQUIRE)
+#else
+#define ATOMIC_LOAD(addr)\
+	(__sync_synchronize(), *addr)
+#endif
diff --git a/src/exception.cc b/src/exception.cc
index fe56297..6e841ef 100644
--- a/src/exception.cc
+++ b/src/exception.cc
@@ -32,6 +32,7 @@
 #include <pthread.h>
 #include "typeinfo.h"
 #include "dwarf_eh.h"
+#include "atomic.h"
 #include "cxxabi.h"
 
 #pragma weak pthread_key_create
@@ -1328,7 +1329,7 @@
 	{
 		if (thread_local_handlers) { return pathscale::set_unexpected(f); }
 
-		return __sync_lock_test_and_set(&unexpectedHandler, f);
+		return ATOMIC_SWAP(&terminateHandler, f);
 	}
 	/**
 	 * Sets the function that is called to terminate the program.
@@ -1336,7 +1337,8 @@
 	terminate_handler set_terminate(terminate_handler f) throw()
 	{
 		if (thread_local_handlers) { return pathscale::set_terminate(f); }
-		return __sync_lock_test_and_set(&terminateHandler, f);
+
+		return ATOMIC_SWAP(&terminateHandler, f);
 	}
 	/**
 	 * Terminates the program, calling a custom terminate implementation if
@@ -1390,7 +1392,7 @@
 		{
 			return info->unexpectedHandler;
 		}
-		return unexpectedHandler;
+		return ATOMIC_LOAD(&unexpectedHandler);
 	}
 	/**
 	 * Returns the current terminate handler.
@@ -1402,7 +1404,7 @@
 		{
 			return info->terminateHandler;
 		}
-		return terminateHandler;
+		return ATOMIC_LOAD(&terminateHandler);
 	}
 }
 #ifdef __arm__
diff --git a/src/memory.cc b/src/memory.cc
index bd7fd22..fec861a 100644
--- a/src/memory.cc
+++ b/src/memory.cc
@@ -36,14 +36,8 @@
 #include <stddef.h>
 #include <stdlib.h>
 #include "stdexcept.h"
+#include "atomic.h"
 
-#ifndef __has_builtin
-#define __has_builtin(x) 0
-#endif
-
-#if !__has_builtin(__sync_swap)
-#define __sync_swap __sync_lock_test_and_set
-#endif
 
 namespace std
 {
@@ -67,7 +61,12 @@
 	__attribute__((weak))
 	new_handler set_new_handler(new_handler handler)
 	{
-		return __sync_swap(&new_handl, handler);
+		return ATOMIC_SWAP(&new_handl, handler);
+	}
+	__attribute__((weak))
+	new_handler get_new_handler(void)
+	{
+		return ATOMIC_LOAD(&new_handl);
 	}
 }
 
@@ -78,9 +77,10 @@
 	void * mem = malloc(size);
 	while (0 == mem)
 	{
-		if (0 != new_handl)
+		new_handler h = std::get_new_handler();
+		if (0 != h)
 		{
-			new_handl();
+			h();
 		}
 		else
 		{
@@ -98,11 +98,12 @@
 	void *mem = malloc(size);
 	while (0 == mem)
 	{
-		if (0 != new_handl)
+		new_handler h = std::get_new_handler();
+		if (0 != h)
 		{
 			try
 			{
-				new_handl();
+				h();
 			}
 			catch (...)
 			{