Skip to contentSkip to conversation

get/put_cpu in up need not disable preemption

PATCH In review Ravikiran G Thirumalai 2 participants 2 messages Nov 9, 2002

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 get/put_cpu in up need not disable preemption

AFAICS, get_cpu, put_cpu and put_cpu_no_resched need not disable preemption on a uniprocessor. Foll patch removes the disable/enable premeption stuff for the UP case. Tested on a PIII 4 way for both UP and SMP configs. Pls apply.

Thanks,
Kiran

include/linux/smp.h +10 -4
diff -ruN -X dontdiff linux-2.5.46/include/linux/smp.h get_cpu-2.5.46/include/linux/smp.h
@@ -78,6 +78,11 @@
 extern void unregister_cpu_notifier(struct notifier_block *nb);
 
 int cpu_up(unsigned int cpu);
+
+#define get_cpu()		({ preempt_disable(); smp_processor_id(); })
+#define put_cpu()		preempt_enable()
+#define put_cpu_no_resched()	preempt_enable_no_resched()
+
 #else /* !SMP */
 
 /*
@@ -106,10 +111,11 @@
 static inline void unregister_cpu_notifier(struct notifier_block *nb)
 {
 }
-#endif /* !SMP */
 
-#define get_cpu()		({ preempt_disable(); smp_processor_id(); })
-#define put_cpu()		preempt_enable()
-#define put_cpu_no_resched()	preempt_enable_no_resched()
+#define get_cpu()		smp_processor_id()
+#define put_cpu()		do { } while (0)
+#define put_cpu_no_resched()	do { } while (0)
+
+#endif /* !SMP */
 
 #endif /* __LINUX_SMP_H */
#1 lore raw
Quoted 4 lines · Ravikiran G Thirumalai

AFAICS, get_cpu, put_cpu and put_cpu_no_resched need not disable preemption on a uniprocessor. Foll patch removes the disable/enable premeption stuff for the UP case. Tested on a PIII 4 way for both UP and SMP configs. Pls apply.

No, it needs to.

Per-CPU data can alleviate the need for a lock. On SMP, a per-CPU variable does not need a lock since it is impossible for another task to enter the same critical section and access the same variable, from another CPU. On preempt it is fully possible.

For example, this is a critical section, and you do not want two threads on the same CPU concurrently inside:

	extern struct my_struct[NR_CPUS];
	int cpu = get_cpu();

	do_stuff(my_struct[cpu]);
	do_more_stuff(my_struct[cpu]);
	foo = my_struct[cpu].bar;

	put_cpu();

So get_cpu() must disable preemption even on UP. The problem you are thinking of (being preempted and returning on a different CPU) is only a subset of the issues. All processor accesses must be atomic.

Robert Love