Date: Thu, 1 Aug 2013 23:38:58 +0000 (UTC) From: Jung-uk Kim <jkim@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r253874 - in projects/atomic64/sys: amd64/include i386/include Message-ID: <201308012338.r71Ncw5M087687@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jkim Date: Thu Aug 1 23:38:57 2013 New Revision: 253874 URL: http://svnweb.freebsd.org/changeset/base/253874 Log: Add a new atomic operation atomic_swap for x86. This operation atomically loads the current value and stores a new value at once, i. e., tmp = *p; *p = v; return (tmp); Note atomic_readandclear is now obsolete and reimplemented as a macro around atomic_swap where the new value v is zero. Modified: projects/atomic64/sys/amd64/include/atomic.h projects/atomic64/sys/i386/include/atomic.h Modified: projects/atomic64/sys/amd64/include/atomic.h ============================================================================== --- projects/atomic64/sys/amd64/include/atomic.h Thu Aug 1 23:38:30 2013 (r253873) +++ projects/atomic64/sys/amd64/include/atomic.h Thu Aug 1 23:38:57 2013 (r253874) @@ -54,12 +54,14 @@ * atomic_clear_int(P, V) (*(u_int *)(P) &= ~(V)) * atomic_add_int(P, V) (*(u_int *)(P) += (V)) * atomic_subtract_int(P, V) (*(u_int *)(P) -= (V)) + * atomic_swap_int(P, V) (return (*(u_int *)(P)); *(u_int *)(P) = (V);) * atomic_readandclear_int(P) (return (*(u_int *)(P)); *(u_int *)(P) = 0;) * * atomic_set_long(P, V) (*(u_long *)(P) |= (V)) * atomic_clear_long(P, V) (*(u_long *)(P) &= ~(V)) * atomic_add_long(P, V) (*(u_long *)(P) += (V)) * atomic_subtract_long(P, V) (*(u_long *)(P) -= (V)) + * atomic_swap_long(P, V) (return (*(u_long *)(P)); *(u_long *)(P) = (V);) * atomic_readandclear_long(P) (return (*(u_long *)(P)); *(u_long *)(P) = 0;) */ @@ -301,45 +303,39 @@ ATOMIC_STORE(long); #ifndef WANT_FUNCTIONS -/* Read the current value and store a zero in the destination. */ +/* Read the current value and store a new value in the destination. */ #ifdef __GNUCLIKE_ASM static __inline u_int -atomic_readandclear_int(volatile u_int *addr) +atomic_swap_int(volatile u_int *p, u_int v) { - u_int res; - res = 0; __asm __volatile( - " xchgl %1,%0 ; " - "# atomic_readandclear_int" - : "+r" (res), /* 0 */ - "=m" (*addr) /* 1 */ - : "m" (*addr)); - - return (res); + " xchgl %1, %0 ; " + "# atomic_swap_int" + : "+r" (v), /* 0 */ + "=m" (*p) /* 1 */ + : "m" (*p)); + return (v); } static __inline u_long -atomic_readandclear_long(volatile u_long *addr) +atomic_swap_long(volatile u_long *p, u_long v) { - u_long res; - res = 0; __asm __volatile( - " xchgq %1,%0 ; " - "# atomic_readandclear_long" - : "+r" (res), /* 0 */ - "=m" (*addr) /* 1 */ - : "m" (*addr)); - - return (res); + " xchgq %1, %0 ; " + "# atomic_swap_long" + : "+r" (v), /* 0 */ + "=m" (*p) /* 1 */ + : "m" (*p)); + return (v); } #else /* !__GNUCLIKE_ASM */ -u_int atomic_readandclear_int(volatile u_int *addr); -u_long atomic_readandclear_long(volatile u_long *addr); +u_int atomic_swap_int(volatile u_int *, u_int); +u_long atomic_swap_long(volatile u_long *, u_long); #endif /* __GNUCLIKE_ASM */ @@ -383,6 +379,9 @@ u_long atomic_readandclear_long(volatile #define atomic_cmpset_acq_long atomic_cmpset_long #define atomic_cmpset_rel_long atomic_cmpset_long +#define atomic_readandclear_int(p) atomic_swap_int(p, 0) +#define atomic_readandclear_long(p) atomic_swap_long(p, 0) + /* Operations on 8-bit bytes. */ #define atomic_set_8 atomic_set_char #define atomic_set_acq_8 atomic_set_acq_char @@ -433,6 +432,7 @@ u_long atomic_readandclear_long(volatile #define atomic_cmpset_32 atomic_cmpset_int #define atomic_cmpset_acq_32 atomic_cmpset_acq_int #define atomic_cmpset_rel_32 atomic_cmpset_rel_int +#define atomic_swap_32 atomic_swap_int #define atomic_readandclear_32 atomic_readandclear_int #define atomic_fetchadd_32 atomic_fetchadd_int @@ -454,6 +454,7 @@ u_long atomic_readandclear_long(volatile #define atomic_cmpset_64 atomic_cmpset_long #define atomic_cmpset_acq_64 atomic_cmpset_acq_long #define atomic_cmpset_rel_64 atomic_cmpset_rel_long +#define atomic_swap_64 atomic_swap_long #define atomic_readandclear_64 atomic_readandclear_long /* Operations on pointers. */ @@ -474,6 +475,7 @@ u_long atomic_readandclear_long(volatile #define atomic_cmpset_ptr atomic_cmpset_long #define atomic_cmpset_acq_ptr atomic_cmpset_acq_long #define atomic_cmpset_rel_ptr atomic_cmpset_rel_long +#define atomic_swap_ptr atomic_swap_long #define atomic_readandclear_ptr atomic_readandclear_long #endif /* !WANT_FUNCTIONS */ Modified: projects/atomic64/sys/i386/include/atomic.h ============================================================================== --- projects/atomic64/sys/i386/include/atomic.h Thu Aug 1 23:38:30 2013 (r253873) +++ projects/atomic64/sys/i386/include/atomic.h Thu Aug 1 23:38:57 2013 (r253874) @@ -54,12 +54,14 @@ * atomic_clear_int(P, V) (*(u_int *)(P) &= ~(V)) * atomic_add_int(P, V) (*(u_int *)(P) += (V)) * atomic_subtract_int(P, V) (*(u_int *)(P) -= (V)) + * atomic_swap_int(P, V) (return (*(u_int *)(P)); *(u_int *)(P) = (V);) * atomic_readandclear_int(P) (return (*(u_int *)(P)); *(u_int *)(P) = 0;) * * atomic_set_long(P, V) (*(u_long *)(P) |= (V)) * atomic_clear_long(P, V) (*(u_long *)(P) &= ~(V)) * atomic_add_long(P, V) (*(u_long *)(P) += (V)) * atomic_subtract_long(P, V) (*(u_long *)(P) -= (V)) + * atomic_swap_long(P, V) (return (*(u_long *)(P)); *(u_long *)(P) = (V);) * atomic_readandclear_long(P) (return (*(u_long *)(P)); *(u_long *)(P) = 0;) */ @@ -392,45 +394,33 @@ atomic_fetchadd_long(volatile u_long *p, return (atomic_fetchadd_int((volatile u_int *)p, (u_int)v)); } -/* Read the current value and store a zero in the destination. */ +/* Read the current value and store a new value in the destination. */ #ifdef __GNUCLIKE_ASM static __inline u_int -atomic_readandclear_int(volatile u_int *addr) +atomic_swap_int(volatile u_int *p, u_int v) { - u_int res; - res = 0; __asm __volatile( - " xchgl %1,%0 ; " - "# atomic_readandclear_int" - : "+r" (res), /* 0 */ - "=m" (*addr) /* 1 */ - : "m" (*addr)); - - return (res); + " xchgl %1, %0 ; " + "# atomic_swap_int" + : "+r" (v), /* 0 */ + "=m" (*p) /* 1 */ + : "m" (*p)); + return (v); } static __inline u_long -atomic_readandclear_long(volatile u_long *addr) +atomic_swap_long(volatile u_long *p, u_long v) { - u_long res; - res = 0; - __asm __volatile( - " xchgl %1,%0 ; " - "# atomic_readandclear_long" - : "+r" (res), /* 0 */ - "=m" (*addr) /* 1 */ - : "m" (*addr)); - - return (res); + return (atomic_swap_int((volatile u_int *)p, (u_int)v)); } #else /* !__GNUCLIKE_ASM */ -u_int atomic_readandclear_int(volatile u_int *addr); -u_long atomic_readandclear_long(volatile u_long *addr); +u_int atomic_swap_int(volatile u_int *, u_int); +u_long atomic_swap_long(volatile u_long *, u_long); #endif /* __GNUCLIKE_ASM */ @@ -474,6 +464,9 @@ u_long atomic_readandclear_long(volatile #define atomic_cmpset_acq_long atomic_cmpset_long #define atomic_cmpset_rel_long atomic_cmpset_long +#define atomic_readandclear_int(p) atomic_swap_int(p, 0) +#define atomic_readandclear_long(p) atomic_swap_long(p, 0) + /* Operations on 8-bit bytes. */ #define atomic_set_8 atomic_set_char #define atomic_set_acq_8 atomic_set_acq_char @@ -524,6 +517,7 @@ u_long atomic_readandclear_long(volatile #define atomic_cmpset_32 atomic_cmpset_int #define atomic_cmpset_acq_32 atomic_cmpset_acq_int #define atomic_cmpset_rel_32 atomic_cmpset_rel_int +#define atomic_swap_32 atomic_swap_int #define atomic_readandclear_32 atomic_readandclear_int #define atomic_fetchadd_32 atomic_fetchadd_int @@ -564,6 +558,8 @@ u_long atomic_readandclear_long(volatile #define atomic_cmpset_rel_ptr(dst, old, new) \ atomic_cmpset_rel_int((volatile u_int *)(dst), (u_int)(old), \ (u_int)(new)) +#define atomic_swap_ptr(p, v) \ + atomic_swap_int((volatile u_int *)(p), (u_int)(v)) #define atomic_readandclear_ptr(p) \ atomic_readandclear_int((volatile u_int *)(p))
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201308012338.r71Ncw5M087687>