Message ID | 1261500191-9441-5-git-send-email-sakari.ailus@maxwell.research.nokia.com (mailing list archive) |
---|---|
State | RFC, archived |
Headers |
Return-path: <linux-media-owner@vger.kernel.org> Envelope-to: mchehab@infradead.org Delivery-date: Tue, 22 Dec 2009 16:45:09 +0000 Received: from bombadil.infradead.org [18.85.46.34] by gaivota.chehab.org with IMAP (fetchmail-6.3.11) for <mchehab@localhost> (single-drop); Tue, 22 Dec 2009 14:48:08 -0200 (BRST) Received: from vger.kernel.org ([209.132.180.67]) by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux)) id 1NN7rB-0004Qc-5h; Tue, 22 Dec 2009 16:45:09 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754106AbZLVQoB (ORCPT <rfc822; kmpark@infradead.org> + 1 other); Tue, 22 Dec 2009 11:44:01 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1754112AbZLVQoA (ORCPT <rfc822;linux-media-outgoing>); Tue, 22 Dec 2009 11:44:00 -0500 Received: from smtp.nokia.com ([192.100.122.233]:49210 "EHLO mgw-mx06.nokia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754108AbZLVQnn (ORCPT <rfc822;linux-media@vger.kernel.org>); Tue, 22 Dec 2009 11:43:43 -0500 Received: from vaebh105.NOE.Nokia.com (vaebh105.europe.nokia.com [10.160.244.31]) by mgw-mx06.nokia.com (Switch-3.3.3/Switch-3.3.3) with ESMTP id nBMGhJfZ006135; Tue, 22 Dec 2009 18:43:40 +0200 Received: from esebh102.NOE.Nokia.com ([172.21.138.183]) by vaebh105.NOE.Nokia.com with Microsoft SMTPSVC(6.0.3790.3959); Tue, 22 Dec 2009 18:43:17 +0200 Received: from mgw-da02.ext.nokia.com ([147.243.128.26]) by esebh102.NOE.Nokia.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.3959); Tue, 22 Dec 2009 18:43:17 +0200 Received: from maxwell.research.nokia.com (maxwell.research.nokia.com [172.21.50.162]) by mgw-da02.ext.nokia.com (Switch-3.3.3/Switch-3.3.3) with ESMTP id nBMGhEBL024390; Tue, 22 Dec 2009 18:43:14 +0200 Received: from lanttu (lanttu.localdomain [192.168.239.4]) by maxwell.research.nokia.com (Postfix) with ESMTPS id 7299E7010E; Tue, 22 Dec 2009 18:43:12 +0200 (EET) Received: from sakke by lanttu with local (Exim 4.69) (envelope-from <sakari.ailus@maxwell.research.nokia.com>) id 1NN7pI-0002Sx-27; Tue, 22 Dec 2009 18:43:12 +0200 From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> To: linux-media@vger.kernel.org Cc: laurent.pinchart@ideasonboard.com, iivanov@mm-sol.com, hverkuil@xs4all.nl, gururaj.nagendra@intel.com Subject: [RFC v2 5/7] V4L: Events: Limit event queue length Date: Tue, 22 Dec 2009 18:43:09 +0200 Message-Id: <1261500191-9441-5-git-send-email-sakari.ailus@maxwell.research.nokia.com> X-Mailer: git-send-email 1.5.6.5 In-Reply-To: <1261500191-9441-4-git-send-email-sakari.ailus@maxwell.research.nokia.com> References: <4B30F713.8070004@maxwell.research.nokia.com> <1261500191-9441-1-git-send-email-sakari.ailus@maxwell.research.nokia.com> <1261500191-9441-2-git-send-email-sakari.ailus@maxwell.research.nokia.com> <1261500191-9441-3-git-send-email-sakari.ailus@maxwell.research.nokia.com> <1261500191-9441-4-git-send-email-sakari.ailus@maxwell.research.nokia.com> X-OriginalArrivalTime: 22 Dec 2009 16:43:17.0596 (UTC) FILETIME=[DCDCB1C0:01CA8325] X-Nokia-AV: Clean Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: <linux-media.vger.kernel.org> X-Mailing-List: linux-media@vger.kernel.org |
Commit Message
Sakari Ailus
Dec. 22, 2009, 4:43 p.m. UTC
Limit event queue length to V4L2_MAX_EVENTS. If the queue is full any
further events will be dropped.
This patch also updates the count field properly, setting it to exactly to
number of further available events.
Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
---
drivers/media/video/v4l2-event.c | 10 +++++++++-
include/media/v4l2-event.h | 5 +++++
2 files changed, 14 insertions(+), 1 deletions(-)
Comments
Hi Sakari, More comments: On Tue, 22 Dec 2009, Sakari Ailus wrote: > Limit event queue length to V4L2_MAX_EVENTS. If the queue is full any > further events will be dropped. > > This patch also updates the count field properly, setting it to exactly to > number of further available events. > > Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> > --- > drivers/media/video/v4l2-event.c | 10 +++++++++- > include/media/v4l2-event.h | 5 +++++ > 2 files changed, 14 insertions(+), 1 deletions(-) > > diff --git a/drivers/media/video/v4l2-event.c b/drivers/media/video/v4l2-event.c > index 9fc0c81..72fdf7f 100644 > --- a/drivers/media/video/v4l2-event.c > +++ b/drivers/media/video/v4l2-event.c > @@ -56,6 +56,8 @@ void v4l2_event_init_fh(struct v4l2_fh *fh) > > INIT_LIST_HEAD(&events->available); > INIT_LIST_HEAD(&events->subscribed); > + > + atomic_set(&events->navailable, 0); > } > EXPORT_SYMBOL_GPL(v4l2_event_init_fh); > > @@ -103,7 +105,8 @@ int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event) > ev = list_first_entry(&events->available, struct _v4l2_event, list); > list_del(&ev->list); > > - ev->event.count = !list_empty(&events->available); > + atomic_dec(&events->navailable); > + ev->event.count = atomic_read(&events->navailable); Combine these two lines to atomic_dec_return(). > > spin_unlock_irqrestore(&events->lock, flags); > > @@ -159,6 +162,9 @@ void v4l2_event_queue(struct video_device *vdev, struct v4l2_event *ev) > if (!v4l2_event_subscribed(fh, ev->type)) > continue; > > + if (atomic_read(&fh->events.navailable) >= V4L2_MAX_EVENTS) > + continue; > + > _ev = kmem_cache_alloc(event_kmem, GFP_ATOMIC); > if (!_ev) > continue; > @@ -169,6 +175,8 @@ void v4l2_event_queue(struct video_device *vdev, struct v4l2_event *ev) > list_add_tail(&_ev->list, &fh->events.available); > spin_unlock(&fh->events.lock); > > + atomic_inc(&fh->events.navailable); > + > wake_up_all(&fh->events.wait); > } > > diff --git a/include/media/v4l2-event.h b/include/media/v4l2-event.h > index b11de92..69305c6 100644 > --- a/include/media/v4l2-event.h > +++ b/include/media/v4l2-event.h > @@ -28,6 +28,10 @@ > #include <linux/types.h> > #include <linux/videodev2.h> > > +#include <asm/atomic.h> > + > +#define V4L2_MAX_EVENTS 1024 /* Ought to be enough for everyone. */ I think this should be programmable by the driver. Most drivers do not use events at all, so by default it should be 0 or perhaps it can check whether the ioctl callback structure contains the event ioctls and set it to 0 or some initial default value. And you want this to be controlled on a per-filehandle basis even. If I look at ivtv, then most of the device nodes will not have events, only a few will support events. And for one device node type I know that there will only be a single event when stopping the streaming, while another device node type will get an event each frame. So being able to adjust the event queue dynamically will give more control and prevent unnecessary waste of memory resources. Regards, Hans > + > struct v4l2_fh; > struct video_device; > > @@ -39,6 +43,7 @@ struct _v4l2_event { > struct v4l2_events { > spinlock_t lock; /* Protect everything here. */ > struct list_head available; > + atomic_t navailable; > wait_queue_head_t wait; > struct list_head subscribed; /* Subscribed events. */ > }; > -- > 1.5.6.5 > -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Hans, On Monday 18 January 2010 13:58:09 Hans Verkuil wrote: > On Tue, 22 Dec 2009, Sakari Ailus wrote: > > Limit event queue length to V4L2_MAX_EVENTS. If the queue is full any > > further events will be dropped. > > > > This patch also updates the count field properly, setting it to exactly > > to number of further available events. > > > > Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> > > --- > > drivers/media/video/v4l2-event.c | 10 +++++++++- > > include/media/v4l2-event.h | 5 +++++ > > 2 files changed, 14 insertions(+), 1 deletions(-) [snip] > > diff --git a/include/media/v4l2-event.h b/include/media/v4l2-event.h > > index b11de92..69305c6 100644 > > --- a/include/media/v4l2-event.h > > +++ b/include/media/v4l2-event.h > > @@ -28,6 +28,10 @@ > > #include <linux/types.h> > > #include <linux/videodev2.h> > > > > +#include <asm/atomic.h> > > + > > +#define V4L2_MAX_EVENTS 1024 /* Ought to be enough for everyone. */ > > I think this should be programmable by the driver. Most drivers do not use > events at all, so by default it should be 0 or perhaps it can check whether > the ioctl callback structure contains the event ioctls and set it to 0 or > some initial default value. > > And you want this to be controlled on a per-filehandle basis even. If I > look at ivtv, then most of the device nodes will not have events, only a > few will support events. And for one device node type I know that there > will only be a single event when stopping the streaming, while another > device node type will get an event each frame. Don't you mean per video node instead of per file handle ? In that case we could add a new field to video_device structure that must be initialized by drivers before registering the device. > So being able to adjust the event queue dynamically will give more control > and prevent unnecessary waste of memory resources.
> Hi Hans, > > On Monday 18 January 2010 13:58:09 Hans Verkuil wrote: >> On Tue, 22 Dec 2009, Sakari Ailus wrote: >> > Limit event queue length to V4L2_MAX_EVENTS. If the queue is full any >> > further events will be dropped. >> > >> > This patch also updates the count field properly, setting it to >> exactly >> > to number of further available events. >> > >> > Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> >> > --- >> > drivers/media/video/v4l2-event.c | 10 +++++++++- >> > include/media/v4l2-event.h | 5 +++++ >> > 2 files changed, 14 insertions(+), 1 deletions(-) > > [snip] > >> > diff --git a/include/media/v4l2-event.h b/include/media/v4l2-event.h >> > index b11de92..69305c6 100644 >> > --- a/include/media/v4l2-event.h >> > +++ b/include/media/v4l2-event.h >> > @@ -28,6 +28,10 @@ >> > #include <linux/types.h> >> > #include <linux/videodev2.h> >> > >> > +#include <asm/atomic.h> >> > + >> > +#define V4L2_MAX_EVENTS 1024 /* Ought to be enough for everyone. */ >> >> I think this should be programmable by the driver. Most drivers do not >> use >> events at all, so by default it should be 0 or perhaps it can check >> whether >> the ioctl callback structure contains the event ioctls and set it to 0 >> or >> some initial default value. >> >> And you want this to be controlled on a per-filehandle basis even. If I >> look at ivtv, then most of the device nodes will not have events, only >> a >> few will support events. And for one device node type I know that there >> will only be a single event when stopping the streaming, while another >> device node type will get an event each frame. > > Don't you mean per video node instead of per file handle ? In that case we > could add a new field to video_device structure that must be initialized > by > drivers before registering the device. Yes, that's what I meant (although you state it much more clearly :-) ). Regards, Hans >> So being able to adjust the event queue dynamically will give more >> control >> and prevent unnecessary waste of memory resources. > > -- > Regards, > > Laurent Pinchart >
Hans Verkuil wrote: > Hi Sakari, Hi Hans, And thanks for the comments! ... >> @@ -103,7 +105,8 @@ int v4l2_event_dequeue(struct v4l2_fh *fh, struct >> v4l2_event *event) >> ev = list_first_entry(&events->available, struct _v4l2_event, list); >> list_del(&ev->list); >> >> - ev->event.count = !list_empty(&events->available); >> + atomic_dec(&events->navailable); >> + ev->event.count = atomic_read(&events->navailable); > > Combine these two lines to atomic_dec_return(). Will fix this. >> >> spin_unlock_irqrestore(&events->lock, flags); >> >> @@ -159,6 +162,9 @@ void v4l2_event_queue(struct video_device *vdev, >> struct v4l2_event *ev) >> if (!v4l2_event_subscribed(fh, ev->type)) >> continue; >> >> + if (atomic_read(&fh->events.navailable) >= V4L2_MAX_EVENTS) >> + continue; >> + >> _ev = kmem_cache_alloc(event_kmem, GFP_ATOMIC); >> if (!_ev) >> continue; >> @@ -169,6 +175,8 @@ void v4l2_event_queue(struct video_device *vdev, >> struct v4l2_event *ev) >> list_add_tail(&_ev->list, &fh->events.available); >> spin_unlock(&fh->events.lock); >> >> + atomic_inc(&fh->events.navailable); >> + >> wake_up_all(&fh->events.wait); >> } >> >> diff --git a/include/media/v4l2-event.h b/include/media/v4l2-event.h >> index b11de92..69305c6 100644 >> --- a/include/media/v4l2-event.h >> +++ b/include/media/v4l2-event.h >> @@ -28,6 +28,10 @@ >> #include <linux/types.h> >> #include <linux/videodev2.h> >> >> +#include <asm/atomic.h> >> + >> +#define V4L2_MAX_EVENTS 1024 /* Ought to be enough for >> everyone. */ > > I think this should be programmable by the driver. Most drivers do not use > events at all, so by default it should be 0 or perhaps it can check whether > the ioctl callback structure contains the event ioctls and set it to 0 or > some initial default value. Right. I'll make the event queue size to be defined by the driver. I'm now planning to make a queue for free events common to file handles in video device. A statically allocated queue for each file handle is probably too much overkill. But a device global queue also means that a process that doesn't dequeue its events will starve the others. > And you want this to be controlled on a per-filehandle basis even. If I > look > at ivtv, then most of the device nodes will not have events, only a few > will > support events. And for one device node type I know that there will only be > a single event when stopping the streaming, while another device node type > will get an event each frame. Instead of initialising the events by the V4L2, the driver could do this and specify the queue size at the same time. The overhead for the drivers not using events would be the event information in the video_device structure. That could be made a pointer as well. > So being able to adjust the event queue dynamically will give more control > and prevent unnecessary waste of memory resources. This sounds to me like trying to re-invent the kmem_cache now. :-) If the event queue is allocated in some other means than kmem_cache I think the size should be fixed. The driver probably knows the best what's the reasonable maximum event queue size and that could be allocated statically. If that overflows then so be it. Regards,
diff --git a/drivers/media/video/v4l2-event.c b/drivers/media/video/v4l2-event.c index 9fc0c81..72fdf7f 100644 --- a/drivers/media/video/v4l2-event.c +++ b/drivers/media/video/v4l2-event.c @@ -56,6 +56,8 @@ void v4l2_event_init_fh(struct v4l2_fh *fh) INIT_LIST_HEAD(&events->available); INIT_LIST_HEAD(&events->subscribed); + + atomic_set(&events->navailable, 0); } EXPORT_SYMBOL_GPL(v4l2_event_init_fh); @@ -103,7 +105,8 @@ int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event) ev = list_first_entry(&events->available, struct _v4l2_event, list); list_del(&ev->list); - ev->event.count = !list_empty(&events->available); + atomic_dec(&events->navailable); + ev->event.count = atomic_read(&events->navailable); spin_unlock_irqrestore(&events->lock, flags); @@ -159,6 +162,9 @@ void v4l2_event_queue(struct video_device *vdev, struct v4l2_event *ev) if (!v4l2_event_subscribed(fh, ev->type)) continue; + if (atomic_read(&fh->events.navailable) >= V4L2_MAX_EVENTS) + continue; + _ev = kmem_cache_alloc(event_kmem, GFP_ATOMIC); if (!_ev) continue; @@ -169,6 +175,8 @@ void v4l2_event_queue(struct video_device *vdev, struct v4l2_event *ev) list_add_tail(&_ev->list, &fh->events.available); spin_unlock(&fh->events.lock); + atomic_inc(&fh->events.navailable); + wake_up_all(&fh->events.wait); } diff --git a/include/media/v4l2-event.h b/include/media/v4l2-event.h index b11de92..69305c6 100644 --- a/include/media/v4l2-event.h +++ b/include/media/v4l2-event.h @@ -28,6 +28,10 @@ #include <linux/types.h> #include <linux/videodev2.h> +#include <asm/atomic.h> + +#define V4L2_MAX_EVENTS 1024 /* Ought to be enough for everyone. */ + struct v4l2_fh; struct video_device; @@ -39,6 +43,7 @@ struct _v4l2_event { struct v4l2_events { spinlock_t lock; /* Protect everything here. */ struct list_head available; + atomic_t navailable; wait_queue_head_t wait; struct list_head subscribed; /* Subscribed events. */ };