diff mbox

libgo patch committed: Add __sync_bool_compare_and_swap_4

Message ID mcrd3nbldes.fsf@google.com
State New
Headers show

Commit Message

Ian Lance Taylor Feb. 1, 2011, 8:15 p.m. UTC
The libgo library uses __sync_bool_compare_and_swap_4 (i.e., uses
__sync_bool_compare_and_swap on uint32 types).  That function is not
available for all gcc targets.  This patch adds the function to the
library for those cases.  Ideally this would be handled by libgcc, but
that does not currently happen.  This function should be harmless if
libgcc does get an implementation.

This implementation is rather slow but it is better than having the
build fail.

Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
Committed to mainline.

Ian

Comments

Joseph Myers Feb. 1, 2011, 8:50 p.m. UTC | #1
On Tue, 1 Feb 2011, Ian Lance Taylor wrote:

> The libgo library uses __sync_bool_compare_and_swap_4 (i.e., uses
> __sync_bool_compare_and_swap on uint32 types).  That function is not
> available for all gcc targets.  This patch adds the function to the
> library for those cases.  Ideally this would be handled by libgcc, but
> that does not currently happen.  This function should be harmless if
> libgcc does get an implementation.

On some targets libgcc does have an implementation (ARM, PA, SH Linux - 
note that for more recent ARM architectures the sync operations are 
inlined).  The __HAVE_* macros only know about whether the operation can 
be inlined, not about whether it's available in libgcc.  libstdc++-v3 uses 
link tests to see if these operations are available (either inlined or in 
libgcc - or for that matter in libc, which could make sense for kernel 
helpers accessed through a vDSO).

For more general questions about implementing atomics in libgcc, see past 
discussions around implementing C++0x/C1x atomics.
diff mbox

Patch

diff -r 948edbf8367c libgo/runtime/thread.c
--- a/libgo/runtime/thread.c	Mon Jan 31 15:32:52 2011 -0800
+++ b/libgo/runtime/thread.c	Tue Feb 01 12:11:10 2011 -0800
@@ -3,6 +3,7 @@ 
 // license that can be found in the LICENSE file.
 
 #include "runtime.h"
+#include "go-assert.h"
 
 void
 runtime_initlock(Lock *l)
@@ -75,3 +76,38 @@ 
 {
 	sem_destroy(&l->sem);
 }
+
+#ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
+
+// For targets which don't have the required sync support.  Really
+// this should be provided by gcc itself.  FIXME.
+
+static pthread_mutex_t sync_lock = PTHREAD_MUTEX_INITIALIZER;
+
+_Bool
+__sync_bool_compare_and_swap_4(uint32*, uint32, uint32)
+  __attribute__((visibility("hidden")));
+
+_Bool
+__sync_bool_compare_and_swap_4(uint32* ptr, uint32 old, uint32 new)
+{
+  int i;
+  _Bool ret;
+
+  i = pthread_mutex_lock(&sync_lock);
+  __go_assert(i == 0);
+
+  if(*ptr != old) {
+    ret = 0;
+  } else {
+    *ptr = new;
+    ret = 1;
+  }
+
+  i = pthread_mutex_unlock(&sync_lock);
+  __go_assert(i == 0);
+
+  return ret;
+}
+
+#endif