freezable_schedule 의 역할이 무엇인가요?

CVE 2015.02.23 08:31 조회 수 : 2741

freezable 또는 freezer 등의 단어가 많이 보이는데 이게 무엇을 의미하는지 모르겠네요...

 

좀 더 구체적인 질문은 이렇습니다.

 

futex_wait_requeue_pi 의 소스코드를 보고 있는데, 이 함수가 uaddr1 -> uaddr2 로 requeue

되기 전까지 계속 wait 상태에 들어가는데 그 코드가

 

static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
2546                                  u32 val, ktime_t *abs_time, u32 bitset,
2547                                  u32 __user *uaddr2)
2548 {
2549         struct hrtimer_sleeper timeout, *to = NULL;
2550         struct rt_mutex_waiter rt_waiter;
2551         struct rt_mutex *pi_mutex = NULL;
2552         struct futex_hash_bucket *hb;
2553         union futex_key key2 = FUTEX_KEY_INIT;
2554         struct futex_q q = futex_q_init;
2555         int res, ret;
2556
2557         if (uaddr == uaddr2)
2558                 return -EINVAL;
2559
2560         if (!bitset)
2561                 return -EINVAL;
2562
2563         if (abs_time) {
2564                 to = &timeout;
2565                 hrtimer_init_on_stack(&to->timer, (flags & FLAGS_CLOCKRT) ?
2566                                       CLOCK_REALTIME : CLOCK_MONOTONIC,
2567                                       HRTIMER_MODE_ABS);
2568                 hrtimer_init_sleeper(to, current);
2569                 hrtimer_set_expires_range_ns(&to->timer, *abs_time,
2570                                              current->timer_slack_ns);
2571         }
2572
2573         /*
2574 * The waiter is allocated on our stack, manipulated by the requeue
2575 * code while we sleep on uaddr.
2576 */
2577         debug_rt_mutex_init_waiter(&rt_waiter);
2578         RB_CLEAR_NODE(&rt_waiter.pi_tree_entry);
2579         RB_CLEAR_NODE(&rt_waiter.tree_entry);
2580         rt_waiter.task = NULL;
2581
2582         ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2, VERIFY_WRITE);
2583         if (unlikely(ret != 0))
2584                 goto out;
2585
2586         q.bitset = bitset;
2587         q.rt_waiter = &rt_waiter;
2588         q.requeue_pi_key = &key2;
2589
2590         /*
2591 * Prepare to wait on uaddr. On success, increments q.key (key1) ref
2592 * count.
2593 */
2594         ret = futex_wait_setup(uaddr, val, flags, &q, &hb);
2595         if (ret)
2596                 goto out_key2;
2597
2598         /*
2599 * The check above which compares uaddrs is not sufficient for
2600 * shared futexes. We need to compare the keys:
2601 */
2602         if (match_futex(&q.key, &key2)) {
2603                 queue_unlock(hb);
2604                 ret = -EINVAL;
2605                 goto out_put_keys;
2606         }
2607
2608         /* Queue the futex_q, drop the hb lock, wait for wakeup. */
2609         futex_wait_queue_me(hb, &q, to);

 

저 위의 futex_wait_queue_me 에서 큐에 현재 uaddr1 / uaddr2 에 대한 정보를

넣고 대기로 빠지는 것으로 알고 있습니다.

 

그런데 futex_wait_queue_me 코드를 보면

 

 

2053 static void futex_wait_queue_me(struct futex_hash_bucket *hb, struct futex_q *q,
2054                                 struct hrtimer_sleeper *timeout)
2055 {
2056         /*
2057 * The task state is guaranteed to be set before another task can
2058 * wake it. set_current_state() is implemented using set_mb() and
2059 * queue_me() calls spin_unlock() upon completion, both serializing
2060 * access to the hash list and forcing another memory barrier.
2061 */
2062         set_current_state(TASK_INTERRUPTIBLE);
2063         queue_me(q, hb);
2064
2065         /* Arm the timer */
2066         if (timeout) {
2067                 hrtimer_start_expires(&timeout->timer, HRTIMER_MODE_ABS);
2068                 if (!hrtimer_active(&timeout->timer))
2069                         timeout->task = NULL;
2070         }
2071
2072         /*
2073 * If we have been removed from the hash list, then another task
2074 * has tried to wake us, and we can skip the call to schedule().
2075 */
2076         if (likely(!plist_node_empty(&q->list))) {
2077                 /*
2078 * If the timer has already expired, current will already be
2079 * flagged for rescheduling. Only call schedule if there
2080 * is no timeout, or if it has yet to expire.
2081 */
2082                 if (!timeout || timeout->task)
2083                         freezable_schedule();
2084         }
2085         __set_current_state(TASK_RUNNING);
2086 }

