Completion-Variable#
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
#include <linux/completion.h>
struct completion_dev {
struct cdev cdev;
struct completion completion;
};
struct completion_dev completion_dev;
static int completion_open(struct inode *inode, struct file *filp)
{
filp->private_data =
container_of(inode->i_cdev, struct completion_dev, cdev);
return 0;
}
static ssize_t completion_read(struct file *filp, char __user *buf,
size_t count, loff_t *pos)
{
struct completion_dev *dev = filp->private_data;
pr_debug("process %d(%s) going to sleep\n", current->pid, current->comm);
wait_for_completion(&dev->completion);
pr_debug("awoken %d(%s)\n", current->pid, current->comm);
return 0;
}
static ssize_t completion_write(struct file *filp, const char __user *buf,
size_t count, loff_t *pos)
{
struct completion_dev *dev = filp->private_data;
pr_debug("process %d(%s) awakening the readers...\n", current->pid, current->comm);
complete(&dev->completion);
return count;
}
static const struct file_operations completion_fops = {
.owner = THIS_MODULE,
.open = completion_open,
.read = completion_read,
.write = completion_write,
};
static int __init m_init(void)
{
int ret;
init_completion(&completion_dev.completion);
ret = alloc_chrdev_region(&dev__t, 0, 1, MODULE_NAME);
if (ret) {
pr_debug("Error: %d -Cant't get major\n", ret);
return ret;
}
cdev_init(&completion_dev.cdev, &completion_fops);
ret = cdev_add(&completion_dev.cdev, dev__t, 1);
[...],
}References: