[PATCH RFC 6/6] Implement "current" with the PDA.
From: Jeremy Fitzhardinge
Date: Sun Aug 27 2006 - 05:23:38 EST
Use the pcurrent field in the PDA to implement the "current" macro.
This ends up compiling down to a single instruction to get the current
task.
The slightly tricky part about this patch is that cpu_init() uses
current very early, before the PDA has been set up. In this instance,
it uses current_thread_info()->task to get the current task.
Also, the very early PDA set up for the boot cpu contains the initial
task pointer so current works from a very early stage.
Signed-off-by: Jeremy Fitzhardinge <jeremy@xxxxxxxxxxxxx>
Cc: Chuck Ebbert <76306.1226@xxxxxxxxxxxxxx>
Cc: Zachary Amsden <zach@xxxxxxxxxx>
Cc: Jan Beulich <jbeulich@xxxxxxxxxx>
Cc: Andi Kleen <ak@xxxxxxx>
--
arch/i386/kernel/cpu/common.c | 27 ++++++++++++++++-----------
include/asm-i386/current.h | 11 ++---------
2 files changed, 18 insertions(+), 20 deletions(-)
===================================================================
--- a/include/asm-i386/current.h
+++ b/include/asm-i386/current.h
@@ -1,15 +1,8 @@
#ifndef _I386_CURRENT_H
#define _I386_CURRENT_H
-#include <linux/thread_info.h>
+#include <asm/pda.h>
-struct task_struct;
-
-static __always_inline struct task_struct * get_current(void)
-{
- return current_thread_info()->task;
-}
-
-#define current get_current()
+#define current (read_pda(pcurrent))
#endif /* !(_I386_CURRENT_H) */
===================================================================
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -587,16 +587,16 @@ void __init early_cpu_init(void)
#endif
}
-static __cpuinit void pda_init(int cpu)
+static __cpuinit void pda_init(int cpu, struct task_struct *curr)
{
struct i386_pda *pda = cpu_pda(cpu);
memset(pda, 0, sizeof(*pda));
pda->cpu_number = cpu;
- pda->pcurrent = current;
-
- printk("cpu %d current %p\n", cpu, current);
+ pda->pcurrent = curr;
+
+ printk("cpu %d current %p\n", cpu, curr);
}
struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
@@ -609,7 +609,7 @@ struct pt_regs * __devinit idle_regs(str
/* Set up a very early PDA for the boot CPU so that smp_processor_id will work */
void __init smp_setup_processor_id(void)
{
- static const __initdata struct i386_pda boot_pda;
+ static __initdata struct i386_pda boot_pda;
pack_descriptor((u32 *)&cpu_gdt_table[GDT_ENTRY_PDA].a,
(u32 *)&cpu_gdt_table[GDT_ENTRY_PDA].b,
@@ -618,6 +618,8 @@ void __init smp_setup_processor_id(void)
/* Set %gs for this CPU's PDA */
asm volatile ("mov %0, %%gs" : : "r" (__KERNEL_PDA));
+
+ boot_pda.pcurrent = current_thread_info()->task;
}
/*
@@ -628,9 +630,12 @@ void __init smp_setup_processor_id(void)
*/
void __cpuinit cpu_init(void)
{
- int cpu = current_thread_info()->cpu; /* need to use this until the PDA is set up */
+ /* Need to use thread_info for cpu and current until the PDA is set up */
+ int cpu = current_thread_info()->cpu;
+ struct task_struct *curr = current_thread_info()->task;
+
struct tss_struct * t = &per_cpu(init_tss, cpu);
- struct thread_struct *thread = ¤t->thread;
+ struct thread_struct *thread = &curr->thread;
struct desc_struct *gdt;
struct i386_pda *pda;
__u32 stk16_off = (__u32)&per_cpu(cpu_16bit_stack, cpu);
@@ -702,7 +707,7 @@ old_gdt:
/* Set up the PDA in this CPU's GDT */
cpu_pda(cpu) = pda;
- pda_init(cpu);
+ pda_init(cpu, curr);
pack_descriptor((u32 *)&gdt[GDT_ENTRY_PDA].a,
(u32 *)&gdt[GDT_ENTRY_PDA].b,
@@ -716,10 +721,10 @@ old_gdt:
* Set up and load the per-CPU TSS and LDT
*/
atomic_inc(&init_mm.mm_count);
- current->active_mm = &init_mm;
- if (current->mm)
+ curr->active_mm = &init_mm;
+ if (curr->mm)
BUG();
- enter_lazy_tlb(&init_mm, current);
+ enter_lazy_tlb(&init_mm, curr);
load_esp0(t, thread);
set_tss_desc(cpu,t);
--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/