static inline long __sched do_wait_for_common(struct completion *x, long (*action)(long), long timeout, int state) { if (!x->done) { DECLARE_WAITQUEUE(wait, current); __add_wait_queue_tail_exclusive(&x->wait, &wait); do { if (signal_pending_state(state, current)) { timeout = -ERESTARTSYS; break; } __set_current_state(state); spin_unlock_irq(&x->wait.lock); timeout = action(timeout); spin_lock_irq(&x->wait.lock); } while (!x->done && timeout); __remove_wait_queue(&x->wait, &wait); if (!x->done) return timeout; } x->done--; return timeout ?: 1; }
// ARM10C 20170830 // x: &kthreadd_done, action: schedule_timeout, timeout: 0x7FFFFFFF, state: 2 static inline long __sched do_wait_for_common(struct completion *x, long (*action)(long), long timeout, int state) { // x->done: (&kthreadd_done)->done: 0 if (!x->done) { // current: kmem_cache#15-oX (struct task_struct) (pid: 1) DECLARE_WAITQUEUE(wait, current); // DECLARE_WAITQUEUE(wait, kmem_cache#15-oX (struct task_struct) (pid: 1)): // wait_queue_t wait = // { // .private = kmem_cache#15-oX (struct task_struct) (pid: 1), // .func = default_wake_function, // .task_list = { NULL, NULL } // } // &x->wait: &(&kthreadd_done)->wait __add_wait_queue_tail_exclusive(&x->wait, &wait); // __add_wait_queue_tail_exclusive 에서 한일: // (&wait)->flags: ? | 0x01 // &(&(&kthreadd_done)->wait)->task_list 과 (&(&(&kthreadd_done)->wait)->task_list)->prev 사이에 &(&wait)->task_list 를 추가함 // 간단히 말하면 head 인 &(&(&kthreadd_done)->wait)->task_list 의 tail에 &(&wait)->task_list 가 추가됨 // // (&(&(&kthreadd_done)->wait)->task_list)->prev = &(&wait)->task_list; // (&(&wait)->task_list)->next = &(&(&kthreadd_done)->wait)->task_list; // (&(&wait)->task_list)->prev = &(&(&kthreadd_done)->wait)->task_list; // (&(&(&kthreadd_done)->wait)->task_list)->next = &(&wait)->task_list; // 2017/08/30 종료 // 2017/09/06 시작 do { // state: 2, current: kmem_cache#15-oX (struct task_struct) (pid: 1) // signal_pending_state(2, kmem_cache#15-oX (struct task_struct) (pid: 1)): 0 if (signal_pending_state(state, current)) { timeout = -ERESTARTSYS; break; } // state: 2 __set_current_state(state); // __set_current_state 에서 한일: // (kmem_cache#15-oX (struct task_struct) (pid: 1))->state: 2 // &x->wait.lock: &(&kthreadd_done)->wait.lock spin_unlock_irq(&x->wait.lock); // spin_unlock_irq 에서 한일: // &(&kthreadd_done)->wait.lock 을 사용하여 spin unlock 을 수행 // action: schedule_timeout, timeout: 0x7FFFFFFF timeout = action(timeout); spin_lock_irq(&x->wait.lock); } while (!x->done && timeout); __remove_wait_queue(&x->wait, &wait); if (!x->done) return timeout; } x->done--; return timeout ?: 1; }