arch/powerpc/include/asm/simple_spinlock.h

Source file repositories/reference/linux-study-clean/arch/powerpc/include/asm/simple_spinlock.h

File Facts

System
Linux kernel
Corpus path
arch/powerpc/include/asm/simple_spinlock.h
Extension
.h
Size
6242 bytes
Lines
269
Domain
Architecture Layer
Bucket
arch/powerpc
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

static inline void splpar_spin_yield(arch_spinlock_t *lock) {}
static inline void splpar_rw_yield(arch_rwlock_t *lock) {}
#endif

static inline void spin_yield(arch_spinlock_t *lock)
{
	if (is_shared_processor())
		splpar_spin_yield(lock);
	else
		barrier();
}

static inline void rw_yield(arch_rwlock_t *lock)
{
	if (is_shared_processor())
		splpar_rw_yield(lock);
	else
		barrier();
}

static inline void arch_spin_lock(arch_spinlock_t *lock)
{
	while (1) {
		if (likely(__arch_spin_trylock(lock) == 0))
			break;
		do {
			HMT_low();
			if (is_shared_processor())
				splpar_spin_yield(lock);
		} while (unlikely(lock->slock != 0));
		HMT_medium();
	}
}

static inline void arch_spin_unlock(arch_spinlock_t *lock)
{
	kcsan_mb();
	__asm__ __volatile__("# arch_spin_unlock\n\t"
				PPC_RELEASE_BARRIER: : :"memory");
	lock->slock = 0;
}

/*
 * 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.
 */

#ifdef CONFIG_PPC64
#define __DO_SIGN_EXTEND	"extsw	%0,%0\n"
#define WRLOCK_TOKEN		LOCK_TOKEN	/* it's negative */
#else
#define __DO_SIGN_EXTEND
#define WRLOCK_TOKEN		(-1)
#endif

/*
 * This returns the old value in the lock + 1,
 * so we got a read lock if the return value is > 0.
 */
static inline long __arch_read_trylock(arch_rwlock_t *rw)
{
	long tmp;
	unsigned int eh = IS_ENABLED(CONFIG_PPC64);

	__asm__ __volatile__(
"1:	lwarx		%0,0,%1,%[eh]\n"
	__DO_SIGN_EXTEND
"	addic.		%0,%0,1\n\
	ble-		2f\n"
"	stwcx.		%0,0,%1\n\
	bne-		1b\n"
	PPC_ACQUIRE_BARRIER
"2:"	: "=&r" (tmp)
	: "r" (&rw->lock), [eh] "n" (eh)
	: "cr0", "xer", "memory");

	return tmp;
}

/*
 * This returns the old value in the lock,
 * so we got the write lock if the return value is 0.
 */
static inline long __arch_write_trylock(arch_rwlock_t *rw)

Annotation

Implementation Notes