From 1379f5c7581b91d931933db7a4f7108ff52fc98e Mon Sep 17 00:00:00 2001 From: "huteng.ht" Date: Fri, 25 Nov 2022 13:58:43 +0800 Subject: [PATCH] use schedule_timeout_uninterruptible in nv_sleep_ms() nv_sleep_ms() function sets current process to TASK_INTERRUPTIBLE and call schedule_timeout() in a while loop until less than a jiffie remains. It retains in the loop regardless of whether signal is received. What's worse, process in TASK_INTERRUPTIBLE state with pending signal would be set back to TASK_RUNNING in __schedule() function, thus it would be rescheduled again and again, never get into sleep state. For example, processes calling nv_pci_remove() to remove a device which is still in use would stuck in the sleep-check loop until usage_count down do zero. Once SIGKILL received, it would remain in TASK_RUNNING, leading to a CPU usage at 100%. Instead, use schedule_timeout_uninterruptible() to substitute the while loop in nv_sleep_ms(). The process would not be woken up only when the requested timeout has expired. Signed-off-by: huteng.ht --- kernel-open/common/inc/nv-time.h | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/kernel-open/common/inc/nv-time.h b/kernel-open/common/inc/nv-time.h index 7c3f512e0..99eb045d2 100644 --- a/kernel-open/common/inc/nv-time.h +++ b/kernel-open/common/inc/nv-time.h @@ -210,23 +210,18 @@ static inline NV_STATUS nv_sleep_ms(unsigned int ms) { // // If we have at least one full jiffy to wait, give up - // up the CPU; since we may be rescheduled before - // the requested timeout has expired, loop until less + // the CPU until the requested timeout has expired and less // than a jiffie of the desired delay remains. // - set_current_state(TASK_INTERRUPTIBLE); - do + schedule_timeout_uninterruptible(jiffies); + ktime_get_real_ts64(&tm_aux); + if (nv_timer_less_than(&tm_aux, &tm_end)) { - schedule_timeout(jiffies); - ktime_get_raw_ts64(&tm_aux); - if (nv_timer_less_than(&tm_aux, &tm_end)) - { - tm_aux = timespec64_sub(tm_end, tm_aux); - ns = (NvU64) timespec64_to_ns(&tm_aux); - } - else - ns = 0; - } while ((jiffies = NV_NSECS_TO_JIFFIES(ns)) != 0); + tm_aux = timespec64_sub(tm_end, tm_aux); + ns = (NvU64) timespec64_to_ns(&tm_aux); + } + else + ns = 0; } if (ns > (NvU64) NSEC_PER_MSEC)