@@ -107,6 +107,8 @@ int v4l2_event_init(struct v4l2_fh *fh, unsigned int n)
INIT_LIST_HEAD(&fh->events->available);
INIT_LIST_HEAD(&fh->events->subscribed);
+ atomic_set(&fh->events->navailable, 0);
+
ret = v4l2_event_alloc(fh, n);
if (ret < 0)
v4l2_event_exit(fh);
@@ -128,10 +130,12 @@ int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event)
return -ENOENT;
}
+ BUG_ON(&events->navailable == 0);
+
kev = list_first_entry(&events->available, struct v4l2_kevent, list);
list_del(&kev->list);
- kev->event.count = !list_empty(&events->available);
+ kev->event.count = atomic_dec_return(&events->navailable);
spin_unlock_irqrestore(&fh->lock, flags);
@@ -225,6 +229,8 @@ void v4l2_event_queue(struct video_device *vdev, struct v4l2_event *ev)
list_add_tail(&kev->list, &events->available);
spin_unlock_irqrestore(&fh->lock, flags);
+ atomic_inc(&events->navailable);
+
wake_up_all(&events->wait);
spin_lock_irqsave(&vdev->fhs.lock, flags);
@@ -240,15 +246,7 @@ EXPORT_SYMBOL_GPL(v4l2_event_queue);
int v4l2_event_pending(struct v4l2_fh *fh)
{
- struct v4l2_events *events = fh->events;
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&fh->lock, flags);
- ret = !list_empty(&events->available);
- spin_unlock_irqrestore(&fh->lock, flags);
-
- return ret;
+ return atomic_read(&fh->events->navailable);
}
EXPORT_SYMBOL_GPL(v4l2_event_pending);
@@ -28,6 +28,8 @@
#include <linux/types.h>
#include <linux/videodev2.h>
+#include <asm/atomic.h>
+
struct v4l2_fh;
struct video_device;
@@ -45,6 +47,7 @@ struct v4l2_events {
wait_queue_head_t wait;
struct list_head subscribed; /* Subscribed events */
struct list_head available; /* Dequeueable event */
+ atomic_t navailable;
struct list_head free; /* Events ready for use */
};