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

Commit 86ef5c9a authored by Gautham R Shenoy's avatar Gautham R Shenoy Committed by Ingo Molnar
Browse files

cpu-hotplug: replace lock_cpu_hotplug() with get_online_cpus()



Replace all lock_cpu_hotplug/unlock_cpu_hotplug from the kernel and use
get_online_cpus and put_online_cpus instead as it highlights the
refcount semantics in these operations.

The new API guarantees protection against the cpu-hotplug operation, but
it doesn't guarantee serialized access to any of the local data
structures. Hence the changes needs to be reviewed.

In case of pseries_add_processor/pseries_remove_processor, use
cpu_maps_update_begin()/cpu_maps_update_done() as we're modifying the
cpu_present_map there.

Signed-off-by: default avatarGautham R Shenoy <ego@in.ibm.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent d221938c
Loading
Loading
Loading
Loading
+6 −5
Original line number Original line Diff line number Diff line
@@ -109,12 +109,13 @@ Never use anything other than cpumask_t to represent bitmap of CPUs.
	for_each_cpu_mask(x,mask) - Iterate over some random collection of cpu mask.
	for_each_cpu_mask(x,mask) - Iterate over some random collection of cpu mask.


	#include <linux/cpu.h>
	#include <linux/cpu.h>
	lock_cpu_hotplug() and unlock_cpu_hotplug():
	get_online_cpus() and put_online_cpus():


The above calls are used to inhibit cpu hotplug operations. While holding the
The above calls are used to inhibit cpu hotplug operations. While the
cpucontrol mutex, cpu_online_map will not change. If you merely need to avoid
cpu_hotplug.refcount is non zero, the cpu_online_map will not change.
cpus going away, you could also use preempt_disable() and preempt_enable()
If you merely need to avoid cpus going away, you could also use
for those sections. Just remember the critical section cannot call any
preempt_disable() and preempt_enable() for those sections.
Just remember the critical section cannot call any
function that can sleep or schedule this process away. The preempt_disable()
function that can sleep or schedule this process away. The preempt_disable()
will work as long as stop_machine_run() is used to take a cpu down.
will work as long as stop_machine_run() is used to take a cpu down.


+5 −5
Original line number Original line Diff line number Diff line
@@ -58,13 +58,13 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
	if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask)))
	if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask)))
		return -EFAULT;
		return -EFAULT;


	lock_cpu_hotplug();
	get_online_cpus();
	read_lock(&tasklist_lock);
	read_lock(&tasklist_lock);


	p = find_process_by_pid(pid);
	p = find_process_by_pid(pid);
	if (!p) {
	if (!p) {
		read_unlock(&tasklist_lock);
		read_unlock(&tasklist_lock);
		unlock_cpu_hotplug();
		put_online_cpus();
		return -ESRCH;
		return -ESRCH;
	}
	}


@@ -106,7 +106,7 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,


out_unlock:
out_unlock:
	put_task_struct(p);
	put_task_struct(p);
	unlock_cpu_hotplug();
	put_online_cpus();
	return retval;
	return retval;
}
}


@@ -125,7 +125,7 @@ asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
	if (len < real_len)
	if (len < real_len)
		return -EINVAL;
		return -EINVAL;


	lock_cpu_hotplug();
	get_online_cpus();
	read_lock(&tasklist_lock);
	read_lock(&tasklist_lock);


	retval = -ESRCH;
	retval = -ESRCH;
@@ -140,7 +140,7 @@ asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,


out_unlock:
out_unlock:
	read_unlock(&tasklist_lock);
	read_unlock(&tasklist_lock);
	unlock_cpu_hotplug();
	put_online_cpus();
	if (retval)
	if (retval)
		return retval;
		return retval;
	if (copy_to_user(user_mask_ptr, &mask, real_len))
	if (copy_to_user(user_mask_ptr, &mask, real_len))
+4 −4
Original line number Original line Diff line number Diff line
@@ -153,7 +153,7 @@ static int pseries_add_processor(struct device_node *np)
	for (i = 0; i < nthreads; i++)
	for (i = 0; i < nthreads; i++)
		cpu_set(i, tmp);
		cpu_set(i, tmp);


	lock_cpu_hotplug();
	cpu_maps_update_begin();


	BUG_ON(!cpus_subset(cpu_present_map, cpu_possible_map));
	BUG_ON(!cpus_subset(cpu_present_map, cpu_possible_map));


@@ -190,7 +190,7 @@ static int pseries_add_processor(struct device_node *np)
	}
	}
	err = 0;
	err = 0;
