From owner-svn-src-head@freebsd.org Mon May 16 07:19:34 2016 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id E0961B3C64A; Mon, 16 May 2016 07:19:34 +0000 (UTC) (envelope-from sephe@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id B8C9A1176; Mon, 16 May 2016 07:19:34 +0000 (UTC) (envelope-from sephe@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u4G7JX8c076125; Mon, 16 May 2016 07:19:33 GMT (envelope-from sephe@FreeBSD.org) Received: (from sephe@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u4G7JXr7076122; Mon, 16 May 2016 07:19:33 GMT (envelope-from sephe@FreeBSD.org) Message-Id: <201605160719.u4G7JXr7076122@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: sephe set sender to sephe@FreeBSD.org using -f From: Sepherosa Ziehau Date: Mon, 16 May 2016 07:19:33 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r299912 - in head: share/man/man9 sys/amd64/include sys/i386/include X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 16 May 2016 07:19:35 -0000 Author: sephe Date: Mon May 16 07:19:33 2016 New Revision: 299912 URL: https://svnweb.freebsd.org/changeset/base/299912 Log: atomic: Add testandclear on i386/amd64 Reviewed by: kib Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D6381 Modified: head/share/man/man9/atomic.9 head/sys/amd64/include/atomic.h head/sys/i386/include/atomic.h Modified: head/share/man/man9/atomic.9 ============================================================================== --- head/share/man/man9/atomic.9 Mon May 16 07:12:04 2016 (r299911) +++ head/share/man/man9/atomic.9 Mon May 16 07:19:33 2016 (r299912) @@ -23,7 +23,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 14, 2015 +.Dd May 12, 2016 .Dt ATOMIC 9 .Os .Sh NAME @@ -65,6 +65,8 @@ .Ft .Fn atomic_swap_ "volatile *p" " v" .Ft int +.Fn atomic_testandclear_ "volatile *p" "u_int v" +.Ft int .Fn atomic_testandset_ "volatile *p" "u_int v" .Sh DESCRIPTION Each of the atomic operations is guaranteed to be atomic across multiple @@ -309,6 +311,15 @@ and .Dq Li 16 and do not have any variants with memory barriers at this time. .Bl -hang +.It Fn atomic_testandclear p v +.Bd -literal -compact +bit = 1 << (v % (sizeof(*p) * NBBY)); +tmp = (*p & bit) != 0; +*p &= ~bit; +return (tmp); +.Ed +.El +.Bl -hang .It Fn atomic_testandset p v .Bd -literal -compact bit = 1 << (v % (sizeof(*p) * NBBY)); @@ -320,6 +331,8 @@ return (tmp); .Pp The .Fn atomic_testandset +and +.Fn atomic_testandclear functions are only implemented for the types .Dq Li int , .Dq Li long @@ -348,6 +361,8 @@ and functions return the value at the specified address. The .Fn atomic_testandset +and +.Fn atomic_testandclear function returns the result of the test operation. .Sh EXAMPLES This example uses the @@ -425,3 +440,6 @@ and .Fn atomic_testandset operations were added in .Fx 10.0 . +.Fn atomic_testandclear +operation was added in +.Fx 11.0 . Modified: head/sys/amd64/include/atomic.h ============================================================================== --- head/sys/amd64/include/atomic.h Mon May 16 07:12:04 2016 (r299911) +++ head/sys/amd64/include/atomic.h Mon May 16 07:19:33 2016 (r299912) @@ -103,6 +103,8 @@ u_int atomic_fetchadd_int(volatile u_int u_long atomic_fetchadd_long(volatile u_long *p, u_long v); int atomic_testandset_int(volatile u_int *p, u_int v); int atomic_testandset_long(volatile u_long *p, u_int v); +int atomic_testandclear_int(volatile u_int *p, u_int v); +int atomic_testandclear_long(volatile u_long *p, u_int v); void atomic_thread_fence_acq(void); void atomic_thread_fence_acq_rel(void); void atomic_thread_fence_rel(void); @@ -264,6 +266,40 @@ atomic_testandset_long(volatile u_long * return (res); } +static __inline int +atomic_testandclear_int(volatile u_int *p, u_int v) +{ + u_char res; + + __asm __volatile( + " " MPLOCKED " " + " btrl %2,%1 ; " + " setc %0 ; " + "# atomic_testandclear_int" + : "=q" (res), /* 0 */ + "+m" (*p) /* 1 */ + : "Ir" (v & 0x1f) /* 2 */ + : "cc"); + return (res); +} + +static __inline int +atomic_testandclear_long(volatile u_long *p, u_int v) +{ + u_char res; + + __asm __volatile( + " " MPLOCKED " " + " btrq %2,%1 ; " + " setc %0 ; " + "# atomic_testandclear_long" + : "=q" (res), /* 0 */ + "+m" (*p) /* 1 */ + : "Jr" ((u_long)(v & 0x3f)) /* 2 */ + : "cc"); + return (res); +} + /* * We assume that a = b will do atomic loads and stores. Due to the * IA32 memory model, a simple store guarantees release semantics. @@ -537,6 +573,7 @@ u_long atomic_swap_long(volatile u_long #define atomic_readandclear_32 atomic_readandclear_int #define atomic_fetchadd_32 atomic_fetchadd_int #define atomic_testandset_32 atomic_testandset_int +#define atomic_testandclear_32 atomic_testandclear_int /* Operations on 64-bit quad words. */ #define atomic_set_64 atomic_set_long @@ -560,6 +597,7 @@ u_long atomic_swap_long(volatile u_long #define atomic_readandclear_64 atomic_readandclear_long #define atomic_fetchadd_64 atomic_fetchadd_long #define atomic_testandset_64 atomic_testandset_long +#define atomic_testandclear_64 atomic_testandclear_long /* Operations on pointers. */ #define atomic_set_ptr atomic_set_long Modified: head/sys/i386/include/atomic.h ============================================================================== --- head/sys/i386/include/atomic.h Mon May 16 07:12:04 2016 (r299911) +++ head/sys/i386/include/atomic.h Mon May 16 07:19:33 2016 (r299912) @@ -108,6 +108,7 @@ void atomic_##NAME##_barr_##TYPE(volatil int atomic_cmpset_int(volatile u_int *dst, u_int expect, u_int src); u_int atomic_fetchadd_int(volatile u_int *p, u_int v); int atomic_testandset_int(volatile u_int *p, u_int v); +int atomic_testandclear_int(volatile u_int *p, u_int v); void atomic_thread_fence_acq(void); void atomic_thread_fence_acq_rel(void); void atomic_thread_fence_rel(void); @@ -250,6 +251,23 @@ atomic_testandset_int(volatile u_int *p, return (res); } +static __inline int +atomic_testandclear_int(volatile u_int *p, u_int v) +{ + u_char res; + + __asm __volatile( + " " MPLOCKED " " + " btrl %2,%1 ; " + " setc %0 ; " + "# atomic_testandclear_int" + : "=q" (res), /* 0 */ + "+m" (*p) /* 1 */ + : "Ir" (v & 0x1f) /* 2 */ + : "cc"); + return (res); +} + /* * We assume that a = b will do atomic loads and stores. Due to the * IA32 memory model, a simple store guarantees release semantics. @@ -602,6 +620,13 @@ atomic_testandset_long(volatile u_long * return (atomic_testandset_int((volatile u_int *)p, v)); } +static __inline int +atomic_testandclear_long(volatile u_long *p, u_int v) +{ + + return (atomic_testandclear_int((volatile u_int *)p, v)); +} + /* Read the current value and store a new value in the destination. */ #ifdef __GNUCLIKE_ASM @@ -728,6 +753,7 @@ u_long atomic_swap_long(volatile u_long #define atomic_readandclear_32 atomic_readandclear_int #define atomic_fetchadd_32 atomic_fetchadd_int #define atomic_testandset_32 atomic_testandset_int +#define atomic_testandclear_32 atomic_testandclear_int /* Operations on pointers. */ #define atomic_set_ptr(p, v) \