mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
ksm: Provide support to use deferred timers for scanner thread
KSM thread to scan pages is getting schedule on definite timeout. That wakes up CPU from idle state and hence may affect the power consumption. Provide an optional support to use deferred timer which suites low-power use-cases. To enable deferred timers, $ echo 1 > /sys/kernel/mm/ksm/deferred_timer Change-Id: I07fe199f97fe1f72f9a9e1b0b757a3ac533719e8 Signed-off-by: Chintan Pandya <cpandya@codeaurora.org>
This commit is contained in:
parent
068766520e
commit
4d97ab65ad
2 changed files with 71 additions and 1 deletions
|
@ -72,6 +72,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.
|
||||
|
|
65
mm/ksm.c
65
mm/ksm.c
|
@ -189,6 +189,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;
|
||||
|
||||
#define KSM_RUN_STOP 0
|
||||
#define KSM_RUN_MERGE 1
|
||||
#define KSM_RUN_UNMERGE 2
|
||||
|
@ -1427,6 +1430,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);
|
||||
|
@ -1446,7 +1484,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,
|
||||
|
@ -1926,6 +1968,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);
|
||||
|
||||
static ssize_t pages_shared_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
|
@ -1980,6 +2042,7 @@ static struct attribute *ksm_attrs[] = {
|
|||
&pages_unshared_attr.attr,
|
||||
&pages_volatile_attr.attr,
|
||||
&full_scans_attr.attr,
|
||||
&deferred_timer_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue