Blame view

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