out_unlock:
out_unlock:
	unlock_cpu_hotplug();
	cpu_maps_update_done();
	return err;
	return err;
}
}


@@ -211,7 +211,7 @@ static void pseries_remove_processor(struct device_node *np)


	nthreads = len / sizeof(u32);
	nthreads = len / sizeof(u32);


	lock_cpu_hotplug();
	cpu_maps_update_begin();
	for (i = 0; i < nthreads; i++) {
	for (i = 0; i < nthreads; i++) {
		for_each_present_cpu(cpu) {
		for_each_present_cpu(cpu) {
			if (get_hard_smp_processor_id(cpu) != intserv[i])
			if (get_hard_smp_processor_id(cpu) != intserv[i])
@@ -225,7 +225,7 @@ static void pseries_remove_processor(struct device_node *np)
			printk(KERN_WARNING "Could not find cpu to remove "
			printk(KERN_WARNING "Could not find cpu to remove "
			       "with physical id 0x%x\n", intserv[i]);
			       "with physical id 0x%x\n", intserv[i]);
	}
	}
	unlock_cpu_hotplug();
	cpu_maps_update_done();
}
}


static int pseries_smp_notifier(struct notifier_block *nb,
static int pseries_smp_notifier(struct notifier_block *nb,
+4 −4
Original line number Original line Diff line number Diff line
@@ -382,7 +382,7 @@ static void do_event_scan_all_cpus(long delay)
{
{
	int cpu;
	int cpu;


	lock_cpu_hotplug();
	get_online_cpus();
	cpu = first_cpu(cpu_online_map);
	cpu = first_cpu(cpu_online_map);
	for (;;) {
	for (;;) {
		set_cpus_allowed(current, cpumask_of_cpu(cpu));
		set_cpus_allowed(current, cpumask_of_cpu(cpu));
@@ -390,15 +390,15 @@ static void do_event_scan_all_cpus(long delay)
		set_cpus_allowed(current, CPU_MASK_ALL);
		set_cpus_allowed(current, CPU_MASK_ALL);


		/* Drop hotplug lock, and sleep for the specified delay */
		/* Drop hotplug lock, and sleep for the specified delay */
		unlock_cpu_hotplug();
		put_online_cpus();
		msleep_interruptible(delay);
		msleep_interruptible(delay);
		lock_cpu_hotplug();
		get_online_cpus();


		cpu = next_cpu(cpu, cpu_online_map);
		cpu = next_cpu(cpu, cpu_online_map);
		if (cpu == NR_CPUS)
		if (cpu == NR_CPUS)
			break;
			break;
	}
	}
	unlock_cpu_hotplug();
	put_online_cpus();
}
}


static int rtasd(void *unused)
static int rtasd(void *unused)
+4 −4
Original line number Original line Diff line number Diff line
@@ -349,7 +349,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
	replace = -1;
	replace = -1;


	/* No CPU hotplug when we change MTRR entries */
	/* No CPU hotplug when we change MTRR entries */
	lock_cpu_hotplug();
	get_online_cpus();
	/*  Search for existing MTRR  */
	/*  Search for existing MTRR  */
	mutex_lock(&mtrr_mutex);
	mutex_lock(&mtrr_mutex);
	for (i = 0; i < num_var_ranges; ++i) {
	for (i = 0; i < num_var_ranges; ++i) {
@@ -405,7 +405,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
	error = i;
	error = i;
 out:
 out:
	mutex_unlock(&mtrr_mutex);
	mutex_unlock(&mtrr_mutex);
	unlock_cpu_hotplug();
	put_online_cpus();
	return error;
	return error;
}
}


@@ -495,7 +495,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)


	max = num_var_ranges;
	max = num_var_ranges;
	/* No CPU hotplug when we change MTRR entries */
	/* No CPU hotplug when we change MTRR entries */
	lock_cpu_hotplug();
	get_online_cpus();
	mutex_lock(&mtrr_mutex);
	mutex_lock(&mtrr_mutex);
	if (reg < 0) {
	if (reg < 0) {
		/*  Search for existing MTRR  */
		/*  Search for existing MTRR  */
@@ -536,7 +536,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
	error = reg;
	error = reg;
 out:
 out:
	mutex_unlock(&mtrr_mutex);
	mutex_unlock(&mtrr_mutex);
	unlock_cpu_hotplug();
	put_online_cpus();
	return error;
	return error;
}
}
/**
/**
Loading