xfs: remove nr_to_write writeback windup.
[safe/jmp/linux-2.6] / kernel / mutex.c
index 4f45d4b..4c0b7b3 100644 (file)
  * Many thanks to Arjan van de Ven, Thomas Gleixner, Steven Rostedt and
  * David Howells for suggestions and improvements.
  *
+ *  - Adaptive spinning for mutexes by Peter Zijlstra. (Ported to mainline
+ *    from the -rt tree, where it was originally implemented for rtmutexes
+ *    by Steven Rostedt, based on work by Gregory Haskins, Peter Morreale
+ *    and Sven Dietrich.
+ *
  * Also see Documentation/mutex-design.txt.
  */
 #include <linux/mutex.h>
@@ -46,6 +51,7 @@ __mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key)
        atomic_set(&lock->count, 1);
        spin_lock_init(&lock->wait_lock);
        INIT_LIST_HEAD(&lock->wait_list);
+       mutex_clear_owner(lock);
 
        debug_mutex_init(lock, name, key);
 }
@@ -83,7 +89,7 @@ __mutex_lock_slowpath(atomic_t *lock_count);
  *
  * This function is similar to (but not equivalent to) down().
  */
-void inline __sched mutex_lock(struct mutex *lock)
+void __sched mutex_lock(struct mutex *lock)
 {
        might_sleep();
        /*
@@ -91,6 +97,7 @@ void inline __sched mutex_lock(struct mutex *lock)
         * 'unlocked' into 'locked' state.
         */
        __mutex_fastpath_lock(&lock->count, __mutex_lock_slowpath);
+       mutex_set_owner(lock);
 }
 
 EXPORT_SYMBOL(mutex_lock);
@@ -115,6 +122,14 @@ void __sched mutex_unlock(struct mutex *lock)
         * The unlocking fastpath is the 0->1 transition from 'locked'
         * into 'unlocked' state:
         */
+#ifndef CONFIG_DEBUG_MUTEXES
+       /*
+        * When debugging is enabled we must not clear the owner before time,
+        * the slow path will always be taken, and that clears the owner field
+        * after verifying that it was indeed current.
+        */
+       mutex_clear_owner(lock);
+#endif
        __mutex_fastpath_unlock(&lock->count, __mutex_unlock_slowpath);
 }
 
@@ -129,21 +144,83 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
 {
        struct task_struct *task = current;
        struct mutex_waiter waiter;
-       unsigned int old_val;
        unsigned long flags;
 
+       preempt_disable();
+       mutex_acquire(&lock->dep_map, subclass, 0, ip);
+
+#ifdef CONFIG_MUTEX_SPIN_ON_OWNER
+       /*
+        * Optimistic spinning.
+        *
+        * We try to spin for acquisition when we find that there are no
+        * pending waiters and the lock owner is currently running on a
+        * (different) CPU.
+        *
+        * The rationale is that if the lock owner is running, it is likely to
+        * release the lock soon.
+        *
+        * Since this needs the lock owner, and this mutex implementation
+        * doesn't track the owner atomically in the lock field, we need to
+        * track it non-atomically.
+        *
+        * We can't do this for DEBUG_MUTEXES because that relies on wait_lock
+        * to serialize everything.
+        */
+
+       for (;;) {
+               struct thread_info *owner;
+
+               /*
+                * If we own the BKL, then don't spin. The owner of
+                * the mutex might be waiting on us to release the BKL.
+                */
+               if (unlikely(current->lock_depth >= 0))
+                       break;
+
+               /*
+                * If there's an owner, wait for it to either
+                * release the lock or go to sleep.
+                */
+               owner = ACCESS_ONCE(lock->owner);
+               if (owner && !mutex_spin_on_owner(lock, owner))
+                       break;
+
+               if (atomic_cmpxchg(&lock->count, 1, 0) == 1) {
+                       lock_acquired(&lock->dep_map, ip);
+                       mutex_set_owner(lock);
+                       preempt_enable();
+                       return 0;
+               }
+
+               /*
+                * When there's no owner, we might have preempted between the
+                * owner acquiring the lock and setting the owner field. If
+                * we're an RT task that will live-lock because we won't let
+                * the owner complete.
+                */
+               if (!owner && (need_resched() || rt_task(task)))
+                       break;
+
+               /*
+                * The cpu_relax() call is a compiler barrier which forces
+                * everything in this loop to be re-loaded. We don't need
+                * memory barriers as we'll eventually observe the right
+                * values at the cost of a few extra spins.
+                */
+               cpu_relax();
+       }
+#endif
        spin_lock_mutex(&lock->wait_lock, flags);
 
        debug_mutex_lock_common(lock, &waiter);
-       mutex_acquire(&lock->dep_map, subclass, 0, ip);
        debug_mutex_add_waiter(lock, &waiter, task_thread_info(task));
 
        /* add waiting tasks to the end of the waitqueue (FIFO): */
        list_add_tail(&waiter.list, &lock->wait_list);
        waiter.task = task;
 
-       old_val = atomic_xchg(&lock->count, -1);
-       if (old_val == 1)
+       if (atomic_xchg(&lock->count, -1) == 1)
                goto done;
 
        lock_contended(&lock->dep_map, ip);
@@ -158,8 +235,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
                 * that when we release the lock, we properly wake up the
                 * other waiters:
                 */
-               old_val = atomic_xchg(&lock->count, -1);
-               if (old_val == 1)
+               if (atomic_xchg(&lock->count, -1) == 1)
                        break;
 
                /*
@@ -173,21 +249,24 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
                        spin_unlock_mutex(&lock->wait_lock, flags);
 
                        debug_mutex_free_waiter(&waiter);
+                       preempt_enable();
                        return -EINTR;
                }
                __set_task_state(task, state);
 
                /* didnt get the lock, go to sleep: */
                spin_unlock_mutex(&lock->wait_lock, flags);
+               preempt_enable_no_resched();
                schedule();
+               preempt_disable();
                spin_lock_mutex(&lock->wait_lock, flags);
        }
 
 done:
        lock_acquired(&lock->dep_map, ip);
        /* got the lock - rejoice! */
