currentマクロ
currentマクロは、実行プロセスのタスク構造体のアドレスを取得するためのアーキテクチャ依存のマクロで、ここではIA-32といたします。currentはSPレジスターの下位11ビットマスクしたアドレスを返すことで、そのプロセスのタスク構造体を取得することを実現しています。
#define current get_current()
#define get_current() (current_thread_info()->task)
static inline struct thread_info *current_thread_info(void)
{
return (struct thread_info *)
(current_stack_pointer & ~(THREAD_SIZE - 1));
}
static inline unsigned long current_stack_pointer(void)
{
unsigned long sp;
asm("mov sp,%0; ":"=r" (sp));
return sp;
}
これは、プロセス毎に独自のカーネルスタックを有しているから。ということが大前提にあるからです。forkでプロセス作成時、dup_task_structで作成するプロセスのタスク構造体を作成し、同時にalloc_thread_infoで作成したthread_info構造体を作成しています。このアドレスをタスク構造体のstackメンバーに設定しています。
static struct task_struct *dup_task_struct(struct task_struct *orig)
{
struct task_struct *tsk;
struct thread_info *ti;
・・・・・
tsk = alloc_task_struct();
if (!tsk)
return NULL;
・・・・・
ti = alloc_thread_info(tsk);
if (!ti) {
free_task_struct(tsk);
return NULL;
}
・・・・・
tsk->stack = ti;
・・・・・
alloc_thread_infoはthread_info構造体を1ページ取得(スタックサイズにより2ページもあり。)します。従って、この先頭アドレスは必ず下位11ビットは0ということです。しかもその先頭には、このthread_infoを使用するtask_struct構造体が設定するようになっています。
struct thread_info {
struct task_struct *task; /* main task structure */
struct exec_domain *exec_domain; /* execution domain */
unsigned long flags; /* low level flags */
__u32 status; /* thread synchronous flags */
__u32 cpu; /* current CPU */
int preempt_count; /* 0 => preemptable,
<0 => BUG */
mm_segment_t addr_limit;
struct restart_block restart_block;
void __user *sysenter_return;
#ifdef CONFIG_X86_32
unsigned long previous_esp; /* ESP of the previous stack in
case of nested (IRQ) stacks
*/
__u8 supervisor_stack[0];
#endif
};
プロセスのスタックポインターに設定しているのは、copy_threadで行っています。ここではtask_pt_regsでthread_info構造体内のアドレスを取得し、それをプロセス構造体のthreadメンバーに設定しているようです。
int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
unsigned long unused,
struct task_struct * p, struct pt_regs * regs)
{
struct pt_regs * childregs;
struct task_struct *tsk;
int err;
childregs = task_pt_regs(p);
*childregs = *regs;
childregs->ax = 0;
childregs->sp = sp;
p->thread.sp = (unsigned long) childregs;
p->thread.sp0 = (unsigned long) (childregs+1);
task_pt_regsマクロを見てみると、プロセス構造体のstackメンバーの先頭アドレスから、KSTK_TOPマクロでその最上位のアドレスを取得し、そこから8引いた値を返しています。スタックは下位に向かって伸びていくものです。これでこのプロセスはカーネルモード時、alloc_thread_infoで確保した、thread_info内の上位部領域から、スタックとして利用可能となるわけです。
#define task_stack_page(tsk) ((tsk)->stack)
define task_pt_regs(task) \
({ \
struct pt_regs *__regs__; \
__regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \
__regs__ - 1; \
})
#define KSTK_TOP(info) \
({ \
unsigned long *__ptr = (unsigned long *)(info); \
(unsigned long)(&__ptr[THREAD_SIZE_LONGS]); \
})
従ってSPポインターは、ページブロックのthread_info内のアドレス範囲で増減するわけで、下位の11ビットをマスクすれば、その先頭アドレス。すなわちプロセス構造体のアドレスが取得できると言う具合のようです。