특별히 루프나 그런 건 없고, 그냥 freezable_schedule() 함수를 호출하고 있습니다.

그럼 이 함수 호출 후에, 어떤 특정 신호를 받거나 할 때까지 이 태스크는 계속 대기한다는

의미인데 원래 schedule() 함수는 스케줄링을 한 다음 다른 태스크에서 다시 현재 태스크로

스케줄링할 수도 있으니 계속 대기가 아니라 다음 스케줄링까지만 대기(?) 를 하게 되는걸로 알고 있는데

저 freezable_schedule 함수는 한 번 호출하면 계속 대기를 하는 건가요?

 

아예 스케줄링 큐에서 빠지는 함수인지, 그러면 다시 다른 태스크에서 현재 태스크를 스케줄링 큐에

넣을때까지는 계속 대기하는 원리라서 futex_cmp_requeue_pi (futex_requeue) 에서 특정 uaddr1 / uaddr2 에 대해

대기하고 있는 waiter 가 있으면 그 waiter 의 태스크를 다시 스케줄링 큐에 넣어준다던지 하는 게 있는 건가요?

 

 

저 freezable_schedule 의 코드를 보면, 커널 컴파일시에 CONFIG_FREEZER 라는 옵션이 만약 n 이면

그냥 schedule() 로 치환이 되고(저런 옵션은 본 적이 없지만..) y 인 경우는 아래처럼

 

168 static inline void freezable_schedule(void)
169 {
170         freezer_do_not_count();
171         schedule();
172         freezer_count();
173 }

이렇게 되고, freezer_do_not_count 가 무엇인지 보니

 

106 static inline void freezer_do_not_count(void)
107 {
108         current->flags |= PF_FREEZER_SKIP;
109 }

그냥 현재 태스크(thread_info) 의 flags 에 PF_FREEZER_SKIP 이라는 플래그를

설정해주는데.. 이게 무슨 역할을 하는 플래그인지 모르겠네요..

스케줄러 소스코드에서 이 플래그를 가지고 뭔가 하는거라도 있어야되는데 찾아보니

그것도 없고 그냥 /kernel/hung_task.c 에서만 뭔가 하거나 freezer.h 에만 조금 뭐 있는거같고.. 

 

 

음.. 질문이 좀 말이 어수선하게 되었는데 그냥 freezable_schedule() 이 하는 일이 무엇인지가 궁금합니다..

freezing 이란 말의 의미로 봐서는 말 그대로 태스크를 프리징시킨다 = 스케줄링하지 않는다 정도인거 같긴 한데..

찾아보면 꼭 그런거같지도 않고... 답변 부탁드리겠습니다.

번호 제목 글쓴이 날짜 조회 수
공지 [공지] 프로그래밍 관련 Q&A 게시판 입니다. woos 2016.04.09 22243
457 커널 컴파일 [1] ldy209 2017.04.06 329
456 디바이스 드라이버 모듈에서 작성한 함수를 커널에서 사용하는 방법 [1] 개짖는소리 2017.02.06 27040
455 VMA의 flag에 관해서 미다리로23 2017.02.09 402
454 카메라 잘하시는 분 부탁드립니다. 김영일 2017.02.02 466
453 llvm 관련하여 질문드립니다. [4] June 2016.09.29 1004
452 linux에서 gpio 초기화에 대한 질문입니다. [2] k40007 2016.10.01 1280
451 Android Application 구동에 관한 조언 부탁드립니다. [1] June 2016.09.21 236
450 사운드 관련하여 질문입니다. qtopia 2016.09.22 134
449 커널의 물리적 주소안에 값을 읽고 싶은데 읽어 오지 않습니다 ㅠ 많은 조언 부탁드립니다 [13] 송창인 2010.12.23 12116
448 access_ok 질문 있습니다. qtopia 2016.07.20 513
447 쓰레드 execution time 질문입니다. [3] 쎈쓰쟁2 2016.03.29 560
446 include/asm-generic/topology.h macro 질문드립니다. [2] k40007 2015.09.29 859
445 Arm 어셈블리어 질문입니다. [2] 이루카 2015.09.25 2310
444 raw_spinlock 질문있습니다. tooson 2015.08.28 903
443 어셈블리어 section에 대해 궁금한 것이 있습니다. [1] 해비 2015.08.12 1812
442 2440 보드의 address 신호와 소스상의 주소를 어떻게 이해 하고 있으면 될까요? 변화의물결 2015.07.28 866
441 안녕하세요 ^^ 임베디드 os 관련 질문이 있습니다 배우고싶어요 2015.07.17 1992
440 Linux Kernel Suspend와 같은 상황 질문드립니다. [1] June 2015.04.07 1164
» freezable_schedule 의 역할이 무엇인가요? [2] CVE 2015.02.23 2741
XE Login