-       mutex_remove_waiter(lock, &waiter, task_thread_info(task));
-       debug_mutex_set_owner(lock, task_thread_info(task));
+       mutex_remove_waiter(lock, &waiter, current_thread_info());
+       mutex_set_owner(lock);
 
        /* set it to 0 if there are no waiters left: */
        if (likely(list_empty(&lock->wait_list)))
@@ -196,6 +275,7 @@ done:
        spin_unlock_mutex(&lock->wait_lock, flags);
 
        debug_mutex_free_waiter(&waiter);
+       preempt_enable();
 
        return 0;
 }
@@ -222,7 +302,8 @@ int __sched
 mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass)
 {
        might_sleep();
-       return __mutex_lock_common(lock, TASK_INTERRUPTIBLE, subclass, _RET_IP_);
+       return __mutex_lock_common(lock, TASK_INTERRUPTIBLE,
+                                  subclass, _RET_IP_);
 }
 
 EXPORT_SYMBOL_GPL(mutex_lock_interruptible_nested);
@@ -260,8 +341,6 @@ __mutex_unlock_common_slowpath(atomic_t *lock_count, int nested)
                wake_up_process(waiter->task);
        }
 
-       debug_mutex_clear_owner(lock);
-
        spin_unlock_mutex(&lock->wait_lock, flags);
 }
 
@@ -298,18 +377,30 @@ __mutex_lock_interruptible_slowpath(atomic_t *lock_count);
  */
 int __sched mutex_lock_interruptible(struct mutex *lock)
 {
+       int ret;
+
        might_sleep();
-       return __mutex_fastpath_lock_retval
+       ret =  __mutex_fastpath_lock_retval
                        (&lock->count, __mutex_lock_interruptible_slowpath);
+       if (!ret)
+               mutex_set_owner(lock);
+
+       return ret;
 }
 
 EXPORT_SYMBOL(mutex_lock_interruptible);
 
 int __sched mutex_lock_killable(struct mutex *lock)
 {
+       int ret;
+
        might_sleep();
-       return __mutex_fastpath_lock_retval
+       ret = __mutex_fastpath_lock_retval
                        (&lock->count, __mutex_lock_killable_slowpath);
+       if (!ret)
+               mutex_set_owner(lock);
+
+       return ret;
 }
 EXPORT_SYMBOL(mutex_lock_killable);
 
@@ -352,9 +443,10 @@ static inline int __mutex_trylock_slowpath(atomic_t *lock_count)
 
        prev = atomic_xchg(&lock->count, -1);
        if (likely(prev == 1)) {
-               debug_mutex_set_owner(lock, current_thread_info());
+               mutex_set_owner(lock);
                mutex_acquire(&lock->dep_map, 0, 1, _RET_IP_);
        }
+
        /* Set it back to 0 if there are no waiters: */
        if (likely(list_empty(&lock->wait_list)))
                atomic_set(&lock->count, 0);
@@ -380,8 +472,36 @@ static inline int __mutex_trylock_slowpath(atomic_t *lock_count)
  */
 int __sched mutex_trylock(struct mutex *lock)
 {
-       return __mutex_fastpath_trylock(&lock->count,
-                                       __mutex_trylock_slowpath);
-}
+       int ret;
 
+       ret = __mutex_fastpath_trylock(&lock->count, __mutex_trylock_slowpath);
+       if (ret)
+               mutex_set_owner(lock);
+
+       return ret;
+}
 EXPORT_SYMBOL(mutex_trylock);
+
+/**
+ * atomic_dec_and_mutex_lock - return holding mutex if we dec to 0
+ * @cnt: the atomic which we are to dec
+ * @lock: the mutex to return holding if we dec to 0
+ *
+ * return true and hold lock if we dec to 0, return false otherwise
+ */
+int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock)
+{
+       /* dec if we can't possibly hit 0 */
+       if (atomic_add_unless(cnt, -1, 1))
+               return 0;
+       /* we might hit 0, so take the lock */
+       mutex_lock(lock);
+       if (!atomic_dec_and_test(cnt)) {
+               /* when we actually did the dec, we didn't hit 0 */
+               mutex_unlock(lock);
+               return 0;
+       }
+       /* we hit 0, and we hold the lock */
+       return 1;
+}
+EXPORT_SYMBOL(atomic_dec_and_mutex_lock);