19.5.1. `px4_poll()` 기반의 효율적인 이벤트 대기 로직

19.5.1. px4_poll() 기반의 효율적인 이벤트 대기 로직

어설픈 usleep() 타이머를 C++ 데몬 코드에서 모조리 도려내 버리고 진정한 0.001ms 단위의 하드코어 리얼타임 인터럽트 반응성(Reactivity)을 시스템적으로 확보하기 위해, PX4 커널 코어 아키텍처는 유닉스(Unix)의 유서 깊은 하단 시스템 콜인 poll() 기능을 픽스호크 NuttX RTOS 환경에 맞게 완벽히 이식 추상화한 px4_poll() 매크로 API를 모듈 해커들에게 제공한다.

이 함수의 핵심 설계 사상은 지극히 폭력적이면서도 우아하다. “스레드를 멍청하게 빙글빙글 돌리지 말고 능동적인 가사 상태로 기절시켜라. 오직 절대적 물리 조건이 맞을 때만 스케줄러가 뺨을 때려 깨워줄 것이다.”
이 강력한 비동기 스케줄링 통제권을 손에 넣음으로써 당신의 퍼블리셔/구독자 모듈 데몬은 무가치한 공회전 CPU 낭비를 0%로 완벽하게 수렴시키면서도, 정작 링 버퍼에 신선한 데이터가 딱 한 방울 떨어지는 찰나의 마이크로초(us) 순간에 즉각 메모리 연산을 재개할 수 있는 짐승 같은 반응 속도의 포식자로 군림하게 된다.

1. 코어 스레드 블로킹(Blocking)과 멀티 인터럽트 기상(Wake-up)의 예술

px4_poll() 함수는 백그라운드 데몬의 무한 루프(while) 블록 한가운데에 뚫을 수 없는 거대한 콘크리트 바리케이드처럼 세워진다.
스레드가 미친 듯이 루프를 돌다 이 함수 라인을 만나는 순간, C++ 런타임 코드는 더 이상 밑으로 흘러 내려가지 못하고 그 자리에 멈춰 선 채(Blocking Mode), 실행 권한을 커널에게 헌납하고 대기 상태 수면 큐(Wait Queue)의 깊은 심연으로 물리적으로 빠지게 된다.

이 완전한 기절 상태에서 당신의 스레드를 다시 살려 깨울 수 있는 생명선 조건은 전 우주에 오직 두 가지뿐이다.

  1. 데이터 도달 (POLLIN 하드웨어 인터럽트): 스레드가 감시하고 있던 건너편 퍼블리셔의 VFS 링 버퍼에 새로운 텔레메트리 페이로드 패킷이 단 1바이트라도 업데이트되어 떨어지는 순간, 커널 OS가 즉각 스케줄링 하드웨어 인터럽트(Signal)를 걸어 잠자던 내 스레드의 멱살을 쥐고 흔들어 가장 폭력적으로 깨워버린다. 이로 인해 usleep 시분할 타임 지연(Latency)이 0에 가까운 즉각적인 초스피드 후속 연산 처리(Control Loop)가 가능해진다.
  2. 타임아웃 (Timeout) 만료 알람: 만일 저 반대편 퍼블리셔 스레드가 죽어버려 픽스호크 파이프라인에 영영 데이터가 들어오지 않으면 내 스레드도 영원히 굶어 죽는 것인가? 이를 절대적으로 방어하기 위해 인스턴스에 강제로 지정해 둔 생명줄 에지 타이머(예: 1000ms 제한)가 카운트를 다 치고 만료되면, 페이로드 여부와 무관하게 시스템 와치독 알람이 울려 스레드가 비상 기상하게 된다. 제어기 모듈은 이 시그널을 바탕으로 “센서가 죽었군! Failsafe 발동!“이라는 치명적 구조 작업을 수행할 수 있다.

이 거대하고 폭력적인 px4_poll() 이벤트 대기 로직을 실제 데몬 코드에 구현하기 위해, 이어지는 하위 단원들에서는 px4_pollfd_struct_t라는 다중 토픽 감시 배열 객체를 힙에 선언하고, 이 바리케이드 함수를 루프 정중앙에 타설한 뒤, 반환되는 상태 숫자를 안전하게 예외 파싱하여 최종 orb_copy 포획으로 연결시키는 픽스호크 전체 스케줄링 배선 작업을 정밀하게 역해부할 것이다.