Day 69 - Completion Synchronization¶
Objective¶
Learn the Linux kernel completion synchronization mechanism and understand how it differs from wait queues.
Topics covered:
- struct completion
- init_completion()
- reinit_completion()
- complete()
- complete_all()
- wait_for_completion()
- wait_for_completion_timeout()
- Completion vs Wait Queue
- One-shot synchronization pattern
What I Learned¶
Completion Synchronization¶
Completion is a lightweight synchronization primitive designed for one-shot events.
Unlike wait queues, completion directly represents:
Wait until an operation has finished.
A completion object maintains an internal completion state and allows one or more waiters to block until another execution context signals completion.
Typical kernel usage includes:
- Hardware initialization
- Firmware loading
- DMA transfer completion
- Worker startup synchronization
- Probe and subsystem initialization
Completion Lifecycle¶
Basic workflow:
The waiter blocks until another thread signals completion.
Completion Timeout¶
To prevent indefinite blocking:
can be used.
This is commonly used when waiting for hardware or firmware responses.
If timeout occurs:
- Cleanup is required
- Worker lifetime must still be handled correctly
- Timeout does not imply worker termination
complete() vs complete_all()¶
A single completion object may have multiple waiters.
complete()¶
Wake a single waiter.
complete_all()¶
Wake all waiters.
Completion State Persistence¶
Completion state remains completed after:
Subsequent:
returns immediately.
To reuse a completion object:
must be called.
Completion vs Wait Queue¶
| Feature | Completion | Wait Queue |
|---|---|---|
| One-shot event | Yes | Possible |
| Repeated event | No | Yes |
| Multiple conditions | No | Yes |
| State machine | No | Yes |
| Driver initialization | Excellent | Acceptable |
| Event-driven workflow | Limited | Excellent |
Completion is optimized for:
Wait until a specific operation finishes.
Wait queues are more suitable for:
Wait until a condition becomes true.
Labs Completed¶
Lab 1 - Basic Completion¶
Implemented:
- init_completion()
- wait_for_completion()
- complete()
Verified:
- Worker thread signals completion
- Module initialization resumes after completion
Lab 2 - Completion Timeout¶
Implemented:
- wait_for_completion_timeout()
- kthread_stop()
Verified:
- Timeout handling
- Worker cleanup path
- Safe resource release after timeout
Important observation:
Timeout does not mean the worker has exited.
Worker lifetime must still be synchronized before releasing resources.
Lab 3 - complete() vs complete_all()¶
Implemented:
- Multiple waiter threads
- Single signaler thread
Verified:
complete()¶
Only one waiter wakes up.
complete_all()¶
All waiters wake up simultaneously.
Lab 4 - reinit_completion()¶
Verified:
- Completion state persists after completion
- New waiters immediately return
- reinit_completion() resets completion state
- Completion object becomes reusable
Key Takeaways¶
- Completion is a one-shot synchronization primitive.
- Completion is commonly used for initialization and operation completion.
- Timeout handling must include worker cleanup.
- complete() wakes one waiter.
- complete_all() wakes all waiters.
- reinit_completion() resets completion state.
- Completion is built on top of wait queues internally.
- Completion expresses operation completion, while wait queues express condition waiting.
Next Step¶
Day 70:
- Notifier Chain
- Event notification framework
- Subsystem callback registration
- Notification propagation mechanisms