diff options
Diffstat (limited to 'mm/ksm.c')
| -rw-r--r-- | mm/ksm.c | 65 |
1 files changed, 64 insertions, 1 deletions
@@ -223,6 +223,9 @@ static unsigned int ksm_thread_pages_to_scan = 100; /* Milliseconds ksmd should sleep between batches */ static unsigned int ksm_thread_sleep_millisecs = 20; +/* Boolean to indicate whether to use deferred timer or not */ +static bool use_deferred_timer; + #ifdef CONFIG_NUMA /* Zeroed when merging across nodes is not allowed */ static unsigned int ksm_merge_across_nodes = 1; @@ -1724,6 +1727,41 @@ static void ksm_do_scan(unsigned int scan_npages) } } +static void process_timeout(unsigned long __data) +{ + wake_up_process((struct task_struct *)__data); +} + +static signed long __sched deferred_schedule_timeout(signed long timeout) +{ + struct timer_list timer; + unsigned long expire; + + __set_current_state(TASK_INTERRUPTIBLE); + if (timeout < 0) { + pr_err("schedule_timeout: wrong timeout value %lx\n", + timeout); + __set_current_state(TASK_RUNNING); + goto out; + } + + expire = timeout + jiffies; + + setup_deferrable_timer_on_stack(&timer, process_timeout, + (unsigned long)current); + mod_timer(&timer, expire); + schedule(); + del_singleshot_timer_sync(&timer); + + /* Remove the timer from the object tracker */ + destroy_timer_on_stack(&timer); + + timeout = expire - jiffies; + +out: + return timeout < 0 ? 0 : timeout; +} + static int ksmd_should_run(void) { return (ksm_run & KSM_RUN_MERGE) && !list_empty(&ksm_mm_head.mm_list); @@ -1744,7 +1782,11 @@ static int ksm_scan_thread(void *nothing) try_to_freeze(); if (ksmd_should_run()) { - schedule_timeout_interruptible( + if (use_deferred_timer) + deferred_schedule_timeout( + msecs_to_jiffies(ksm_thread_sleep_millisecs)); + else + schedule_timeout_interruptible( msecs_to_jiffies(ksm_thread_sleep_millisecs)); } else { wait_event_freezable(ksm_thread_wait, @@ -2196,6 +2238,26 @@ static ssize_t run_store(struct kobject *kobj, struct kobj_attribute *attr, } KSM_ATTR(run); +static ssize_t deferred_timer_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return snprintf(buf, 8, "%d\n", use_deferred_timer); +} + +static ssize_t deferred_timer_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + unsigned long enable; + int err; + + err = kstrtoul(buf, 10, &enable); + use_deferred_timer = enable; + + return count; +} +KSM_ATTR(deferred_timer); + #ifdef CONFIG_NUMA static ssize_t merge_across_nodes_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) @@ -2308,6 +2370,7 @@ static struct attribute *ksm_attrs[] = { &pages_unshared_attr.attr, &pages_volatile_attr.attr, &full_scans_attr.attr, + &deferred_timer_attr.attr, #ifdef CONFIG_NUMA &merge_across_nodes_attr.attr, #endif |
