diff options
author | hboehm <hboehm> | 2006-03-28 23:36:58 +0000 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2011-07-25 15:19:42 +0400 |
commit | 00768a253f3d93a85a2dfbf85fd4e7f5a70b1dca (patch) | |
tree | 84809a8c56e717e8c1c1aca0059bccbbb9d77b55 | |
parent | 6784eb46516f8f0876f2af66af450c43ecd8af36 (diff) | |
download | libatomic_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-- | ChangeLog | 22 | ||||
-rwxr-xr-x | src/atomic_ops.h | 2 | ||||
-rw-r--r-- | src/atomic_ops/sysdeps/gcc/powerpc.h | 1 | ||||
-rw-r--r-- | src/atomic_ops/sysdeps/msftc/x86.h | 96 | ||||
-rw-r--r-- | tests/run_parallel.inc | 55 | ||||
-rw-r--r-- | tests/test_atomic.c | 7 | ||||
-rw-r--r-- | tests/test_atomic_include.h | 9 |
7 files changed, 165 insertions, 27 deletions
@@ -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 |