| 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
 |