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

Commit f8102d8f authored by Olav Haugan's avatar Olav Haugan Committed by Gerrit - the friendly Code Review server
Browse files

core_ctl: Synchronize access to cluster cpu list



Cluster cpu list traversal is not properly protected against removal of
element by a separate thread. Add proper locking to ensure an element
cannot be removed while accessing the list.

In addition ensure we don't end up in a livelock never exiting the loop
due to hotplug continuously moving elements to the end of the list.

Change-Id: I85b232b5c4dbf65bcb1fede97e1894e6ef9b6a94
Signed-off-by: default avatarOlav Haugan <ohaugan@codeaurora.org>
Signed-off-by: default avatarSatya Durga Srinivasu Prabhala <satyap@codeaurora.org>
parent 11bb76e5
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -719,8 +719,18 @@ static void move_cpu_lru(struct cpu_data *cpu_data)
static void try_to_isolate(struct cluster_data *cluster, unsigned int need)
{
	struct cpu_data *c, *tmp;
	unsigned long flags;
	unsigned int num_cpus = cluster->num_cpus;

	/*
	 * Protect against entry being removed (and added at tail) by other
	 * thread (hotplug).
	 */
	spin_lock_irqsave(&state_lock, flags);
	list_for_each_entry_safe(c, tmp, &cluster->lru, sib) {
		if (!num_cpus--)
			break;

		if (!is_active(c))
			continue;
		if (cluster->active_cpus == need)
@@ -729,6 +739,8 @@ static void try_to_isolate(struct cluster_data *cluster, unsigned int need)
		if (c->is_busy)
			continue;

		spin_unlock_irqrestore(&state_lock, flags);

		pr_debug("Trying to isolate CPU%u\n", c->cpu);
		if (!sched_isolate_cpu(c->cpu)) {
			c->isolated_by_us = true;
@@ -738,7 +750,9 @@ static void try_to_isolate(struct cluster_data *cluster, unsigned int need)
			pr_debug("Unable to isolate CPU%u\n", c->cpu);
		}
		cluster->active_cpus = get_active_cpu_count(cluster);
		spin_lock_irqsave(&state_lock, flags);
	}
	spin_unlock_irqrestore(&state_lock, flags);

	/*
	 * If the number of active CPUs is within the limits, then
@@ -747,12 +761,19 @@ static void try_to_isolate(struct cluster_data *cluster, unsigned int need)
	if (cluster->active_cpus <= cluster->max_cpus)
		return;

	num_cpus = cluster->num_cpus;
	spin_lock_irqsave(&state_lock, flags);
	list_for_each_entry_safe(c, tmp, &cluster->lru, sib) {
		if (!num_cpus--)
			break;

		if (!is_active(c))
			continue;
		if (cluster->active_cpus <= cluster->max_cpus)
			break;

		spin_unlock_irqrestore(&state_lock, flags);

		pr_debug("Trying to isolate CPU%u\n", c->cpu);
		if (!sched_isolate_cpu(c->cpu)) {
			c->isolated_by_us = true;
@@ -762,15 +783,28 @@ static void try_to_isolate(struct cluster_data *cluster, unsigned int need)
			pr_debug("Unable to isolate CPU%u\n", c->cpu);
		}
		cluster->active_cpus = get_active_cpu_count(cluster);
		spin_lock_irqsave(&state_lock, flags);
	}
	spin_unlock_irqrestore(&state_lock, flags);

}

static void __try_to_unisolate(struct cluster_data *cluster,
			       unsigned int need, bool force)
{
	struct cpu_data *c, *tmp;
	unsigned long flags;
	unsigned int num_cpus = cluster->num_cpus;

	/*
	 * Protect against entry being removed (and added at tail) by other
	 * thread (hotplug).
	 */
	spin_lock_irqsave(&state_lock, flags);
	list_for_each_entry_safe(c, tmp, &cluster->lru, sib) {
		if (!num_cpus--)
			break;

		if (!c->isolated_by_us)
			continue;
		if ((c->online && !cpu_isolated(c->cpu)) ||
@@ -779,6 +813,8 @@ static void __try_to_unisolate(struct cluster_data *cluster,
		if (cluster->active_cpus == need)
			break;

		spin_unlock_irqrestore(&state_lock, flags);

		pr_debug("Trying to unisolate CPU%u\n", c->cpu);
		if (!sched_unisolate_cpu(c->cpu)) {
			c->isolated_by_us = false;
@@ -787,7 +823,9 @@ static void __try_to_unisolate(struct cluster_data *cluster,
			pr_debug("Unable to unisolate CPU%u\n", c->cpu);
		}
		cluster->active_cpus = get_active_cpu_count(cluster);
		spin_lock_irqsave(&state_lock, flags);
	}
	spin_unlock_irqrestore(&state_lock, flags);
}

static void try_to_unisolate(struct cluster_data *cluster, unsigned int need)