WFE 명령어 (Wait For Event)
Summary
정의: 프로세서를 저전력 대기 상태로 진입시키는 명령어. 특정 이벤트(Event) 가 발생할 때까지 실행을 중단하고 대기함. 이벤트 발생 시 자동으로 깨어나 다음 명령어부터 실행 재개함.
문법
WFE
특징: 오퍼랜드가 없는 단독 명령어임.
질문에 대한 직접 답변 — “일반적으로 사용 가능한가?”
결론: EL0(일반 사용자 애플리케이션)에서도 실행 가능함. 이전에 다룬 AT(특권 명령어)와는 다르게, WFE는 특권 레벨 제약이 없는 일반 명령어임.
단, 실제 사용 빈도는 매우 제한적: 일반 애플리케이션 코드(예: 단순 로직, 계산, 문자열 처리)에서는 거의 등장하지 않고, 저수준 동기화 프리미티브(스핀락, 뮤텍스)를 직접 구현하는 라이브러리 코드나 커널의 유휴(idle) 루프에서 주로 관찰됨.
동작 원리
대기 해제(wake-up) 조건:
- 이벤트 레지스터(Event Register) 설정 — 다른 코어가
SEV(Send Event) 명령어를 실행한 경우 - 배타적 모니터 클리어 — 이전에 다룬
LDXR로 설정한 배타적 모니터가 다른 코어의 접근으로 클리어된 경우 (자동으로 이벤트 발생) - 인터럽트 발생 — IRQ, FIQ 등 예외 상황
- 디버그 이벤트
중요한 안전장치: WFE는 “이벤트가 절대 안 오면 영원히 멈춘다”는 위험이 없도록 설계됨. 위 조건 중 하나라도 만족하면 즉시 깨어나며, 심지어 아무 이유 없이도 스퓨리어스(spurious)하게 깨어날 수 있음 — 그래서 항상 루프 안에서 조건을 재확인하는 패턴으로 사용해야 함.
WFE와 짝을 이루는 명령어 — SEV (Send Event)
정의: 다른 모든 코어에 이벤트를 broadcast하여 WFE로 대기 중인 코어를 깨우는 명령어.
SEV
전형적 사용 패턴:
코어 A: WFE (대기)
코어 B: 공유 자원 해제 후 → SEV (코어 A 깨움)
코어 A: 이벤트 수신 → 깨어나서 조건 재확인
실전 활용 — 스핀락 최적화 패턴
단순 스핀락의 문제점: 락이 풀리기를 기다리며 무한 루프를 도는 경우, CPU 자원과 전력을 낭비함.
// 비효율적인 순수 스핀락 (전력 낭비)
spin_loop:
ldxr w0, [x1] // 락 상태 로드
cbnz w0, spin_loop // 락이 걸려있으면 계속 반복 (busy-wait)
WFE를 활용한 최적화된 스핀락:
spin_loop:
ldaxr w0, [x1] // 락 상태 로드 (배타적 모니터 설정)
cbz w0, try_lock // 락이 풀려있으면 획득 시도
wfe // 락이 걸려있으면 저전력 대기
b spin_loop // 깨어나면 다시 확인
try_lock:
mov w2, #1
stxr w3, w2, [x1] // 락 획득 시도
cbnz w3, spin_loop // 실패 시 재시도
// 락 획득 성공
핵심 이점: LDXR로 설정된 배타적 모니터는 다른 코어가 해당 주소에 쓰기(락 해제)를 하면 자동으로 클리어되고, 이것이 곧 WFE의 wake-up 이벤트로 작동함. 즉 별도의 SEV 호출 없이도 락 해제 시 자동으로 대기 코어가 깨어남 (배타적 모니터 메커니즘과 이벤트 메커니즘이 연동되어 있음).
커널 유휴(Idle) 루프에서의 활용
용도: 운영체제 커널이 실행할 작업이 없을 때, CPU를 완전히 멈추지 않고 저전력 대기 상태로 전환하여 배터리 소모를 줄이는 데 사용됨.
idle_loop:
wfe // 인터럽트나 이벤트가 올 때까지 저전력 대기
// 인터럽트 처리 후 여기로 복귀
b idle_loop
macOS/iOS 맥락: XNU 커널의 유휴 루프, 또는 Grand Central Dispatch(GCD)의 저수준 스레드 대기 구현 등에서 이런 패턴이 활용될 수 있음 (다만 실제 커널 소스 세부사항은 공개 범위가 제한적임).
WFE vs WFI — 유사 명령어 비교
| 명령어 | 정식 명칭 | 깨우는 조건 |
|---|---|---|
WFE |
Wait For Event | 이벤트(SEV, 배타적 모니터 클리어, 인터럽트 등) |
WFI |
Wait For Interrupt | 인터럽트만 (더 제한적) |
차이: WFE는 이벤트 메커니즘(소프트웨어적으로 SEV로도 트리거 가능)까지 포함하는 더 넓은 대기 조건을 가지며, WFI는 순수하게 하드웨어 인터럽트만을 기다림. 스핀락 같은 코어 간 소프트웨어 동기화에는 WFE가, 단순 유휴 대기에는 WFI가 더 적합한 경우가 많음.
결론적 정리
| 항목 | 내용 |
|---|---|
| 특권 레벨 | EL0(일반)에서도 실행 가능 |
| 일반 앱에서 관찰 빈도 | 낮음 (직접 작성하는 경우 드묾) |
| 실제 등장 맥락 | 스핀락 구현, 저수준 동기화 라이브러리, 커널 유휴 루프 |
| 짝 명령어 | SEV (이벤트 발생시켜 깨움) |
| 관련 명령어 | WFI(인터럽트 전용 대기) |
최종 판단: 문법적으로는 “일반적으로 사용 가능”하지만, 실질적으로는 락-프리 동기화 프리미티브나 시스템 저수준 코드를 직접 작성하는 경우가 아니라면 애플리케이션 개발자가 직접 손으로 작성할 일은 거의 없는 명령어임. 다만 pthread_mutex, os_unfair_lock 같은 macOS 동기화 API의 내부 구현을 리버싱하다 보면 마주칠 가능성이 있는 명령어임.