summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/linux/six.h1
-rw-r--r--kernel/locking/six.c17
2 files changed, 17 insertions, 1 deletions
diff --git a/include/linux/six.h b/include/linux/six.h
index f336ae049df8..fe4b6292d773 100644
--- a/include/linux/six.h
+++ b/include/linux/six.h
@@ -119,6 +119,7 @@ struct six_lock_waiter {
struct task_struct *task;
enum six_lock_type lock_want;
bool lock_acquired;
+ u64 start_time;
};
typedef int (*six_lock_should_sleep_fn)(struct six_lock *lock, void *);
diff --git a/kernel/locking/six.c b/kernel/locking/six.c
index 91cbca5a1ae9..18bc060241a2 100644
--- a/kernel/locking/six.c
+++ b/kernel/locking/six.c
@@ -6,6 +6,7 @@
#include <linux/preempt.h>
#include <linux/rcupdate.h>
#include <linux/sched.h>
+#include <linux/sched/clock.h>
#include <linux/sched/rt.h>
#include <linux/six.h>
#include <linux/slab.h>
@@ -421,8 +422,20 @@ static int __six_lock_type_slowpath(struct six_lock *lock, enum six_lock_type ty
* unlock:
*/
ret = __do_six_trylock_type(lock, type, current, false);
- if (ret <= 0)
+ if (ret <= 0) {
+ wait->start_time = local_clock();
+
+ if (!list_empty(&lock->wait_list)) {
+ struct six_lock_waiter *last =
+ list_last_entry(&lock->wait_list,
+ struct six_lock_waiter, list);
+
+ if (time_before_eq64(wait->start_time, last->start_time))
+ wait->start_time = last->start_time + 1;
+ }
+
list_add_tail(&wait->list, &lock->wait_list);
+ }
raw_spin_unlock(&lock->wait_lock);
if (unlikely(ret > 0)) {
@@ -477,6 +490,8 @@ static int __six_lock_type_waiter(struct six_lock *lock, enum six_lock_type type
{
int ret;
+ wait->start_time = 0;
+
if (type != SIX_LOCK_write)
six_acquire(&lock->dep_map, 0);