diff mbox series

parisc: Release spinlocks using ordered store

Message ID 20181017010759.GA28022@mx3210.localdomain (mailing list archive)
State Accepted, archived
Headers show
Series parisc: Release spinlocks using ordered store | expand

Commit Message

John David Anglin Oct. 17, 2018, 1:07 a.m. UTC
This patch updates the spin unlock code to use an ordered store with release
semanatics.  All prior accesses are guaranteed to be performed before an
ordered store is performed.

Using an ordered store is significantly faster than using the sync memory
barrier.


Signed-off-by: John David Anglin <dave.anglin@bell.net>

Comments

John David Anglin Nov. 3, 2018, 2:30 p.m. UTC | #1
On 2018-10-16 9:07 PM, John David Anglin wrote:
> This patch updates the spin unlock code to use an ordered store with release
> semanatics.  All prior accesses are guaranteed to be performed before an
> ordered store is performed.
>
> Using an ordered store is significantly faster than using the sync memory
> barrier.
Unfortunately, this patch needs to be reverted.  We need the full sync 
barrier and not the limited
barrier provided by using an ordered store.  The sync ensures that all 
accesses and cache purge
instructions that follow the sync are performed after all such 
instructions prior the sync instruction
have completed executing.

The patch breaks the rwlock implementation in glibc.  This caused the 
test-lock application in the
libprelude testsuite to hang.  With the change reverted, the test runs 
correctly and the libprelude
package builds successfully.

>
> diff --git a/arch/parisc/include/asm/spinlock.h b/arch/parisc/include/asm/spinlock.h
> index 8a63515f03bf..16aec9ba2580 100644
> --- a/arch/parisc/include/asm/spinlock.h
> +++ b/arch/parisc/include/asm/spinlock.h
> @@ -37,8 +37,8 @@ static inline void arch_spin_unlock(arch_spinlock_t *x)
>   	volatile unsigned int *a;
>   
>   	a = __ldcw_align(x);
> -	mb();
> -	*a = 1;
> +	/* Release with ordered store. */
> +	__asm__ __volatile__("stw,ma %0,0(%1)" : : "r"(1), "r"(a) : "memory");
>   }
>   
>   static inline int arch_spin_trylock(arch_spinlock_t *x)
> diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
> index f453997a7b8f..f5f22ea9b97e 100644
> --- a/arch/parisc/kernel/syscall.S
> +++ b/arch/parisc/kernel/syscall.S
> @@ -640,8 +640,7 @@ cas_action:
>   	sub,<>	%r28, %r25, %r0
>   2:	stw	%r24, 0(%r26)
>   	/* Free lock */
> -	sync
> -	stw	%r20, 0(%sr2,%r20)
> +	stw,ma	%r20, 0(%sr2,%r20)
>   #if ENABLE_LWS_DEBUG
>   	/* Clear thread register indicator */
>   	stw	%r0, 4(%sr2,%r20)
> @@ -655,8 +654,7 @@ cas_action:
>   3:		
>   	/* Error occurred on load or store */
>   	/* Free lock */
> -	sync
> -	stw	%r20, 0(%sr2,%r20)
> +	stw,ma	%r20, 0(%sr2,%r20)
>   #if ENABLE_LWS_DEBUG
>   	stw	%r0, 4(%sr2,%r20)
>   #endif
> @@ -857,8 +855,7 @@ cas2_action:
>   
>   cas2_end:
>   	/* Free lock */
> -	sync
> -	stw	%r20, 0(%sr2,%r20)
> +	stw,ma	%r20, 0(%sr2,%r20)
>   	/* Enable interrupts */
>   	ssm	PSW_SM_I, %r0
>   	/* Return to userspace, set no error */
> @@ -868,8 +865,7 @@ cas2_end:
>   22:
>   	/* Error occurred on load or store */
>   	/* Free lock */
> -	sync
> -	stw	%r20, 0(%sr2,%r20)
> +	stw,ma	%r20, 0(%sr2,%r20)
>   	ssm	PSW_SM_I, %r0
>   	ldo	1(%r0),%r28
>   	b	lws_exit
>
> Signed-off-by: John David Anglin <dave.anglin@bell.net>
>

Signed-off-by: John David Anglin <dave.anglin@bell.net>
diff mbox series

Patch

diff --git a/arch/parisc/include/asm/spinlock.h b/arch/parisc/include/asm/spinlock.h
index 8a63515f03bf..16aec9ba2580 100644
--- a/arch/parisc/include/asm/spinlock.h
+++ b/arch/parisc/include/asm/spinlock.h
@@ -37,8 +37,8 @@  static inline void arch_spin_unlock(arch_spinlock_t *x)
 	volatile unsigned int *a;
 
 	a = __ldcw_align(x);
-	mb();
-	*a = 1;
+	/* Release with ordered store. */
+	__asm__ __volatile__("stw,ma %0,0(%1)" : : "r"(1), "r"(a) : "memory");
 }
 
 static inline int arch_spin_trylock(arch_spinlock_t *x)
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
index f453997a7b8f..f5f22ea9b97e 100644
--- a/arch/parisc/kernel/syscall.S
+++ b/arch/parisc/kernel/syscall.S
@@ -640,8 +640,7 @@  cas_action:
 	sub,<>	%r28, %r25, %r0
 2:	stw	%r24, 0(%r26)
 	/* Free lock */
-	sync
-	stw	%r20, 0(%sr2,%r20)
+	stw,ma	%r20, 0(%sr2,%r20)
 #if ENABLE_LWS_DEBUG
 	/* Clear thread register indicator */
 	stw	%r0, 4(%sr2,%r20)
@@ -655,8 +654,7 @@  cas_action:
 3:		
 	/* Error occurred on load or store */
 	/* Free lock */
-	sync
-	stw	%r20, 0(%sr2,%r20)
+	stw,ma	%r20, 0(%sr2,%r20)
 #if ENABLE_LWS_DEBUG
 	stw	%r0, 4(%sr2,%r20)
 #endif
@@ -857,8 +855,7 @@  cas2_action:
 
 cas2_end:
 	/* Free lock */
-	sync
-	stw	%r20, 0(%sr2,%r20)
+	stw,ma	%r20, 0(%sr2,%r20)
 	/* Enable interrupts */
 	ssm	PSW_SM_I, %r0
 	/* Return to userspace, set no error */
@@ -868,8 +865,7 @@  cas2_end:
 22:
 	/* Error occurred on load or store */
 	/* Free lock */
-	sync
-	stw	%r20, 0(%sr2,%r20)
+	stw,ma	%r20, 0(%sr2,%r20)
 	ssm	PSW_SM_I, %r0
 	ldo	1(%r0),%r28
 	b	lws_exit