cregit-Linux how code gets into the kernel

Release 4.14 arch/x86/include/asm/rwsem.h

/* SPDX-License-Identifier: GPL-2.0 */
/* rwsem.h: R/W semaphores implemented using XADD/CMPXCHG for i486+
 *
 * Written by David Howells (dhowells@redhat.com).
 *
 * Derived from asm-x86/semaphore.h
 *
 *
 * The MSW of the count is the negated number of active writers and waiting
 * lockers, and the LSW is the total number of active locks
 *
 * The lock count is initialized to 0 (no active and no waiting lockers).
 *
 * When a writer subtracts WRITE_BIAS, it'll get 0xffff0001 for the case of an
 * uncontended lock. This can be determined because XADD returns the old value.
 * Readers increment by 1 and see a positive value when uncontended, negative
 * if there are writers (and maybe) readers waiting (in which case it goes to
 * sleep).
 *
 * The value of WAITING_BIAS supports up to 32766 waiting processes. This can
 * be extended to 65534 by manually checking the whole MSW rather than relying
 * on the S flag.
 *
 * The value of ACTIVE_BIAS supports up to 65535 active processes.
 *
 * This should be totally fair - if anything is waiting, a process that wants a
 * lock will go to the back of the queue. When the currently active lock is
 * released, if there's a writer at the front of the queue, then that and only
 * that will be woken up; if there's a bunch of consecutive readers at the
 * front, then they'll all be woken up, but no other readers will be.
 */

#ifndef _ASM_X86_RWSEM_H

#define _ASM_X86_RWSEM_H

#ifndef _LINUX_RWSEM_H
#error "please don't include asm/rwsem.h directly, use linux/rwsem.h instead"
#endif

#ifdef __KERNEL__
#include <asm/asm.h>

/*
 * The bias values and the counter type limits the number of
 * potential readers/writers to 32767 for 32 bits and 2147483647
 * for 64 bits.
 */

#ifdef CONFIG_X86_64

# define RWSEM_ACTIVE_MASK		0xffffffffL
#else

# define RWSEM_ACTIVE_MASK		0x0000ffffL
#endif


#define RWSEM_UNLOCKED_VALUE		0x00000000L

#define RWSEM_ACTIVE_BIAS		0x00000001L

#define RWSEM_WAITING_BIAS		(-RWSEM_ACTIVE_MASK-1)

#define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS

#define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)

/*
 * lock for reading
 */

