mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +02:00 
			
		
		
		
	locking/pvqspinlock: Use try_cmpxchg() in qspinlock_paravirt.h
Use try_cmpxchg(*ptr, &old, new) instead of cmpxchg(*ptr, old, new) == old in qspinlock_paravirt.h x86 CMPXCHG instruction returns success in ZF flag, so this change saves a compare after cmpxchg. No functional change intended. Signed-off-by: Uros Bizjak <ubizjak@gmail.com> Signed-off-by: Ingo Molnar <mingo@kernel.org> Reviewed-by: Waiman Long <longman@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Link: https://lore.kernel.org/r/20240411192317.25432-2-ubizjak@gmail.com
This commit is contained in:
		
							parent
							
								
									6a97734f22
								
							
						
					
					
						commit
						fea0e1820b
					
				
					 1 changed files with 8 additions and 8 deletions
				
			
		|  | @ -86,9 +86,10 @@ static inline bool pv_hybrid_queued_unfair_trylock(struct qspinlock *lock) | |||
| 	 */ | ||||
| 	for (;;) { | ||||
| 		int val = atomic_read(&lock->val); | ||||
| 		u8 old = 0; | ||||
| 
 | ||||
| 		if (!(val & _Q_LOCKED_PENDING_MASK) && | ||||
| 		   (cmpxchg_acquire(&lock->locked, 0, _Q_LOCKED_VAL) == 0)) { | ||||
| 		    try_cmpxchg_acquire(&lock->locked, &old, _Q_LOCKED_VAL)) { | ||||
| 			lockevent_inc(pv_lock_stealing); | ||||
| 			return true; | ||||
| 		} | ||||
|  | @ -211,8 +212,9 @@ static struct qspinlock **pv_hash(struct qspinlock *lock, struct pv_node *node) | |||
| 	int hopcnt = 0; | ||||
| 
 | ||||
| 	for_each_hash_entry(he, offset, hash) { | ||||
| 		struct qspinlock *old = NULL; | ||||
| 		hopcnt++; | ||||
| 		if (!cmpxchg(&he->lock, NULL, lock)) { | ||||
| 		if (try_cmpxchg(&he->lock, &old, lock)) { | ||||
| 			WRITE_ONCE(he->node, node); | ||||
| 			lockevent_pv_hop(hopcnt); | ||||
| 			return &he->lock; | ||||
|  | @ -355,7 +357,7 @@ static void pv_wait_node(struct mcs_spinlock *node, struct mcs_spinlock *prev) | |||
| static void pv_kick_node(struct qspinlock *lock, struct mcs_spinlock *node) | ||||
| { | ||||
| 	struct pv_node *pn = (struct pv_node *)node; | ||||
| 
 | ||||
| 	enum vcpu_state old = vcpu_halted; | ||||
| 	/*
 | ||||
| 	 * If the vCPU is indeed halted, advance its state to match that of | ||||
| 	 * pv_wait_node(). If OTOH this fails, the vCPU was running and will | ||||
|  | @ -372,8 +374,7 @@ static void pv_kick_node(struct qspinlock *lock, struct mcs_spinlock *node) | |||
| 	 * subsequent writes. | ||||
| 	 */ | ||||
| 	smp_mb__before_atomic(); | ||||
| 	if (cmpxchg_relaxed(&pn->state, vcpu_halted, vcpu_hashed) | ||||
| 	    != vcpu_halted) | ||||
| 	if (!try_cmpxchg_relaxed(&pn->state, &old, vcpu_hashed)) | ||||
| 		return; | ||||
| 
 | ||||
| 	/*
 | ||||
|  | @ -541,15 +542,14 @@ __pv_queued_spin_unlock_slowpath(struct qspinlock *lock, u8 locked) | |||
| #ifndef __pv_queued_spin_unlock | ||||
| __visible __lockfunc void __pv_queued_spin_unlock(struct qspinlock *lock) | ||||
| { | ||||
| 	u8 locked; | ||||
| 	u8 locked = _Q_LOCKED_VAL; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * We must not unlock if SLOW, because in that case we must first | ||||
| 	 * unhash. Otherwise it would be possible to have multiple @lock | ||||
| 	 * entries, which would be BAD. | ||||
| 	 */ | ||||
| 	locked = cmpxchg_release(&lock->locked, _Q_LOCKED_VAL, 0); | ||||
| 	if (likely(locked == _Q_LOCKED_VAL)) | ||||
| 	if (try_cmpxchg_release(&lock->locked, &locked, 0)) | ||||
| 		return; | ||||
| 
 | ||||
| 	__pv_queued_spin_unlock_slowpath(lock, locked); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Uros Bizjak
						Uros Bizjak