Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.3 111 lines 3.8 kB view raw
1/* 2 * include/asm-generic/mutex-xchg.h 3 * 4 * Generic implementation of the mutex fastpath, based on xchg(). 5 * 6 * NOTE: An xchg based implementation might be less optimal than an atomic 7 * decrement/increment based implementation. If your architecture 8 * has a reasonable atomic dec/inc then you should probably use 9 * asm-generic/mutex-dec.h instead, or you could open-code an 10 * optimized version in asm/mutex.h. 11 */ 12#ifndef _ASM_GENERIC_MUTEX_XCHG_H 13#define _ASM_GENERIC_MUTEX_XCHG_H 14 15/** 16 * __mutex_fastpath_lock - try to take the lock by moving the count 17 * from 1 to a 0 value 18 * @count: pointer of type atomic_t 19 * @fail_fn: function to call if the original value was not 1 20 * 21 * Change the count from 1 to a value lower than 1, and call <fail_fn> if it 22 * wasn't 1 originally. This function MUST leave the value lower than 1 23 * even when the "1" assertion wasn't true. 24 */ 25static inline void 26__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *)) 27{ 28 if (unlikely(atomic_xchg(count, 0) != 1)) 29 fail_fn(count); 30} 31 32/** 33 * __mutex_fastpath_lock_retval - try to take the lock by moving the count 34 * from 1 to a 0 value 35 * @count: pointer of type atomic_t 36 * @fail_fn: function to call if the original value was not 1 37 * 38 * Change the count from 1 to a value lower than 1, and call <fail_fn> if it 39 * wasn't 1 originally. This function returns 0 if the fastpath succeeds, 40 * or anything the slow path function returns 41 */ 42static inline int 43__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *)) 44{ 45 if (unlikely(atomic_xchg(count, 0) != 1)) 46 return fail_fn(count); 47 return 0; 48} 49 50/** 51 * __mutex_fastpath_unlock - try to promote the mutex from 0 to 1 52 * @count: pointer of type atomic_t 53 * @fail_fn: function to call if the original value was not 0 54 * 55 * try to promote the mutex from 0 to 1. if it wasn't 0, call <function> 56 * In the failure case, this function is allowed to either set the value to 57 * 1, or to set it to a value lower than one. 58 * If the implementation sets it to a value of lower than one, the 59 * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs 60 * to return 0 otherwise. 61 */ 62static inline void 63__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *)) 64{ 65 if (unlikely(atomic_xchg(count, 1) != 0)) 66 fail_fn(count); 67} 68 69#define __mutex_slowpath_needs_to_unlock() 0 70 71/** 72 * __mutex_fastpath_trylock - try to acquire the mutex, without waiting 73 * 74 * @count: pointer of type atomic_t 75 * @fail_fn: spinlock based trylock implementation 76 * 77 * Change the count from 1 to a value lower than 1, and return 0 (failure) 78 * if it wasn't 1 originally, or return 1 (success) otherwise. This function 79 * MUST leave the value lower than 1 even when the "1" assertion wasn't true. 80 * Additionally, if the value was < 0 originally, this function must not leave 81 * it to 0 on failure. 82 * 83 * If the architecture has no effective trylock variant, it should call the 84 * <fail_fn> spinlock-based trylock variant unconditionally. 85 */ 86static inline int 87__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *)) 88{ 89 int prev = atomic_xchg(count, 0); 90 91 if (unlikely(prev < 0)) { 92 /* 93 * The lock was marked contended so we must restore that 94 * state. If while doing so we get back a prev value of 1 95 * then we just own it. 96 * 97 * [ In the rare case of the mutex going to 1, to 0, to -1 98 * and then back to 0 in this few-instructions window, 99 * this has the potential to trigger the slowpath for the 100 * owner's unlock path needlessly, but that's not a problem 101 * in practice. ] 102 */ 103 prev = atomic_xchg(count, prev); 104 if (prev < 0) 105 prev = 0; 106 } 107 108 return prev; 109} 110 111#endif