From ff383d96babf5c44493c34606ef7485e25d08507 Mon Sep 17 00:00:00 2001 From: Balazs Gerofi Date: Wed, 7 Feb 2018 19:27:33 +0900 Subject: [PATCH] spinlock: rewrite spinlock to use Linux ticket head/tail format This is a cherry-pick of 2964302d094f035242d6257d8af5450f72f9b5a7. Change-Id: Ie8b7e825b28415dd41cc232fbeceb4653251f9e3 --- arch/x86_64/kernel/include/arch-lock.h | 67 ++++++++++++-------------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/arch/x86_64/kernel/include/arch-lock.h b/arch/x86_64/kernel/include/arch-lock.h index f66b66df..5e318ded 100644 --- a/arch/x86_64/kernel/include/arch-lock.h +++ b/arch/x86_64/kernel/include/arch-lock.h @@ -14,7 +14,17 @@ int __kprintf(const char *format, ...); #endif -typedef int ihk_spinlock_t; +typedef unsigned short __ticket_t; +typedef unsigned int __ticketpair_t; + +typedef struct ihk_spinlock { + union { + __ticketpair_t head_tail; + struct __raw_tickets { + __ticket_t head, tail; + } tickets; + }; +} ihk_spinlock_t; extern void preempt_enable(void); extern void preempt_disable(void); @@ -23,9 +33,9 @@ extern void preempt_disable(void); static void ihk_mc_spinlock_init(ihk_spinlock_t *lock) { - *lock = 0; + lock->head_tail = 0; } -#define SPIN_LOCK_UNLOCKED 0 +#define SPIN_LOCK_UNLOCKED { .head_tail = 0 } #ifdef DEBUG_SPINLOCK #define ihk_mc_spinlock_lock_noirq(l) { \ @@ -39,40 +49,24 @@ __kprintf("[%d] ret ihk_mc_spinlock_lock_noirq\n", ihk_mc_get_processor_id()); \ static void __ihk_mc_spinlock_lock_noirq(ihk_spinlock_t *lock) { - int inc = 0x00010000; - int tmp; - -#if 0 - asm volatile("lock ; xaddl %0, %1\n" - "movzwl %w0, %2\n\t" - "shrl $16, %0\n\t" - "1:\t" - "cmpl %0, %2\n\t" - "je 2f\n\t" - "rep ; nop\n\t" - "movzwl %1, %2\n\t" - "jmp 1b\n" - "2:" - : "+Q" (inc), "+m" (*lock), "=r" (tmp) : : "memory", "cc"); -#endif + register struct __raw_tickets inc = { .tail = 0x0002 }; preempt_disable(); - asm volatile("lock; xaddl %0, %1\n" - "movzwl %w0, %2\n\t" - "shrl $16, %0\n\t" - "1:\t" - "cmpl %0, %2\n\t" - "je 2f\n\t" - "rep ; nop\n\t" - "movzwl %1, %2\n\t" - /* don't need lfence here, because loads are in-order */ - "jmp 1b\n" - "2:" - : "+r" (inc), "+m" (*lock), "=&r" (tmp) - : - : "memory", "cc"); + asm volatile ("lock xaddl %0, %1\n" + : "+r" (inc), "+m" (*(lock)) : : "memory", "cc"); + if (inc.head == inc.tail) + goto out; + + for (;;) { + if (*((volatile __ticket_t *)&lock->tickets.head) == inc.tail) + goto out; + cpu_pause(); + } + +out: + barrier(); /* make sure nothing creeps before the lock is taken */ } #ifdef DEBUG_SPINLOCK @@ -106,8 +100,11 @@ __kprintf("[%d] ret ihk_mc_spinlock_unlock_noirq\n", ihk_mc_get_processor_id()); #endif static void __ihk_mc_spinlock_unlock_noirq(ihk_spinlock_t *lock) { - asm volatile ("lock incw %0" : "+m"(*lock) : : "memory", "cc"); - + __ticket_t inc = 0x0002; + + asm volatile ("lock addw %1, %0\n" + : "+m" (lock->tickets.head) : "ri" (inc) : "memory", "cc"); + preempt_enable(); }