summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhboehm <hboehm>2006-03-28 23:36:58 +0000
committerIvan Maidanski <ivmai@mail.ru>2011-07-25 15:19:42 +0400
commit00768a253f3d93a85a2dfbf85fd4e7f5a70b1dca (patch)
tree84809a8c56e717e8c1c1aca0059bccbbb9d77b55
parent6784eb46516f8f0876f2af66af450c43ecd8af36 (diff)
downloadlibatomic_ops-00768a253f3d93a85a2dfbf85fd4e7f5a70b1dca.tar.gz
2006-03-28 Hans Boehm <Hans.Boehm@hp.com>
Integrate Earl Chew's atomic_ops improvements. More details are in the libatomic_ops ChangeLog. * ChangeLog, src/atomic_ops.h, src/atomic_ops/sysdeps/gcc/powerpc.h, src/atomic_ops/sysdeps/msftc/x86.h, tests/run_parallel.inc, tests/test_atomic.c, tests/test_atomic_include.h.
-rw-r--r--ChangeLog22
-rwxr-xr-xsrc/atomic_ops.h2
-rw-r--r--src/atomic_ops/sysdeps/gcc/powerpc.h1
-rw-r--r--src/atomic_ops/sysdeps/msftc/x86.h96
-rw-r--r--tests/run_parallel.inc55
-rw-r--r--tests/test_atomic.c7
-rw-r--r--tests/test_atomic_include.h9
7 files changed, 165 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog
index dcf2d43..77b9089 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2006-03-28 Earl Chew (Agilent)
+ * src/atomic_ops/sysdeps/gcc/powerpc.h: Remove unused variable cr.
+ * src/atomic_ops/sysdeps/msftc/x86.h:
+ Use new intrinsics available in MSVC 2003 and MSVC 2005.
+ Use inline assembler to generate mfence and byte sized xchg
+ Use correct prototype for InterlockedCompareExchange.
+ * src/atomic_ops.h: Add test for __PPC__ .
+ * tests/run_parallel.inc: Add simple VxWorks support.
+ * tests/test_atomic.c, tests/test_atomic_include.h: Add prototypes to silence compiler warnings.
+
+2006-1-13 Hans Boehm <Hans.Boehm@hp.com>
+ *src/atomic_ops/sysdeps/gcc/powerpc.h: Beginnings of 64 bit support.
+ *src/atomic_ops/sysdeps/gcc/x86.h: Use "=q" for AO_test_and_set_full.
+
+2005-11-4 Hans Boehm <Hans.Boehm@hp.com>
+ *src/atomic_ops/sysdeps/gcc/ia64.h: Include
+ all_acquire_release_volatile.h, instead of just the pointer-sized
+ version.
+ *src/atomic_ops/sysdeps/gcc/ia64.h: Include
+ all_acquire_release_volatile.h and all_atomic_load_store.h,
+ instead of just the pointer-sized versions.
+
[1.1 release]
2003-09-27 Hans Boehm <Hans.Boehm@hp.com>
diff --git a/src/atomic_ops.h b/src/atomic_ops.h
index 3a65030..1feb379 100755
--- a/src/atomic_ops.h
+++ b/src/atomic_ops.h
@@ -210,7 +210,7 @@
# if defined(__m68k__)
# include "atomic_ops/sysdeps/gcc/m68k.h"
# endif /* __m68k__ */
-# if defined(__powerpc__) || defined(__ppc__)
+# if defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)
# include "atomic_ops/sysdeps/gcc/powerpc.h"
# endif /* __powerpc__ */
# if defined(__arm__) && !defined(AO_USE_PTHREAD_DEFS)
diff --git a/src/atomic_ops/sysdeps/gcc/powerpc.h b/src/atomic_ops/sysdeps/gcc/powerpc.h
index 5f33e71..cd5a534 100644
--- a/src/atomic_ops/sysdeps/gcc/powerpc.h
+++ b/src/atomic_ops/sysdeps/gcc/powerpc.h
@@ -66,7 +66,6 @@ AO_lwsync()
AO_INLINE AO_t
AO_load_acquire(volatile AO_t *addr)
{
- int cr;
AO_t result;
/* FIXME: We should get gcc to allocate one of the condition */
diff --git a/src/atomic_ops/sysdeps/msftc/x86.h b/src/atomic_ops/sysdeps/msftc/x86.h
index eac112c..1192d90 100644
--- a/src/atomic_ops/sysdeps/msftc/x86.h
+++ b/src/atomic_ops/sysdeps/msftc/x86.h
@@ -23,7 +23,7 @@
/* The following really assume we have a 486 or better. */
/* If ASSUME_WINDOWS98 is defined, we assume Windows 98 or newer. */
-#include "../aligned_atomic_load_store.h"
+#include "../all_aligned_atomic_load_store.h"
/* Real X86 implementations, except for some old WinChips, appear */
/* to enforce ordering between memory operations, EXCEPT that a later */
@@ -34,20 +34,72 @@
#include "../ordered_except_wr.h"
-#include "../test_and_set_t_is_ao_t.h"
- /* We should use byte-sized test-and-set locations, as with */
- /* gcc. But I couldn't find the appropriate compiler */
- /* intrinsic. - HB */
+#include "../test_and_set_t_is_char.h"
-#include <windows.h>
+#include <winbase.h>
+
+#if _MSC_VER < 1310
+
+#define _InterlockedIncrement InterlockedIncrement
+#define _InterlockedDecrement InterlockedDecrement
+#define _InterlockedExchange InterlockedExchange
+#define _InterlockedCompareExchange InterlockedCompareExchange
+
+#else
+
+#if _MSC_VER >= 1400
+#include <intrin.h>
+
+#pragma intrinsic (_ReadWriteBarrier)
+
+#else
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LONG __cdecl _InterlockedIncrement(LONG volatile *Addend);
+LONG __cdecl _InterlockedDecrement(LONG volatile *Addend);
+LONG __cdecl _InterlockedExchangeAdd(LONG volatile* Target, LONG Addend);
+LONG __cdecl _InterlockedExchange(LONG volatile* Target, LONG Value);
+LONG __cdecl _InterlockedCompareExchange(LONG volatile* Dest,
+ LONG Exchange, LONG Comp);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _MSC_VER >= 1400 */
+
+#pragma intrinsic (_InterlockedIncrement)
+#pragma intrinsic (_InterlockedDecrement)
+#pragma intrinsic (_InterlockedExchange)
+#pragma intrinsic (_InterlockedExchangeAdd)
+#pragma intrinsic (_InterlockedCompareExchange)
+
+#endif /* _MSC_VER < 1310 */
/* As far as we can tell, the lfence and sfence instructions are not */
/* currently needed or useful for cached memory accesses. */
+AO_INLINE void
+AO_nop_full()
+{
+ __asm { mfence }
+}
+
+#define AO_HAVE_nop_full
+
+AO_INLINE AO_t
+AO_fetch_and_add_full (volatile AO_t *p, AO_t incr)
+{
+ return _InterlockedExchangeAdd((LONG volatile*)p, (LONG)incr);
+}
+
+#define AO_HAVE_fetch_and_add_full
+
AO_INLINE AO_t
AO_fetch_and_add1_full (volatile AO_t *p)
{
- return InterlockedIncrement((LONG volatile *)p) - 1;
+ return _InterlockedIncrement((LONG volatile *)p) - 1;
}
#define AO_HAVE_fetch_and_add1_full
@@ -55,7 +107,7 @@ AO_fetch_and_add1_full (volatile AO_t *p)
AO_INLINE AO_t
AO_fetch_and_sub1_full (volatile AO_t *p)
{
- return InterlockedDecrement((LONG volatile *)p) + 1;
+ return _InterlockedDecrement((LONG volatile *)p) + 1;
}
#define AO_HAVE_fetch_and_sub1_full
@@ -63,8 +115,12 @@ AO_fetch_and_sub1_full (volatile AO_t *p)
AO_INLINE AO_TS_VAL_t
AO_test_and_set_full(volatile AO_TS_t *addr)
{
- return (AO_TS_VAL_t) InterlockedExchange((LONG volatile *)addr,
- (LONG)AO_TS_SET);
+ __asm
+ {
+ mov eax,AO_TS_SET ;
+ mov ebx,addr ;
+ xchg byte ptr [ebx],al ;
+ }
}
#define AO_HAVE_test_and_set_full
@@ -75,20 +131,14 @@ AO_INLINE int
AO_compare_and_swap_full(volatile AO_t *addr,
AO_t old, AO_t new_val)
{
-# if 0
- /* Use the pointer variant, since that should always have the right size. */
- /* This seems to fail with VC++ 6 on Win2000 because the routine isn't */
- /* actually there. */
- return InterlockedCompareExchangePointer((PVOID volatile *)addr,
- (PVOID)new_val, (PVOID) old)
- == (PVOID)old;
-# endif
- /* FIXME - This is nearly useless on win64. */
- /* Use InterlockedCompareExchange64 for win64? */
- return InterlockedCompareExchange((DWORD volatile *)addr,
- (DWORD)new_val, (DWORD) old)
- == (DWORD)old;
+ return _InterlockedCompareExchange((LONG volatile *)addr,
+ (LONG)new_val, (LONG)old)
+ == (LONG)old;
}
#define AO_HAVE_compare_and_swap_full
#endif /* ASSUME_WINDOWS98 */
+
+#ifndef _WIN64
+#include "../ao_t_is_int.h"
+#endif
diff --git a/tests/run_parallel.inc b/tests/run_parallel.inc
index 39308d5..1a87c8b 100644
--- a/tests/run_parallel.inc
+++ b/tests/run_parallel.inc
@@ -9,6 +9,8 @@
defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__CYGWIN__) || \
defined(_WIN32_WINCE)
# define USE_WINTHREADS
+#elif defined(__vxworks)
+# define USE_VXTHREADS
#else
# define USE_PTHREADS
#endif
@@ -20,6 +22,11 @@
# include <pthread.h>
#endif
+#ifdef USE_VXTHREADS
+# include <vxworks.h>
+# include <taskLib.h>
+#endif
+
#ifdef USE_WINTHREADS
# include <windows.h>
#endif
@@ -30,8 +37,10 @@ typedef void * (* thr_func)(void *);
typedef int (* test_func)(void); /* Returns != 0 on success */
+void * run_parallel(int nthreads, thr_func f1, test_func t, const char *name);
+
#ifdef USE_PTHREADS
-void * run_parallel(int nthreads, thr_func f1, test_func t, char *name)
+void * run_parallel(int nthreads, thr_func f1, test_func t, const char *name)
{
pthread_attr_t attr;
pthread_t thr[100];
@@ -87,6 +96,48 @@ void * run_parallel(int nthreads, thr_func f1, test_func t, char *name)
}
#endif /* USE_PTHREADS */
+#ifdef USE_VXTHREADS
+void * run_parallel(int nthreads, thr_func f1, test_func t, const char *name)
+{
+ int thr[100];
+ int i;
+
+ fprintf(stderr, "Testing %s\n", name);
+ if (nthreads > 100)
+ {
+ fprintf(stderr, "run_parallel: requested too many threads\n");
+ taskSuspend(0);
+ }
+
+ for (i = 0; i < nthreads; ++i)
+ {
+ thr[i] = taskSpawn((char*) name, 180, 0, 32768, (FUNCPTR) f1, i,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9);
+ if (thr[i] == ERROR)
+ {
+ fprintf(stderr, "taskSpawn failed with %d, thread %d\n",
+ errno, i);
+ taskSuspend(0);
+ }
+ }
+ for (i = 0; i < nthreads; ++i)
+ {
+ while (taskIdVerify(thr[i]) == OK)
+ taskDelay(60);
+ }
+ if (t())
+ {
+ fprintf(stderr, "Succeeded\n");
+ }
+ else
+ {
+ fprintf(stderr, "Failed\n");
+ taskSuspend(0);
+ }
+ return 0;
+}
+#endif /* USE_VXTHREADS */
+
#ifdef USE_WINTHREADS
struct tramp_args {
@@ -101,7 +152,7 @@ DWORD WINAPI tramp(LPVOID param)
return (DWORD)(args -> fn)((LPVOID)(args -> arg));
}
-void * run_parallel(int nthreads, thr_func f1, test_func t, char *name)
+void * run_parallel(int nthreads, thr_func f1, test_func t, const char *name)
{
HANDLE thr[100];
struct tramp_args args[100];
diff --git a/tests/test_atomic.c b/tests/test_atomic.c
index 03da5f2..d31297d 100644
--- a/tests/test_atomic.c
+++ b/tests/test_atomic.c
@@ -27,6 +27,13 @@
# define NITERS 10000000
#endif
+void * add1sub1_thr(void * id);
+int add1sub1_test(void);
+void * acqrel_thr(void *id);
+int acqrel_test(void);
+void * test_and_set_thr(void * id);
+int test_and_set_test(void);
+
#if defined(AO_HAVE_fetch_and_add1) && defined(AO_HAVE_fetch_and_sub1)
AO_t counter = 0;
diff --git a/tests/test_atomic_include.h b/tests/test_atomic_include.h
index c9970ab..bc280eb 100644
--- a/tests/test_atomic_include.h
+++ b/tests/test_atomic_include.h
@@ -5,6 +5,15 @@
* see doc/COPYING for details.
*/
+void test_atomic(void);
+void test_atomic_release(void);
+void test_atomic_acquire(void);
+void test_atomic_read(void);
+void test_atomic_write(void);
+void test_atomic_full(void);
+void test_atomic_release_write(void);
+void test_atomic_acquire_read(void);
+
/* Some basic sanity tests. These do not test the barrier semantics. */
#undef TA_assert