Fix poll, thanks to the simple test program.
[~madcoder/pwqr.git] / kernel / pwqr.c
index 8248482..233bd7a 100644 (file)
@@ -115,6 +115,7 @@ struct pwqr_sb {
        unsigned                overcommit_wakes;
 
        int                     state;
+       unsigned                has_pollin;
 };
 
 struct pwqr_task {
@@ -194,6 +195,7 @@ static void pwqr_sb_timer_cb(unsigned long arg)
        if (sb->running > sb->concurrency) {
                printk(KERN_DEBUG "wake up poll");
                wake_up_poll(&sb->wqh_poll, POLLIN);
+               sb->has_pollin = 1;
        }
        pwqr_sb_unlock_irqrestore(sb, flags);
 }
@@ -208,6 +210,7 @@ static struct pwqr_sb *pwqr_sb_create(void)
 
        kref_init(&sb->kref);
        init_waitqueue_head(&sb->wqh);
+       init_waitqueue_head(&sb->wqh_poll);
        sb->concurrency    = num_online_cpus();
        init_timer(&sb->timer);
        sb->timer.function = pwqr_sb_timer_cb;
@@ -466,7 +469,7 @@ static unsigned int pwqr_poll(struct file *filp, poll_table *wait)
        poll_wait(filp, &sb->wqh_poll, wait);
 
        pwqr_sb_lock_irqsave(sb, flags);
-       if (sb->running > sb->concurrency)
+       if (sb->has_pollin)
                events |= POLLIN;
        if (sb->state < 0)
                events |= POLLHUP;
@@ -502,8 +505,10 @@ static inline ssize_t pwqr_sb_read(struct pwqr_sb *sb, int no_wait, u32 *cnt)
                remove_wait_queue(&sb->wqh_poll, &wait);
                __set_current_state(TASK_RUNNING);
        }
-       if (likely(rc == 0))
+       if (likely(rc == 0)) {
                *cnt = sb->running - sb->concurrency;
+               sb->has_pollin = 0;
+       }
        spin_unlock_irq(&sb->wqh.lock);
 
        return rc;