Directed yield: direct yield of spinlocks for s390.
Subsystems (2)
PATCH 2/2 Directed yield: direct yield of spinlocks for s390.
From: Martin Schwidefsky <[email protected]>
[patch 2/2] Directed yield: direct yield of spinlocks for s390.
Use the new diagnose 0x9c in the spinlock implementation for s390. It yields the remaining timeslice of the virtual cpu that tries to acquire a lock to the virtual cpu that is the current holder of the lock.
Signed-off-by Martin Schwidefsky <[email protected]>
---
arch/s390/kernel/head31.S | 11 ++++++ arch/s390/kernel/head64.S | 11 ++++++ arch/s390/lib/spinlock.c | 62 +++++++++++++++++++++++--------------- include/asm-s390/setup.h | 1 include/asm-s390/spinlock.h | 31 +++++++++++++------ include/asm-s390/spinlock_types.h | 6 +-- 6 files changed, 87 insertions(+), 35 deletions(-)
arch/s390/kernel/head31.S +11 -0
@@ -254,6 +254,16 @@ startup_continue: oi 3(%r12),0x80 # set IDTE flag .Lchkidte: +# +# find out if the diag 0x9c is available +# + mvc __LC_PGM_NEW_PSW(8),.Lpcdiag9c-.LPG1(%r13) + stap __LC_CPUID+4 # store cpu address + lh %r1,__LC_CPUID+4 + diag %r1,0,0x9c # test diag 0x9c + oi 2(%r12),1 # set diag9c flag +.Lchkdiag9c: + lpsw .Lentry-.LPG1(13) # jump to _stext in primary-space, # virtual and never return ... .align 8
@@ -281,6 +291,7 @@ startup_continue: .Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp .Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg .Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte +.Lpcdiag9c:.long 0x00080000,0x80000000 + .Lchkdiag9c .Lmemsize:.long memory_size .Lmchunk:.long memory_chunk .Lmflags:.long machine_flags
arch/s390/kernel/head64.S +11 -0
@@ -251,6 +251,17 @@ startup_continue: 0: # +# find out if the diag 0x9c is available +# + la %r1,0f-.LPG1(%r13) # set program check address + stg %r1,__LC_PGM_NEW_PSW+8 + stap __LC_CPUID+4 # store cpu address + lh %r1,__LC_CPUID+4 + diag %r1,0,0x9c # test diag 0x9c + oi 6(%r12),1 # set diag9c flag +0: + +# # find out if we have the MVCOS instruction # la %r1,0f-.LPG1(%r13) # set program check address
arch/s390/lib/spinlock.c +39 -23
126 lines not on this page · raw message
include/asm-s390/setup.h +1 -0
@@ -39,6 +39,7 @@ extern unsigned long machine_flags;#define MACHINE_IS_P390 (machine_flags & 4)#define MACHINE_HAS_MVPG (machine_flags & 16)#define MACHINE_HAS_IDTE (machine_flags & 128) +#define MACHINE_HAS_DIAG9C (machine_flags & 256)#ifndef __s390x__#define MACHINE_HAS_IEEE (machine_flags & 2)
include/asm-s390/spinlock.h +22 -9
@@ -11,6 +11,8 @@#ifndef __ASM_SPINLOCK_H#define __ASM_SPINLOCK_H +#include <linux/smp.h> +static inline int _raw_compare_and_swap (volatile unsigned int *lock,unsigned int old,unsigned int new)
@@ -31,34 +33,46 @@ _raw_compare_and_swap(volatile unsigned* (the type definitions are in asm/spinlock_types.h) */ -#define __raw_spin_is_locked (x) ((x)->lock != 0) +#define __raw_spin_is_locked (x) ((x)->owner_cpu != 0)#define __raw_spin_lock_flags (lock, flags) __raw_spin_lock(lock)#define __raw_spin_unlock_wait (lock) \ - do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0) + do { while (__raw_spin_is_locked(lock)) \ + _raw_spin_relax(lock); } while (0) -extern void _raw_spin_lock_wait (raw_spinlock_t *lp,unsigned int pc); -extern int _raw_spin_trylock_retry (raw_spinlock_t *lp,unsigned int pc); +extern void _raw_spin_lock_wait (raw_spinlock_t *,unsigned int pc); +extern int _raw_spin_trylock_retry (raw_spinlock_t *,unsigned int pc); +extern void _raw_spin_relax (raw_spinlock_t *lock);static inline void __raw_spin_lock (raw_spinlock_t *lp) {unsigned long pc =1 | (unsigned long )__builtin_return_address (0 ); +int old; -if (unlikely (_raw_compare_and_swap (&lp->lock,0 , pc) !=0 )) -_raw_spin_lock_wait (lp, pc); + old =_raw_compare_and_swap (&lp->owner_cpu,0 , ~smp_processor_id ()); +if (likely (old ==0 )) { + lp->owner_pc = pc; +return ; + } +_raw_spin_lock_wait (lp, pc); }static inline int __raw_spin_trylock (raw_spinlock_t *lp) {unsigned long pc =1 | (unsigned long )__builtin_return_address (0 ); +int old; -if (likely (_raw_compare_and_swap (&lp->lock,0 , pc) ==0 )) + old =_raw_compare_and_swap (&lp->owner_cpu,0 , ~smp_processor_id ()); +if (likely (old ==0 )) { + lp->owner_pc = pc;return 1 ; + }return _raw_spin_trylock_retry (lp, pc); }static inline void __raw_spin_unlock (raw_spinlock_t *lp) { -_raw_compare_and_swap (&lp->lock, lp->lock,0 ); + lp->owner_pc =0 ; +_raw_compare_and_swap (&lp->owner_cpu, lp->owner_cpu,0 ); }/*
@@ -135,7 +149,6 @@ static inline int __raw_write_trylock(rareturn _raw_write_trylock_retry (rw); } -#define _raw_spin_relax (lock) cpu_relax()#define _raw_read_relax (lock) cpu_relax()#define _raw_write_relax (lock) cpu_relax()
include/asm-s390/spinlock_types.h +3 -3
@@ -6,16 +6,16 @@#endif typedef struct { -volatile unsigned int lock; +volatile unsigned int owner_cpu; +volatile unsigned int owner_pc; } __attribute__ ((aligned (4 )))raw_spinlock_t ;#define __RAW_SPIN_LOCK_UNLOCKED { 0 }typedef struct {volatile unsigned int lock; -volatile unsigned int owner_pc; }raw_rwlock_t ; -#define __RAW_RW_LOCK_UNLOCKED { 0, 0 } +#define __RAW_RW_LOCK_UNLOCKED { 0 }#endif