Use completion. queue
authorThadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
Mon, 24 May 2010 12:51:31 +0000 (08:51 -0400)
committerThadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
Mon, 24 May 2010 12:51:31 +0000 (08:51 -0400)
hellochar.c

index a22677d..a847392 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <linux/circ_buf.h>
+#include <linux/sched.h>
+#include <linux/completion.h>
 
 MODULE_LICENSE("GPL");
 
@@ -34,6 +36,7 @@ static const char default_greeting[] = "Hello, World!\n";
 static struct circ_buf *hello;
 static struct circ_buf hello_instance;
 static DEFINE_MUTEX(hello_mtx);
+static DECLARE_COMPLETION(hello_wait);
 
 static int hello_open(struct inode *ino, struct file *fp)
 {
@@ -63,6 +66,7 @@ static ssize_t hello_read(struct file *fp, char __user *buf, size_t sz,
        mutex_unlock(&hello_mtx);
        if (r)
                return -EFAULT;
+       complete(&hello_wait);
        return sz;
 }
 
@@ -76,6 +80,14 @@ static ssize_t hello_write(struct file *fp, const char __user *buf, size_t sz,
        if (mutex_lock_interruptible(&hello_mtx))
                return -ERESTARTSYS;
        len = CIRC_SPACE(hello->head, hello->tail, MAXLEN);
+       while (len == 0) {
+               mutex_unlock(&hello_mtx);
+               if (wait_for_completion_interruptible(&hello_wait))
+                       return -ERESTARTSYS;
+               if (mutex_lock_interruptible(&hello_mtx))
+                       return -ERESTARTSYS;
+               len = CIRC_SPACE(hello->head, hello->tail, MAXLEN);
+       }
        if (sz > len)
                sz = len;
        fsz = min(sz, CIRC_SPACE_TO_END(hello->head, hello->tail, MAXLEN));