From eb74e5b3fee7b6aaf5baefc8734fbe14289b3c63 Mon Sep 17 00:00:00 2001 From: Liujie Xie Date: Tue, 14 Feb 2023 14:42:26 +0800 Subject: [PATCH] ANDROID: vendor_hooks: Add hooks for mutex and rwsem optimistic spin These hooks help us do the following things: a) Record the number of mutex and rwsem optimistic spin. b) Monitor the time of mutex and rwsem optimistic spin. c) Make it possible if oems don't want mutex and rwsem to optimistic spin for a long time. Bug: 267565260 Change-Id: I2bee30fb17946be85e026213b481aeaeaee2459f Signed-off-by: Liujie Xie (cherry picked from commit d01f7e1269d2651768a0bd91a88f76339a1cb427) (cherry picked from commit 05b5ff11ad98c5896b352b4c376a84b63684e06c) --- drivers/android/vendor_hooks.c | 6 ++++++ include/trace/hooks/dtask.h | 18 ++++++++++++++++++ kernel/locking/mutex.c | 10 ++++++++++ kernel/locking/rwsem.c | 12 ++++++++++++ 4 files changed, 46 insertions(+) diff --git a/drivers/android/vendor_hooks.c b/drivers/android/vendor_hooks.c index d508cc353fc3..c835f500ac9d 100644 --- a/drivers/android/vendor_hooks.c +++ b/drivers/android/vendor_hooks.c @@ -73,10 +73,16 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mutex_wait_start); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mutex_wait_finish); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rtmutex_wait_start); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rtmutex_wait_finish); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mutex_opt_spin_start); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mutex_opt_spin_finish); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mutex_can_spin_on_owner); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_read_wait_start); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_read_wait_finish); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_write_wait_start); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_write_wait_finish); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_opt_spin_start); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_opt_spin_finish); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_can_spin_on_owner); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_sched_show_task); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_cpu_idle_enter); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_cpu_idle_exit); diff --git a/include/trace/hooks/dtask.h b/include/trace/hooks/dtask.h index f92996271a1f..4220575c98f8 100644 --- a/include/trace/hooks/dtask.h +++ b/include/trace/hooks/dtask.h @@ -22,6 +22,15 @@ DECLARE_HOOK(android_vh_mutex_wait_start, DECLARE_HOOK(android_vh_mutex_wait_finish, TP_PROTO(struct mutex *lock), TP_ARGS(lock)); +DECLARE_HOOK(android_vh_mutex_opt_spin_start, + TP_PROTO(struct mutex *lock, bool *time_out, int *cnt), + TP_ARGS(lock, time_out, cnt)); +DECLARE_HOOK(android_vh_mutex_opt_spin_finish, + TP_PROTO(struct mutex *lock, bool taken), + TP_ARGS(lock, taken)); +DECLARE_HOOK(android_vh_mutex_can_spin_on_owner, + TP_PROTO(struct mutex *lock, int *retval), + TP_ARGS(lock, retval)); DECLARE_HOOK(android_vh_rtmutex_wait_start, TP_PROTO(struct rt_mutex_base *lock), @@ -42,6 +51,15 @@ DECLARE_HOOK(android_vh_rwsem_write_wait_start, DECLARE_HOOK(android_vh_rwsem_write_wait_finish, TP_PROTO(struct rw_semaphore *sem), TP_ARGS(sem)); +DECLARE_HOOK(android_vh_rwsem_opt_spin_start, + TP_PROTO(struct rw_semaphore *sem, bool *time_out, int *cnt, bool chk_only), + TP_ARGS(sem, time_out, cnt, chk_only)); +DECLARE_HOOK(android_vh_rwsem_opt_spin_finish, + TP_PROTO(struct rw_semaphore *sem, bool taken), + TP_ARGS(sem, taken)); +DECLARE_HOOK(android_vh_rwsem_can_spin_on_owner, + TP_PROTO(struct rw_semaphore *sem, bool *ret), + TP_ARGS(sem, ret)); DECLARE_HOOK(android_vh_sched_show_task, TP_PROTO(struct task_struct *task), diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c index 622dcf7a26b0..44b6ff75d31d 100644 --- a/kernel/locking/mutex.c +++ b/kernel/locking/mutex.c @@ -361,10 +361,17 @@ bool mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner, struct ww_acquire_ctx *ww_ctx, struct mutex_waiter *waiter) { bool ret = true; + int cnt = 0; + bool time_out = false; lockdep_assert_preemption_disabled(); while (__mutex_owner(lock) == owner) { + trace_android_vh_mutex_opt_spin_start(lock, &time_out, &cnt); + if (time_out) { + ret = false; + break; + } /* * Ensure we emit the owner->on_cpu, dereference _after_ * checking lock->owner still matches owner. And we already @@ -415,6 +422,7 @@ static inline int mutex_can_spin_on_owner(struct mutex *lock) owner = __mutex_owner(lock); if (owner) retval = owner_on_cpu(owner); + trace_android_vh_mutex_can_spin_on_owner(lock, &retval); /* * If lock->owner is not set, the mutex has been released. Return true @@ -496,6 +504,7 @@ mutex_optimistic_spin(struct mutex *lock, struct ww_acquire_ctx *ww_ctx, if (!waiter) osq_unlock(&lock->osq); + trace_android_vh_mutex_opt_spin_finish(lock, true); return true; @@ -504,6 +513,7 @@ fail_unlock: osq_unlock(&lock->osq); fail: + trace_android_vh_mutex_opt_spin_finish(lock, false); /* * If we fell out of the spin path because of need_resched(), * reschedule now, before we try-lock the mutex. This avoids getting diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c index 0e6c93fb1f2d..bcf8160bb6ac 100644 --- a/kernel/locking/rwsem.c +++ b/kernel/locking/rwsem.c @@ -734,6 +734,7 @@ static inline bool rwsem_can_spin_on_owner(struct rw_semaphore *sem) (owner && !(flags & RWSEM_READER_OWNED) && !owner_on_cpu(owner))) ret = false; preempt_enable(); + trace_android_vh_rwsem_can_spin_on_owner(sem, &ret); lockevent_cond_inc(rwsem_opt_fail, !ret); return ret; @@ -759,6 +760,8 @@ rwsem_spin_on_owner(struct rw_semaphore *sem) struct task_struct *new, *owner; unsigned long flags, new_flags; enum owner_state state; + int cnt = 0; + bool time_out = false; lockdep_assert_preemption_disabled(); @@ -768,6 +771,9 @@ rwsem_spin_on_owner(struct rw_semaphore *sem) return state; for (;;) { + trace_android_vh_rwsem_opt_spin_start(sem, &time_out, &cnt, true); + if (time_out) + break; /* * When a waiting writer set the handoff flag, it may spin * on the owner as well. Once that writer acquires the lock, @@ -832,6 +838,8 @@ static bool rwsem_optimistic_spin(struct rw_semaphore *sem) int prev_owner_state = OWNER_NULL; int loop = 0; u64 rspin_threshold = 0; + int cnt = 0; + bool time_out = false; preempt_disable(); @@ -848,6 +856,9 @@ static bool rwsem_optimistic_spin(struct rw_semaphore *sem) for (;;) { enum owner_state owner_state; + trace_android_vh_rwsem_opt_spin_start(sem, &time_out, &cnt, false); + if (time_out) + break; owner_state = rwsem_spin_on_owner(sem); if (!(owner_state & OWNER_SPINNABLE)) break; @@ -941,6 +952,7 @@ static bool rwsem_optimistic_spin(struct rw_semaphore *sem) cpu_relax(); } osq_unlock(&sem->osq); + trace_android_vh_rwsem_opt_spin_finish(sem, taken); done: preempt_enable(); lockevent_cond_inc(rwsem_opt_fail, !taken);