Completions are a simple synchronization mechanism that is preferable to
sleeping and waking up in some situations. If you have a task that must
simply sleep until some process has run its course, completions can do it
easily and without race conditions. They are not strictly a 2.6 feature,
having been added in 2.4.7, but they merit a quick summary here.
A completion is, essentially, a one-shot flag that says "things may
proceed." Working with completions requires including
<linux/completion.h> and creating a variable of type
struct completion. This structure may be declared and
initialized statically with:
DECLARE_COMPLETION(my_comp);
A dynamic initialization would look like:
struct completion my_comp;
init_completion(&my_comp);
When your driver begins some process whose completion must be waited for,
it's simply a matter of passing your completion event to
wait_for_completion():
void wait_for_completion(struct completion *comp);
When some other part of your code has decided that the completion has
happened, it can wake up anybody who is waiting with one of:
void complete(struct completion *comp);
void complete_all(struct completion *comp);
The first form will wake up exactly one waiting process, while the second
will wake up all processes waiting for that event. Note that completions
are implemented in such a way that they will work properly even if
complete() is called before wait_for_completion().
If you do not use complete_all(), you should be able to use a
completion structure multiple times without problem. It does not hurt,
however, to reinitialize the structure before each use - so long as you do
it before initiating the process that will call complete()! The
macro INIT_COMPLETION() can be used to quickly reinitialize a
completion structure that has been fully initialized at least once. No comments have been posted.
Post one now
|