Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3d6e8cbc authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ksm: Provide support to use deferred timers for scanner thread"

parents 574aa092 913b3be9
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -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.
+64 −1
Original line number Diff line number Diff line
@@ -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;
@@ -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);
@@ -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 {
@@ -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)
@@ -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