wake_up은 결과 데이터를 대신 저장하지 않습니다
wait queue는 조건이 참이 될 때까지 task가 기다릴 수 있게 합니다. 생산자는 공유 상태를 먼저 바꾸고 적절히 알리며, 소비자는 깨어난 뒤에도 조건을 확인합니다. “깨웠다”는 사실만을 데이터로 삼으면 대기 등록 전후의 경쟁이나 여러 소비자가 있을 때 결과를 잃기 쉽습니다.
- 생산자
동기화 규칙에 맞춰 결과와 준비 상태를 갱신합니다.
wait queue에 상태 변화를 알립니다.
- 기다리는 task
대기 등록과 조건 확인을 API 규칙에 맞춰 수행합니다.
조건이 참이면 데이터를 사용할 단계로 갑니다.
- 결과 소비
lock·메모리 순서·소유권 규칙에 맞춰 데이터를 읽고 처리합니다.
화살표는 상태 공개와 알림의 관계입니다. wake_up 호출 순간 소비자가 즉시 CPU를 얻는다는 뜻은 아닙니다.
volatile만 붙여 이 과정을 동기화할 수는 없습니다. 데이터 경쟁·메모리 순서·다중 소비자 처리는 lock이나 적절한 atomic·barrier 규칙을 포함해 설계해야 합니다. wait_event와 wake_up API
completion은 완료 상태를 보존합니다
1. 객체 초기화
init_completion() 또는 선언 매크로로 완료 객체를 준비합니다. worker와 waiter가 같은 객체를 사용하고 그 객체가 둘보다 오래 살아 있어야 합니다.
2. 작업 시작
worker에게 처리를 요청합니다. waiter가 wait 함수를 호출하기 전에 worker가 끝날 수도 있습니다. 이 순서 자체는 completion에서 잃어버린 알림이 되는 이유가 아닙니다.
3. 완료 기록
worker가 결과를 준비하고 complete()를 호출합니다. completion은 완료 상태를 기록하므로 아직 waiter가 잠들지 않았어도 이후 wait가 이를 소비할 수 있습니다.
4. 대기 종료
wait가 완료를 얻으면 다음 처리로 갑니다. timeout·signal로 돌아온 경우는 실제 작업 완료와 구분하고, 아직 실행 중인 worker가 접근할 객체를 반환하지 않아야 합니다.
단계는 가능한 실행 순서의 한 예입니다. worker와 waiter는 동시에 진행할 수 있고, complete가 wait보다 먼저 오는 경우도 유효합니다.
반환형과 반환값을 정확하게 읽습니다
| API | 반환값의 의미 |
|---|---|
| wait_for_completion() | 반환값이 없습니다. 완료를 기다리는 동안 잠들 수 있습니다. |
| wait_for_completion_timeout() | 0은 timeout, 양수는 완료에 따른 남은 jiffies이며, 완료로 반환할 때에는 최소 1입니다. |
| wait_for_completion_interruptible_timeout() | long을 반환합니다. 0은 timeout, 양수는 완료, 음수는 signal에 따른 중단을 나타냅니다. |
| try_wait_for_completion() | 기다리지 않고 완료 하나를 얻을 수 있는지 시도합니다. 성공하면 완료 하나를 소비하고 true, 얻지 못하면 false를 반환합니다. |
| completion_done() | 완료 상태가 있는지 관찰합니다. “waiter가 없는가”를 조사하는 API가 아니며 관찰 직후 상태가 달라질 수 있습니다. |
interruptible은 하드웨어 interrupt를 모두 끈다는 뜻이 아닙니다. 대기 중 signal에 의해 돌아올 수 있는 task 상태를 말합니다. 함수 반환형을 unsigned로 바꿔 음수 오류를 큰 양수로 읽지 않아야 합니다. 6.18.37 API 선언 완료 처리 구현
timeout은 작업 취소가 아닙니다
ret = wait_for_completion_interruptible_timeout(&job->done, limit);
if (ret <= 0) {
/* 실제 작업을 취소하거나, 종료를 확인하거나, 수명을 연장합니다. */
/* 이 지점에서 무조건 free(job) 하면 안 됩니다. */
}설명용 코드입니다. limit는 jiffies 단위로 준비한 대기 시간이며 ret는 long입니다. 실제 cancel API와 동기화는 작업 종류에 따라 다릅니다. 시간 제한이 지났는데 worker가 뒤늦게 complete(&job->done)를 호출하면, 이미 해제한 job에 접근하는 use-after-free가 될 수 있습니다.
| 재사용할 때 | 필요한 확인 |
|---|---|
| reinit_completion() | 앞선 waiter·complete 호출과 동시에 재초기화하지 않도록 제어해야 합니다. |
| complete_all() 이후 | 다음 작업을 시작하기 전에 이전 작업의 모든 사용자와 완료 상태를 정리해야 합니다. |
| stack에 놓은 completion | 함수가 반환한 뒤 producer가 접근하지 않는다는 보장이 있어야 합니다. |