2009-12-04

Linux kernel Competion Events

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:

Post a Comment