Arm Linux Kernel Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

81112
549
416221


wake_up_new_task() - 프로세스(Process) 실행(Activate) 4. 프로세스(Process) 관리

프로세스가 새로 생성되면 프로세스를 깨워서 실행시켜야 해요.
wake_up_new_task() 함수가 이 역할을 수행하거든요.

아래 코드를 보면 많은 동작을 하는 것 같지만, 요약하면 아래와 같아요.
1> 생성된 후 처음으로 시작하는 프로세스에 대한 스케쥴러 통계 정보를 설정
2> Runqueue에 새로 생성된 프로세스를 추가해서 생성된 프로세스를 깨움

이제 코드 리뷰를 좀 해볼께요.
[1]: 해당 task_struct에 대한 Runqueue을 가져와요
[2]: Runqueue에 해당 프로세스(struct task_struct *p)를 Queue하고 깨워요.
void wake_up_new_task(struct task_struct *p)
{
unsigned long flags;
struct rq *rq;

raw_spin_lock_irqsave(&p->pi_lock, flags);
/* Initialize new task's runnable average */
init_entity_runnable_average(&p->se);
#ifdef CONFIG_SMP
/*
* Fork balancing, do it here and not earlier because:
*  - cpus_allowed can change in the fork path
*  - any previously selected cpu might disappear through hotplug
*/
set_task_cpu(p, select_task_rq(p, task_cpu(p), SD_BALANCE_FORK, 0));
#endif

rq = __task_rq_lock(p); //<<--[1]
activate_task(rq, p, 0); //<<--[2]
p->on_rq = TASK_ON_RQ_QUEUED;
trace_sched_wakeup_new(p);
check_preempt_curr(rq, p, WF_FORK);
#ifdef CONFIG_SMP
if (p->sched_class->task_woken) {
/*
* Nothing relies on rq->lock after this, so its fine to
* drop it.
*/
lockdep_unpin_lock(&rq->lock);
p->sched_class->task_woken(rq, p);
lockdep_pin_lock(&rq->lock);
}
#endif
task_rq_unlock(rq, p, &flags);
}

wake_up_new_task() 함수는 그럼 어디에서 호출되냐구요?
_do_fork()에서 copy_process() 함수 호출로 프로세스를 생성한 다음에 바로 호출하네요.
long _do_fork(unsigned long clone_flags,
      unsigned long stack_start,
      unsigned long stack_size,
      int __user *parent_tidptr,
      int __user *child_tidptr,
      unsigned long tls)
{
struct task_struct *p;
int trace = 0;
long nr;

if (!(clone_flags & CLONE_UNTRACED)) {
if (clone_flags & CLONE_VFORK)
trace = PTRACE_EVENT_VFORK;
else if ((clone_flags & CSIGNAL) != SIGCHLD)
trace = PTRACE_EVENT_CLONE;
else
trace = PTRACE_EVENT_FORK;

if (likely(!ptrace_event_enabled(current, trace)))
trace = 0;
}

p = copy_process(clone_flags, stack_start, stack_size,
child_tidptr, NULL, trace, tls, NUMA_NO_NODE);
/*
* Do this prior waking up the new thread - the thread pointer
* might get invalid after that point, if the thread exits quickly.
*/
if (!IS_ERR(p)) {
struct completion vfork;
struct pid *pid;

trace_sched_process_fork(current, p);

pid = get_task_pid(p, PIDTYPE_PID);
nr = pid_vnr(pid);

if (clone_flags & CLONE_PARENT_SETTID)
put_user(nr, parent_tidptr);

if (clone_flags & CLONE_VFORK) {
p->vfork_done = &vfork;
init_completion(&vfork);
get_task_struct(p);
}

wake_up_new_task(p);
.


덧글

댓글 입력 영역