Loading Documentation/vm/ksm.txt +7 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,13 @@ pages_sharing - how many more sites are sharing them i.e. how much saved pages_unshared - how many pages unique but repeatedly checked for merging pages_volatile - how many pages changing too fast to be placed in a tree full_scans - how many times all mergeable areas have been scanned deferred_timer - whether to use deferred timers or not e.g. "echo 1 > /sys/kernel/mm/ksm/deferred_timer" Default: 0 (means, we are not using deferred timers. Users might want to set deferred_timer option if they donot want ksm thread to wakeup CPU to carryout ksm activities thus gaining on battery while compromising slightly on memory that could have been saved.) A high ratio of pages_sharing to pages_shared indicates good sharing, but a high ratio of pages_unshared to pages_sharing indicates wasted effort. Loading mm/ksm.c +64 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -1706,6 +1709,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); Loading @@ -1726,6 +1764,10 @@ static int ksm_scan_thread(void *nothing) try_to_freeze(); if (ksmd_should_run()) { 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 { Loading Loading @@ -2275,6 +2317,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) Loading Loading @@ -2387,6 +2449,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 Loading Loading
Documentation/vm/ksm.txt +7 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,13 @@ pages_sharing - how many more sites are sharing them i.e. how much saved pages_unshared - how many pages unique but repeatedly checked for merging pages_volatile - how many pages changing too fast to be placed in a tree full_scans - how many times all mergeable areas have been scanned deferred_timer - whether to use deferred timers or not e.g. "echo 1 > /sys/kernel/mm/ksm/deferred_timer" Default: 0 (means, we are not using deferred timers. Users might want to set deferred_timer option if they donot want ksm thread to wakeup CPU to carryout ksm activities thus gaining on battery while compromising slightly on memory that could have been saved.) A high ratio of pages_sharing to pages_shared indicates good sharing, but a high ratio of pages_unshared to pages_sharing indicates wasted effort. Loading
mm/ksm.c +64 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -1706,6 +1709,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); Loading @@ -1726,6 +1764,10 @@ static int ksm_scan_thread(void *nothing) try_to_freeze(); if (ksmd_should_run()) { 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 { Loading Loading @@ -2275,6 +2317,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) Loading Loading @@ -2387,6 +2449,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 Loading