locking/rtmutex: Dont dereference waiter lockless
[linux-2.6-microblaze.git] / kernel / locking / rtmutex_common.h
index 9e2f1db..c47e836 100644 (file)
@@ -28,6 +28,7 @@
  * @wake_state:                Wakeup state to use (TASK_NORMAL or TASK_RTLOCK_WAIT)
  * @prio:              Priority of the waiter
  * @deadline:          Deadline of the waiter if applicable
+ * @ww_ctx:            WW context pointer
  */
 struct rt_mutex_waiter {
        struct rb_node          tree_entry;
@@ -37,20 +38,24 @@ struct rt_mutex_waiter {
        unsigned int            wake_state;
        int                     prio;
        u64                     deadline;
+       struct ww_acquire_ctx   *ww_ctx;
 };
 
 /**
  * rt_wake_q_head - Wrapper around regular wake_q_head to support
  *                 "sleeping" spinlocks on RT
- * @head:      The regular wake_q_head for sleeping lock variants
+ * @head:              The regular wake_q_head for sleeping lock variants
+ * @rtlock_task:       Task pointer for RT lock (spin/rwlock) wakeups
  */
 struct rt_wake_q_head {
        struct wake_q_head      head;
+       struct task_struct      *rtlock_task;
 };
 
 #define DEFINE_RT_WAKE_Q(name)                                         \
        struct rt_wake_q_head name = {                                  \
                .head           = WAKE_Q_HEAD_INITIALIZER(name.head),   \
+               .rtlock_task    = NULL,                                 \
        }
 
 /*
@@ -76,9 +81,9 @@ extern int __rt_mutex_futex_trylock(struct rt_mutex_base *l);
 
 extern void rt_mutex_futex_unlock(struct rt_mutex_base *lock);
 extern bool __rt_mutex_futex_unlock(struct rt_mutex_base *lock,
-                               struct wake_q_head *wake_q);
+                               struct rt_wake_q_head *wqh);
 
-extern void rt_mutex_postunlock(struct wake_q_head *wake_q);
+extern void rt_mutex_postunlock(struct rt_wake_q_head *wqh);
 
 /*
  * Must be guarded because this header is included from rcu/tree_plugin.h
@@ -90,6 +95,19 @@ static inline int rt_mutex_has_waiters(struct rt_mutex_base *lock)
        return !RB_EMPTY_ROOT(&lock->waiters.rb_root);
 }
 
+/*
+ * Lockless speculative check whether @waiter is still the top waiter on
+ * @lock. This is solely comparing pointers and not derefencing the
+ * leftmost entry which might be about to vanish.
+ */
+static inline bool rt_mutex_waiter_is_top_waiter(struct rt_mutex_base *lock,
+                                                struct rt_mutex_waiter *waiter)
+{
+       struct rb_node *leftmost = rb_first_cached(&lock->waiters);
+
+       return rb_entry(leftmost, struct rt_mutex_waiter, tree_entry) == waiter;
+}
+
 static inline struct rt_mutex_waiter *rt_mutex_top_waiter(struct rt_mutex_base *lock)
 {
        struct rb_node *leftmost = rb_first_cached(&lock->waiters);
@@ -178,7 +196,7 @@ static inline void rt_mutex_init_waiter(struct rt_mutex_waiter *waiter)
        waiter->task = NULL;
 }
 
-static inline void rtlock_init_rtmutex_waiter(struct rt_mutex_waiter *waiter)
+static inline void rt_mutex_init_rtlock_waiter(struct rt_mutex_waiter *waiter)
 {
        rt_mutex_init_waiter(waiter);
        waiter->wake_state = TASK_RTLOCK_WAIT;