18.6.2.2 블로킹(Blocking)된 구독자 스레드의 세마포어 반환 및 RTOS 스케줄러(Scheduler)에 의한 실행 큐(Run Queue) 복귀

18.6.2.2 블로킹(Blocking)된 구독자 스레드의 세마포어 반환 및 RTOS 스케줄러(Scheduler)에 의한 실행 큐(Run Queue) 복귀

퍼블리셔 스레드의 마지막 임무로 호출된 poll_notify()는 잠자고 있던 구독자들을 깨우는 강력한 시스템 이벤트를 발생시킨다. 이 알림(Notification)이 실제로 어떻게 동작하여 멈춰 있던 코드를 다시 흐르게 만드는지 알아보자.

1. 세마포어(Semaphore)의 반환(Post) 메커니즘

18.6.1절에서 구독자 스레드가 poll_wait()를 통해 세마포어 카운트를 감소시키며 수면(Sleep) 상태로 들어갔음을 기억할 것이다.

가상 파일 시스템(VFS) 내부에서 poll_notify(&_pollset, ...) 호출을 접수받은 커널은 즉각적으로 대응한다. 커널은 _pollset 대기열에 등록된 모든 pollfd 구조체를 순회하며, 각 구조체와 연결된 스레드를 강제로 깨우기 위해 그들이 잠들어 있는 세마포어를 향해 반환 연산(sem_post 또는 nxsem_post)을 원자적으로 수행한다.

이는 0이었던 세마포어 카운트를 1 이상으로 끌어올리는 행위이다.

2. RTOS 스케줄러(Scheduler)의 개입과 스레드 기상(Wake-up)

NuttX RTOS 코어 스케줄러는 그 즉시 이 이벤트를 감시하고 있다가 반응한다.

  1. 실행 큐(Run Queue)로의 편입: 카운트가 올라간 세마포어에서 대기 중이던 구독자 스레드는 즉각적으로 ‘대기(Blocked)’ 상태에서 해제되어, 다음 실행을 기다리는 대기열인 ‘실행 준비 완료(Ready-to-run)’ 큐로 물리적 위치를 이동한다.
  2. 우선순위(Priority) 스케줄링 승리: 만약 깨어난 구독자 스레드의 우선순위가 현재 CPU를 점유하고 있는 스레드(우연히 퍼블리셔일 수도 있고, 전혀 다른 낮은 우선순위의 백그라운드 태스크일 수도 있다)보다 높다면, 선점형(Preemptive) 스케줄러 특성상 커널은 무자비하게 현재 스레드를 강제 문맥 교환(Context Switching)시켜 버린다.
  3. 코드 흐름의 재개(Resume): 이제 구독자 스레드가 다시 CPU 제어권을 획득한다. 함수 콜 스택(Call Stack)은 그가 18.6.1절에서 잠들기 직전 호출했었던 px4_poll(...) 시스템 콜 내부에서 멈춰있던 바로 그 지점부터 다시 실행(Resume)된다.

3. px4_poll 탈출과 이벤트 검증

스레드가 다시 깨어난 후 px4_poll() 함수는 드디어 차단(Blocking) 상태를 풀고 유저 공간(User Space)으로 반환(Return)된다.

// 18.6.1.1 예제 코드의 재개(Resume) 시점
int pret = px4_poll(fds, 3, 1000);

// pret > 0 인 상태로 이 줄이 실행됨
if (pret > 0) {
    // 커널이 fds[0].revents (가속도 센서 낚싯대) 변수에 POLLIN 비트를 세팅했음을 확인
    if (fds[0].revents & POLLIN) {
        // 성공적으로 기상! 최신 데이터가 있음을 확신하고 복사를 시작함
        sub_accel.copy(&accel_data);
    }
}

반환되기 직전, 커널은 깨우는 원인이 되었던 디바이스(예: 가속도 노드)에 해당하는 배열 요소(fds[0])의 revents 필드에 방금 터진 이벤트가 POLLIN(읽기 가능)이었음을 알리는 비트를 수동으로 세팅(|= POLLIN)해 준다.

유저 스페이스의 구독자 로직은 이 revents 비트 마스크만 확인하고도 “아하, 방금 나를 깨운 범인이 가속도 퍼블리셔구나!” 하고 직감할 수 있게 된다.

결과적으로, [퍼블리셔의 발행 -> poll_notify() -> 세마포어 Post -> 스케줄러 기상 -> px4_poll() 탈출 -> 구독 및 복사] 로 이어지는 이 숨가쁜 도미노 마이크로초(us) 스케일의 연쇄 작용이 바로 PX4-Autopilot 이벤트 구동 시스템의 심장 박동이다.