Release 4.8 arch/x86/include/asm/spinlock.h
#ifndef _ASM_X86_SPINLOCK_H
#define _ASM_X86_SPINLOCK_H
#include <linux/jump_label.h>
#include <linux/atomic.h>
#include <asm/page.h>
#include <asm/processor.h>
#include <linux/compiler.h>
#include <asm/paravirt.h>
#include <asm/bitops.h>
/*
* Your basic SMP spinlocks, allowing only a single CPU anywhere
*
* Simple spin lock operations. There are two variants, one clears IRQ's
* on the local processor, one does not.
*
* These are fair FIFO ticket locks, which support up to 2^16 CPUs.
*
* (the type definitions are in asm/spinlock_types.h)
*/
#ifdef CONFIG_X86_32
# define LOCK_PTR_REG "a"
#else
# define LOCK_PTR_REG "D"
#endif
#if defined(CONFIG_X86_32) && (defined(CONFIG_X86_PPRO_FENCE))
/*
* On PPro SMP, we use a locked operation to unlock
* (PPro errata 66, 92)
*/
# define UNLOCK_LOCK_PREFIX LOCK_PREFIX
#else
# define UNLOCK_LOCK_PREFIX
#endif
/* How long a lock should spin before we consider blocking */
#define SPIN_THRESHOLD (1 << 15)
extern struct static_key paravirt_ticketlocks_enabled;
static __always_inline bool static_key_false(struct static_key *key);
#ifdef CONFIG_QUEUED_SPINLOCKS
#include <asm/qspinlock.h>
#else
#ifdef CONFIG_PARAVIRT_SPINLOCKS
static inline void __ticket_enter_slowpath(arch_spinlock_t *lock)
{
set_bit(0, (volatile unsigned long *)&lock->tickets.head);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| jeremy fitzhardinge | jeremy fitzhardinge | 28 | 96.55% | 1 | 50.00% |
| raghavendra k t* (same as raghavendra koushik) | raghavendra k t* (same as raghavendra koushik) | 1 | 3.45% | 1 | 50.00% |
| Total | 29 | 100.00% | 2 | 100.00% |
#else /* !CONFIG_PARAVIRT_SPINLOCKS */
static __always_inline void __ticket_lock_spinning(arch_spinlock_t *lock,
__ticket_t ticket)
{
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| jeremy fitzhardinge | jeremy fitzhardinge | 13 | 100.00% | 2 | 100.00% |
| Total | 13 | 100.00% | 2 | 100.00% |
static inline void __ticket_unlock_kick(arch_spinlock_t *lock,
__ticket_t ticket)
{
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| jeremy fitzhardinge | jeremy fitzhardinge | 13 | 100.00% | 2 | 100.00% |
| Total | 13 | 100.00% | 2 | 100.00% |
#endif /* CONFIG_PARAVIRT_SPINLOCKS */
static inline int __tickets_equal(__ticket_t one, __ticket_t two)
{
return !((one ^ two) & ~TICKET_SLOWPATH_FLAG);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| raghavendra k t* (same as raghavendra koushik) | raghavendra k t* (same as raghavendra koushik) | 26 | 100.00% | 1 | 100.00% |
| Total | 26 | 100.00% | 1 | 100.00% |
static inline void __ticket_check_and_clear_slowpath(arch_spinlock_t *lock,
__ticket_t head)
{
if (head & TICKET_SLOWPATH_FLAG) {
arch_spinlock_t old, new;
old.tickets.head = head;
new.tickets.head = head & ~TICKET_SLOWPATH_FLAG;
old.tickets.tail = new.tickets.head + TICKET_LOCK_INC;
new.tickets.tail = old.tickets.tail;
/* try to clear slowpath flag when there are no contenders */
cmpxchg(&lock->head_tail, old.head_tail, new.head_tail);
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| raghavendra k t* (same as raghavendra koushik) | raghavendra k t* (same as raghavendra koushik) | 89 | 100.00% | 1 | 100.00% |
| Total | 89 | 100.00% | 1 | 100.00% |
static __always_inline int arch_spin_value_unlocked(arch_spinlock_t lock)
{
return __tickets_equal(lock.tickets.head, lock.tickets.tail);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| linus torvalds | linus torvalds | 22 | 84.62% | 1 | 50.00% |
| raghavendra k t* (same as raghavendra koushik) | raghavendra k t* (same as raghavendra koushik) | 4 | 15.38% | 1 | 50.00% |
| Total | 26 | 100.00% | 2 | 100.00% |
/*
* Ticket locks are conceptually two parts, one indicating the current head of
* the queue, and the other indicating the current tail. The lock is acquired
* by atomically noting the tail and incrementing it by one (thus adding
* ourself to the queue and noting our position), then waiting until the head
* becomes equal to the the initial value of the tail.
*
* We use an xadd covering *both* parts of the lock, to increment the tail and
* also load the position of the head, which takes care of memory ordering
* issues and should be optimal for the uncontended case. Note the tail must be
* in the high part, because a wide xadd increment of the low part would carry
* up and contaminate the high part.
*/
static __always_inline void arch_spin_lock(arch_spinlock_t *lock)
{
register struct __raw_tickets inc = { .tail = TICKET_LOCK_INC };
inc = xadd(&lock->tickets, inc);
if (likely(inc.head == inc.tail))
goto out;
for (;;) {
unsigned count = SPIN_THRESHOLD;
do {
inc.head = READ_ONCE(lock->tickets.head);
if (__tickets_equal(inc.head, inc.tail))
goto clear_slowpath;
cpu_relax();
} while (--count);
__ticket_lock_spinning(lock, inc.tail);
}
clear_slowpath:
__ticket_check_and_clear_slowpath(lock, inc.head);
out:
barrier(); /* make sure nothing creeps before the lock is taken */
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| jeremy fitzhardinge | jeremy fitzhardinge | 91 | 70.00% | 6 | 50.00% |
| raghavendra k t* (same as raghavendra koushik) | raghavendra k t* (same as raghavendra koushik) | 26 | 20.00% | 1 | 8.33% |
| thomas gleixner | thomas gleixner | 8 | 6.15% | 2 | 16.67% |
| jan beulich | jan beulich | 3 | 2.31% | 1 | 8.33% |
| christian borntraeger | christian borntraeger | 1 | 0.77% | 1 | 8.33% |
| nick piggin | nick piggin | 1 | 0.77% | 1 | 8.33% |
| Total | 130 | 100.00% | 12 | 100.00% |
static __always_inline int arch_spin_trylock(arch_spinlock_t *lock)
{
arch_spinlock_t old, new;
old.tickets = READ_ONCE(lock->tickets);
if (!__tickets_equal(old.tickets.head, old.tickets.tail))
return 0;
new.head_tail = old.head_tail + (TICKET_LOCK_INC << TICKET_SHIFT);
new.head_tail &= ~TICKET_SLOWPATH_FLAG;
/* cmpxchg is a full barrier, so nothing can move before it */
return cmpxchg(&lock->head_tail, old.head_tail, new.head_tail) == old.head_tail;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| jeremy fitzhardinge | jeremy fitzhardinge | 67 | 73.63% | 5 | 41.67% |
| raghavendra k t* (same as raghavendra koushik) | raghavendra k t* (same as raghavendra koushik) | 10 | 10.99% | 1 | 8.33% |
| thomas gleixner | thomas gleixner | 7 | 7.69% | 2 | 16.67% |
| nick piggin | nick piggin | 3 | 3.30% | 1 | 8.33% |
| jan beulich | jan beulich | 3 | 3.30% | 2 | 16.67% |
| christian borntraeger | christian borntraeger | 1 | 1.10% | 1 | 8.33% |
| Total | 91 | 100.00% | 12 | 100.00% |
static __always_inline void arch_spin_unlock(arch_spinlock_t *lock)
{
if (TICKET_SLOWPATH_FLAG &&
static_key_false(¶virt_ticketlocks_enabled)) {
__ticket_t head;
BUILD_BUG_ON(((__ticket_t)NR_CPUS) != NR_CPUS);
head = xadd(&lock->tickets.head, TICKET_LOCK_INC);
if (unlikely(head & TICKET_SLOWPATH_FLAG)) {
head &= ~TICKET_SLOWPATH_FLAG;
__ticket_unlock_kick(lock, (head + TICKET_LOCK_INC));
}
} else
__add(&lock->tickets.head, TICKET_LOCK_INC, UNLOCK_LOCK_PREFIX);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| jeremy fitzhardinge | jeremy fitzhardinge | 52 | 55.32% | 4 | 50.00% |
| raghavendra k t* (same as raghavendra koushik) | raghavendra k t* (same as raghavendra koushik) | 30 | 31.91% | 1 | 12.50% |
| jan beulich | jan beulich | 8 | 8.51% | 1 | 12.50% |
| nick piggin | nick piggin | 3 | 3.19% | 1 | 12.50% |
| thomas gleixner | thomas gleixner | 1 | 1.06% | 1 | 12.50% |
| Total | 94 | 100.00% | 8 | 100.00% |
static inline int arch_spin_is_locked(arch_spinlock_t *lock)
{
struct __raw_tickets tmp = READ_ONCE(lock->tickets);
return !__tickets_equal(tmp.tail, tmp.head);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| nick piggin | nick piggin | 18 | 51.43% | 1 | 14.29% |
| jeremy fitzhardinge | jeremy fitzhardinge | 8 | 22.86% | 2 | 28.57% |
| raghavendra k t* (same as raghavendra koushik) | raghavendra k t* (same as raghavendra koushik) | 5 | 14.29% | 1 | 14.29% |
| linus torvalds | linus torvalds | 2 | 5.71% | 1 | 14.29% |
| thomas gleixner | thomas gleixner | 1 | 2.86% | 1 | 14.29% |
| christian borntraeger | christian borntraeger | 1 | 2.86% | 1 | 14.29% |
| Total | 35 | 100.00% | 7 | 100.00% |
static inline int arch_spin_is_contended(arch_spinlock_t *lock)
{
struct __raw_tickets tmp = READ_ONCE(lock->tickets);
tmp.head &= ~TICKET_SLOWPATH_FLAG;
return (__ticket_t)(tmp.tail - tmp.head) > TICKET_LOCK_INC;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| nick piggin | nick piggin | 18 | 40.00% | 1 | 10.00% |
| jeremy fitzhardinge | jeremy fitzhardinge | 11 | 24.44% | 4 | 40.00% |
| raghavendra k t* (same as raghavendra koushik) | raghavendra k t* (same as raghavendra koushik) | 7 | 15.56% | 1 | 10.00% |
| tahsin erdogan | tahsin erdogan | 5 | 11.11% | 1 | 10.00% |
| linus torvalds | linus torvalds | 2 | 4.44% | 1 | 10.00% |
| thomas gleixner | thomas gleixner | 1 | 2.22% | 1 | 10.00% |
| christian borntraeger | christian borntraeger | 1 | 2.22% | 1 | 10.00% |
| Total | 45 | 100.00% | 10 | 100.00% |
#define arch_spin_is_contended arch_spin_is_contended
static __always_inline void arch_spin_lock_flags(arch_spinlock_t *lock,
unsigned long flags)
{
arch_spin_lock(lock);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| jeremy fitzhardinge | jeremy fitzhardinge | 17 | 85.00% | 1 | 33.33% |
| thomas gleixner | thomas gleixner | 3 | 15.00% | 2 | 66.67% |
| Total | 20 | 100.00% | 3 | 100.00% |
static inline void arch_spin_unlock_wait(arch_spinlock_t *lock)
{
__ticket_t head = READ_ONCE(lock->tickets.head);
for (;;) {
struct __raw_tickets tmp = READ_ONCE(lock->tickets);
/*
* We need to check "unlocked" in a loop, tmp.head == head
* can be false positive because of overflow.
*/
if (__tickets_equal(tmp.head, tmp.tail) ||
!__tickets_equal(tmp.head, head))
break;
cpu_relax();
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| oleg nesterov | oleg nesterov | 40 | 57.97% | 1 | 20.00% |
| thomas gleixner | thomas gleixner | 18 | 26.09% | 3 | 60.00% |
| raghavendra k t* (same as raghavendra koushik) | raghavendra k t* (same as raghavendra koushik) | 11 | 15.94% | 1 | 20.00% |
| Total | 69 | 100.00% | 5 | 100.00% |
#endif /* CONFIG_QUEUED_SPINLOCKS */
/*
* Read-write spinlocks, allowing multiple readers
* but only one writer.
*
* NOTE! it is quite common to have readers in interrupts
* but no interrupt writers. For those circumstances we
* can "mix" irq-safe locks - any writer needs to get a
* irq-safe write-lock, but readers can get non-irqsafe
* read-locks.
*
* On x86, we implement read-write locks using the generic qrwlock with
* x86 specific optimization.
*/
#include <asm/qrwlock.h>
#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
#define arch_spin_relax(lock) cpu_relax()
#define arch_read_relax(lock) cpu_relax()
#define arch_write_relax(lock) cpu_relax()
#endif /* _ASM_X86_SPINLOCK_H */
Overall Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| jeremy fitzhardinge | jeremy fitzhardinge | 340 | 40.48% | 12 | 31.58% |
| raghavendra k t* (same as raghavendra koushik) | raghavendra k t* (same as raghavendra koushik) | 209 | 24.88% | 1 | 2.63% |
| thomas gleixner | thomas gleixner | 87 | 10.36% | 5 | 13.16% |
| nick piggin | nick piggin | 70 | 8.33% | 2 | 5.26% |
| oleg nesterov | oleg nesterov | 40 | 4.76% | 1 | 2.63% |
| linus torvalds | linus torvalds | 26 | 3.10% | 2 | 5.26% |
| robin holt | robin holt | 14 | 1.67% | 1 | 2.63% |
| jan beulich | jan beulich | 14 | 1.67% | 2 | 5.26% |
| waiman long | waiman long | 13 | 1.55% | 3 | 7.89% |
| glauber de oliveira costa | glauber de oliveira costa | 8 | 0.95% | 1 | 2.63% |
| tahsin erdogan | tahsin erdogan | 5 | 0.60% | 1 | 2.63% |
| christian borntraeger | christian borntraeger | 4 | 0.48% | 1 | 2.63% |
| h. peter anvin | h. peter anvin | 3 | 0.36% | 1 | 2.63% |
| ingo molnar | ingo molnar | 2 | 0.24% | 1 | 2.63% |
| kyle mcmartin | kyle mcmartin | 2 | 0.24% | 1 | 2.63% |
| richard weinberger | richard weinberger | 1 | 0.12% | 1 | 2.63% |
| dave jones | dave jones | 1 | 0.12% | 1 | 2.63% |
| arun sharma | arun sharma | 1 | 0.12% | 1 | 2.63% |
| Total | 840 | 100.00% | 38 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.