static inline void __down_read(struct rw_semaphore *sem) { asm volatile("# beginning down_read\n\t" LOCK_PREFIX _ASM_INC "(%1)\n\t" /* adds 0x00000001 */ " jns 1f\n" " call call_rwsem_down_read_failed\n" "1:\n\t" "# ending down_read\n\t" : "+m" (sem->count) : "a" (sem) : "memory", "cc"); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds1270.59%125.00%
Joe Perches317.65%125.00%
H. Peter Anvin15.88%125.00%
Michel Lespinasse15.88%125.00%
Total17100.00%4100.00%

/* * trylock for reading -- returns 1 if successful, 0 if contention */
static inline bool __down_read_trylock(struct rw_semaphore *sem) { long result, tmp; asm volatile("# beginning __down_read_trylock\n\t" " mov %0,%1\n\t" "1:\n\t" " mov %1,%2\n\t" " add %3,%2\n\t" " jle 2f\n\t" LOCK_PREFIX " cmpxchg %2,%0\n\t" " jnz 1b\n\t" "2:\n\t" "# ending __down_read_trylock\n\t" : "+m" (sem->count), "=&a" (result), "=&r" (tmp) : "i" (RWSEM_ACTIVE_READ_BIAS) : "memory", "cc"); return result >= 0; }

Contributors

PersonTokensPropCommitsCommitProp
Christoph Hellwig2080.00%120.00%
Joe Perches28.00%120.00%
Linus Torvalds14.00%120.00%
H. Peter Anvin14.00%120.00%
Thomas Gleixner14.00%120.00%
Total25100.00%5100.00%

/* * lock for writing */ #define ____down_write(sem, slow_path) \ ({ \ long tmp; \ struct rw_semaphore* ret; \ \ asm volatile("# beginning down_write\n\t" \ LOCK_PREFIX " xadd %1,(%4)\n\t" \ /* adds 0xffff0001, returns the old value */ \ " test " __ASM_SEL(%w1,%k1) "," __ASM_SEL(%w1,%k1) "\n\t" \ /* was the active mask 0 before? */\ " jz 1f\n" \ " call " slow_path "\n" \ "1:\n" \ "# ending down_write" \ : "+m" (sem->count), "=d" (tmp), \ "=a" (ret), ASM_CALL_CONSTRAINT \ : "a" (sem), "1" (RWSEM_ACTIVE_WRITE_BIAS) \ : "memory", "cc"); \ ret; \ })
static inline void __down_write(struct rw_semaphore *sem) { ____down_write(sem, "call_rwsem_down_write_failed"); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds1052.63%133.33%
Michal Hocko947.37%266.67%
Total19100.00%3100.00%


static inline int __down_write_killable(struct rw_semaphore *sem) { if (IS_ERR(____down_write(sem, "call_rwsem_down_write_failed_killable"))) return -EINTR; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Michal Hocko3096.77%150.00%
Linus Torvalds13.23%150.00%
Total31100.00%2100.00%

/* * trylock for writing -- returns 1 if successful, 0 if contention */
static inline bool __down_write_trylock(struct rw_semaphore *sem) { bool result; long tmp0, tmp1; asm volatile("# beginning __down_write_trylock\n\t" " mov %0,%1\n\t" "1:\n\t" " test " __ASM_SEL(%w1,%k1) "," __ASM_SEL(%w1,%k1) "\n\t" /* was the active mask 0 before? */ " jnz 2f\n\t" " mov %1,%2\n\t" " add %4,%2\n\t" LOCK_PREFIX " cmpxchg %2,%0\n\t" " jnz 1b\n\t" "2:\n\t" CC_SET(e) "# ending __down_write_trylock\n\t" : "+m" (sem->count), "=&a" (tmp0), "=&r" (tmp1), CC_OUT(e) (result) : "er" (RWSEM_ACTIVE_WRITE_BIAS) : "memory"); return result; }

Contributors

PersonTokensPropCommitsCommitProp
Christoph Hellwig1450.00%125.00%
Michel Lespinasse725.00%125.00%
H. Peter Anvin621.43%125.00%
Jan Beulich13.57%125.00%
Total28100.00%4100.00%

/* * unlock after reading */
static inline void __up_read(struct rw_semaphore *sem) { long tmp; asm volatile("# beginning __up_read\n\t" LOCK_PREFIX " xadd %1,(%2)\n\t" /* subtracts 1, returns the old value */ " jns 1f\n\t" " call call_rwsem_wake\n" /* expects old value in %edx */ "1:\n" "# ending __up_read\n" : "+m" (sem->count), "=d" (tmp) : "a" (sem), "1" (-RWSEM_ACTIVE_READ_BIAS) : "memory", "cc"); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds1672.73%350.00%
Michel Lespinasse313.64%116.67%
Joe Perches29.09%116.67%
Thomas Gleixner14.55%116.67%
Total22100.00%6100.00%

/* * unlock after writing */
static inline void __up_write(struct rw_semaphore *sem) { long tmp; asm volatile("# beginning __up_write\n\t" LOCK_PREFIX " xadd %1,(%2)\n\t" /* subtracts 0xffff0001, returns the old value */ " jns 1f\n\t" " call call_rwsem_wake\n" /* expects old value in %edx */ "1:\n\t" "# ending __up_write\n" : "+m" (sem->count), "=d" (tmp) : "a" (sem), "1" (-RWSEM_ACTIVE_WRITE_BIAS) : "memory", "cc"); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds1568.18%233.33%
Michel Lespinasse418.18%233.33%
Joe Perches29.09%116.67%
Thomas Gleixner14.55%116.67%
Total22100.00%6100.00%

/* * downgrade write lock to read lock */
static inline void __downgrade_write(struct rw_semaphore *sem) { asm volatile("# beginning __downgrade_write\n\t" LOCK_PREFIX _ASM_ADD "%2,(%1)\n\t" /* * transitions 0xZZZZ0001 -> 0xYYYY0001 (i386) * 0xZZZZZZZZ00000001 -> 0xYYYYYYYY00000001 (x86_64) */ " jns 1f\n\t" " call call_rwsem_downgrade_wake\n" "1:\n\t" "# ending __downgrade_write\n" : "+m" (sem->count) : "a" (sem), "er" (-RWSEM_WAITING_BIAS) : "memory", "cc"); }

Contributors

PersonTokensPropCommitsCommitProp
David Howells1270.59%125.00%
Avi Kivity211.76%125.00%
Joe Perches211.76%125.00%
H. Peter Anvin15.88%125.00%
Total17100.00%4100.00%

#endif /* __KERNEL__ */ #endif /* _ASM_X86_RWSEM_H */

Overall Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds9736.47%520.83%
Michal Hocko5119.17%28.33%
Christoph Hellwig3613.53%14.17%
H. Peter Anvin3111.65%312.50%
Michel Lespinasse155.64%312.50%
David Howells134.89%14.17%
Joe Perches114.14%14.17%
Thomas Gleixner41.50%28.33%
Avi Kivity20.75%14.17%
Josh Poimboeuf20.75%14.17%
Jan Beulich10.38%14.17%
Adam Buchbinder10.38%14.17%
Greg Kroah-Hartman10.38%14.17%
Michael Hayes10.38%14.17%
Total266100.00%24100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.