X-Git-Url: http://git.liburcu.org/?p=urcu.git;a=blobdiff_plain;f=urcu%2Fuatomic_arch_s390.h;h=2a4fa03e66cedb8d32488ae9e659ef886e76d88f;hp=917dbf2f471941457adcfff198f25c1f08747ce9;hb=b39e1761c4ccb070fcda1b86dc4ff0c66a853299;hpb=48d848c7291ec22da6258ac03cd9c1dafec1fdfb diff --git a/urcu/uatomic_arch_s390.h b/urcu/uatomic_arch_s390.h index 917dbf2..2a4fa03 100644 --- a/urcu/uatomic_arch_s390.h +++ b/urcu/uatomic_arch_s390.h @@ -1,5 +1,5 @@ -#ifndef _URCU_ARCH_ATOMIC_S390_H -#define _URCU_ARCH_ATOMIC_S390_H +#ifndef _URCU_UATOMIC_ARCH_S390_H +#define _URCU_UATOMIC_ARCH_S390_H /* * Atomic exchange operations for the S390 architecture. Based on information @@ -8,6 +8,7 @@ * * Copyright (c) 2009 Novell, Inc. * Author: Jan Blunck + * Copyright (c) 2009 Mathieu Desnoyers * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -28,69 +29,74 @@ * IN THE SOFTWARE. */ -#ifndef __SIZEOF_LONG__ -#ifdef __s390x__ -#define __SIZEOF_LONG__ 8 -#else -#define __SIZEOF_LONG__ 4 -#endif -#endif - -#ifndef BITS_PER_LONG -#define BITS_PER_LONG (__SIZEOF_LONG__ * 8) -#endif +#include +#include -#define uatomic_set(addr, v) \ -do { \ - ACCESS_ONCE(*(addr)) = (v); \ -} while (0) +#ifdef __cplusplus +extern "C" { +#endif -#define uatomic_read(addr) ACCESS_ONCE(*(addr)) +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2) +#define COMPILER_HAVE_SHORT_MEM_OPERAND +#endif -static inline __attribute__((always_inline)) -unsigned int uatomic_exchange_32(volatile unsigned int *addr, unsigned int val) -{ - unsigned int result; +/* + * MEMOP assembler operand rules: + * - op refer to MEMOP_IN operand + * - MEMOP_IN can expand to more than a single operand. Use it at the end of + * operand list only. + */ - __asm__ __volatile__( - "0: cs %0,%2,%1\n" - " brc 4,0b\n" - : "=&r"(result), "=m" (*addr) - : "r"(val), "m" (*addr) - : "memory", "cc"); +#ifdef COMPILER_HAVE_SHORT_MEM_OPERAND - return result; -} +#define MEMOP_OUT(addr) "=Q" (*(addr)) +#define MEMOP_IN(addr) "Q" (*(addr)) +#define MEMOP_REF(op) #op /* op refer to MEMOP_IN operand */ -#if (BITS_PER_LONG == 64) +#else /* !COMPILER_HAVE_SHORT_MEM_OPERAND */ -static inline __attribute__((always_inline)) -unsigned long uatomic_exchange_64(volatile unsigned long *addr, - unsigned long val) -{ - unsigned long result; +#define MEMOP_OUT(addr) "=m" (*(addr)) +#define MEMOP_IN(addr) "a" (addr), "m" (*(addr)) +#define MEMOP_REF(op) "0(" #op ")" /* op refer to MEMOP_IN operand */ - __asm__ __volatile__( - "0: csg %0,%2,%1\n" - " brc 4,0b\n" - : "=&r"(result), "=m" (*addr) - : "r"(val), "m" (*addr) - : "memory", "cc"); +#endif /* !COMPILER_HAVE_SHORT_MEM_OPERAND */ - return result; -} +struct __uatomic_dummy { + unsigned long v[10]; +}; +#define __hp(x) ((struct __uatomic_dummy *)(x)) -#endif +/* xchg */ static inline __attribute__((always_inline)) unsigned long _uatomic_exchange(volatile void *addr, unsigned long val, int len) { switch (len) { case 4: - return uatomic_exchange_32(addr, val); -#if (BITS_PER_LONG == 64) + { + unsigned int old_val; + + __asm__ __volatile__( + "0: cs %0,%2," MEMOP_REF(%3) "\n" + " brc 4,0b\n" + : "=&r" (old_val), MEMOP_OUT (__hp(addr)) + : "r" (val), MEMOP_IN (__hp(addr)) + : "memory", "cc"); + return old_val; + } +#if (CAA_BITS_PER_LONG == 64) case 8: - return uatomic_exchange_64(addr, val); + { + unsigned long old_val; + + __asm__ __volatile__( + "0: csg %0,%2," MEMOP_REF(%3) "\n" + " brc 4,0b\n" + : "=&r" (old_val), MEMOP_OUT (__hp(addr)) + : "r" (val), MEMOP_IN (__hp(addr)) + : "memory", "cc"); + return old_val; + } #endif default: __asm__ __volatile__(".long 0xd00d00"); @@ -99,110 +105,38 @@ unsigned long _uatomic_exchange(volatile void *addr, unsigned long val, int len) return 0; } -#define uatomic_xchg(addr, v) \ +#define uatomic_xchg(addr, v) \ (__typeof__(*(addr))) _uatomic_exchange((addr), (unsigned long)(v), \ sizeof(*(addr))) +/* cmpxchg */ static inline __attribute__((always_inline)) -void uatomic_add_32(volatile unsigned int *addr, unsigned int val) -{ - unsigned int result, old; - - __asm__ __volatile__( - " l %0, %1\n" - "0: lr %2, %0\n" - " ar %2, %3\n" - " cs %0,%2,%1\n" - " brc 4,0b\n" - : "=&r"(old), "+m" (*addr), - "=&r"(result) - : "r"(val) - : "memory", "cc"); -} - -#if (BITS_PER_LONG == 64) - -static inline __attribute__((always_inline)) -void uatomic_add_64(volatile unsigned long *addr, unsigned long val) -{ - unsigned long result, old; - - __asm__ __volatile__( - " lg %0, %1\n" - "0: lgr %2, %0\n" - " agr %2, %3\n" - " csg %0,%2,%1\n" - " brc 4,0b\n" - : "=&r"(old), "+m" (*addr), - "=&r"(result) - : "r"(val) - : "memory", "cc"); -} - -#endif - -static inline __attribute__((always_inline)) -void _uatomic_add(void *addr, unsigned long val, int len) -{ - switch (len) { - case 4: - uatomic_add_32(addr, val); - return; -#if (BITS_PER_LONG == 64) - case 8: - uatomic_add_64(addr, val); - return; -#endif - default: - __asm__ __volatile__(".long 0xd00d00"); - } - - return; -} - -#define uatomic_add(addr, val) \ - _uatomic_add((addr), (unsigned long)(val), sizeof(*(addr))) - -static inline __attribute__((always_inline)) -unsigned int uatomic_cmpxchg_32(volatile unsigned int *addr, unsigned int old, - unsigned int new) -{ - __asm__ __volatile__( - " cs %0,%2,%1\n" - : "+r"(old), "+m"(*addr) - : "r"(new) - : "memory", "cc"); - - return old; -} - -#if (BITS_PER_LONG == 64) - -static inline __attribute__((always_inline)) -unsigned long uatomic_cmpxchg_64(volatile unsigned long *addr, - unsigned long old, unsigned long new) -{ - __asm__ __volatile__( - " csg %0,%2,%1\n" - : "+r"(old), "+m"(*addr) - : "r"(new) - : "memory", "cc"); - - return old; -} - -#endif - unsigned long _uatomic_cmpxchg(void *addr, unsigned long old, - unsigned long new, int len) + unsigned long _new, int len) { switch (len) { case 4: - return uatomic_cmpxchg_32(addr, old, new); -#if (BITS_PER_LONG == 64) + { + unsigned int old_val = (unsigned int)old; + + __asm__ __volatile__( + " cs %0,%2," MEMOP_REF(%3) "\n" + : "+r" (old_val), MEMOP_OUT (__hp(addr)) + : "r" (_new), MEMOP_IN (__hp(addr)) + : "memory", "cc"); + return old_val; + } +#if (CAA_BITS_PER_LONG == 64) case 8: - return uatomic_cmpxchg_64(addr, old, new); + { + __asm__ __volatile__( + " csg %0,%2," MEMOP_REF(%3) "\n" + : "+r" (old), MEMOP_OUT (__hp(addr)) + : "r" (_new), MEMOP_IN (__hp(addr)) + : "memory", "cc"); + return old; + } #endif default: __asm__ __volatile__(".long 0xd00d00"); @@ -211,10 +145,16 @@ unsigned long _uatomic_cmpxchg(void *addr, unsigned long old, return 0; } -#define uatomic_cmpxchg(addr, old, new) \ +#define uatomic_cmpxchg(addr, old, _new) \ (__typeof__(*(addr))) _uatomic_cmpxchg((addr), \ (unsigned long)(old), \ - (unsigned long)(new), \ + (unsigned long)(_new), \ sizeof(*(addr))) -#endif /* _URCU_ARCH_ATOMIC_S390_H */ +#ifdef __cplusplus +} +#endif + +#include + +#endif /* _URCU_UATOMIC_ARCH_S390_H */