“나중에 실행”과 “잠들어도 됨”은 같은 말이 아닙니다
| 실행 문맥 | 일반적인 sleep 가능 여부 | 읽을 때 주의할 점 |
|---|---|---|
| hard IRQ handler | 잠들 수 없습니다. | 장치 상태 확인·필요한 acknowledge·후속 처리 예약을 짧게 수행합니다. |
| threaded IRQ handler | thread 문맥이므로 가능한 작업 범위가 넓습니다. | 잡고 있는 lock 등 호출 시점의 제약은 여전히 확인해야 합니다. |
| softirq / tasklet | 일반적으로 잠들 수 없습니다. | ksoftirqd가 처리할 수 있다고 callback을 임의의 sleep 문맥으로 취급하지 않습니다. |
| 일반 threaded workqueue | worker thread에서 실행합니다. | 일반 프로세스 문맥이어도 lock·의존성·종료 순서를 지켜야 합니다. |
| WQ_BH workqueue | softirq 문맥이며 잠들 수 없습니다. | Linux 6.18에서 모든 workqueue가 sleep 가능하다고 쓰면 틀립니다. |
PREEMPT_RT에서는 interrupt 처리와 일부 lock의 성질이 달라집니다. 그 구성의 규칙을 따로 확인해야 합니다. 함수 이름에 “deferred”가 들어갔다는 이유만으로 mutex·blocking I/O를 사용해도 된다고 판단하지 않습니다. threaded workqueue와 WQ_BH PREEMPT_RT의 차이
장치 완료에서 worker까지 상태를 넘깁니다
- 장치
DMA나 다른 작업을 끝내고 상태·interrupt를 제공합니다.
CPU가 interrupt handler에 진입합니다.
- handler
자기 장치의 원인인지 확인하고 장치 규약에 맞춰 처리합니다.
필요한 상태를 기록하고 후속 작업을 queue합니다.
- worker
공유 상태를 동기화 규칙에 맞춰 읽어 시간이 더 드는 작업을 합니다.
소비자에게 완료·데이터를 알립니다.
- 소비자
조건·반환값을 확인하고 결과를 사용합니다.
화살표는 알림과 작업 전달입니다. IRQ 발생 횟수, queue_work 호출 횟수, worker 실행 횟수가 항상 일대일이라는 뜻은 아닙니다.
같은 work item이 이미 pending이면 queue_work가 새 항목 하나를 계속 쌓아 주는 이벤트 저장소처럼 동작하지 않습니다. 이벤트 수를 모두 보존해야 한다면 별도의 queue·counter·상태 구조를 두고 worker가 그것을 처리하도록 설계합니다. queue_work의 반환과 보장
remove 때는 새 작업이 들어오는 경로부터 닫습니다
1. 새 요청 차단
장치가 더 이상 새 전송·interrupt·work를 만들지 않도록 driver의 상태와 하드웨어를 제어합니다. 사용자 요청과도 동기화해야 합니다.
2. 진행 중 처리 정리
IRQ·DMA·timer·work 등 실제 사용한 비동기 경로가 끝났는지 맞는 API로 확인합니다. cancel_work_sync 하나가 다른 모든 생산자를 자동으로 멈추는 것은 아닙니다.
3. 자원 반환
callback이 더 이상 driver의 구조체·MMIO·buffer에 접근하지 않는 상태에서 반환합니다. devm을 쓴 자원도 비동기 접근의 종료 시점은 설계해야 합니다.
단계는 수명 관리의 원칙입니다. 실제 IRQ masking·synchronize·DMA stop·work cancel 순서는 장치와 lock 의존성에 맞춰 정해야 합니다.
worker가 필요로 하는 mutex를 잡은 채 cancel_work_sync로 worker 종료를 기다리면 서로 기다리는 상황을 만들 수 있습니다. “sync”라는 이름은 호출이 무엇과 동기화하는지 읽으라는 표시이지 모든 교착을 피하는 기능이 아닙니다.
문맥이 의심되면 호출 경로를 기록합니다
| 증상 | 살펴볼 관계 |
|---|---|
| sleeping function called from invalid context | hard IRQ·softirq·spinlock 보유 상태에서 잠들 수 있는 API를 호출했는지 확인합니다. |
| 일부 이벤트가 사라집니다. | work item 하나를 이벤트 개수 저장소로 잘못 사용했는지 확인합니다. |
| 드라이버 제거 때 멈춥니다. | 종료를 기다리는 쪽의 lock과 callback이 필요로 하는 lock의 순서를 확인합니다. |
| 제거 뒤 use-after-free | 새 work를 queue하는 경로가 살아 있거나 DMA·IRQ가 아직 자원을 사용하는지 확인합니다. |