Re: [PATCH 2/7] kfifo: move out spinlock

Previous thread: [RFC -tip] x86,apic: set cpu_has_apic manually for discrete apic by Cyrill Gorcunov on Sunday, August 16, 2009 - 12:57 pm. (2 messages)

Next thread: [patch] fs: Make unload_nls() NULL pointer safe by Thomas Gleixner on Sunday, August 16, 2009 - 2:05 pm. (2 messages)
From: Stefani Seibold
Date: Sunday, August 16, 2009 - 1:39 pm

This is a new generic kernel FIFO implementation.

The current kernel fifo API is not very widely used, because it has to many
constrains. Only 13 files in the current 2.6.31-rc5 used it. FIFO's are
like list's a very basic thing and a kfifo API which handles the most use
case would save a lot of development time and memory resources.

I think this are the reasons why kfifo is not in use:

- The API is to simple, important functions are missing
- A fifo can be only allocated dynamically
- There is a need of a spinlock despite you need it or not
- There is no support for data records inside a fifo

So i decided to extend the kfifo in a more generic way without blowing up
the API to much. The new API has the following benefits:

- Generic usage: For kernel internal use and/or device driver.
- Provide an API for the most use case.
- Slim API: The whole API provides 23 functions.
- Linux style habit.
- DECLARE_KFIFO, DEFINE_KFIFO and INIT_KFIFO Macros
- Direct copy_to_user from the fifo and copy_from_user into the fifo.
- The kfifo itself is an in place member of the using data structure, this save an 
  indirection access and does not waste the kernel allocator. 
- Lockless access: if only one reader and one writer is active on the fifo,
  which is the common use case, no additional locking is necessary.
- Remove spinlock - give the user the freedom of choice what kind of locking to use if 
  one is required.
- Ability to handle records. Three type of records are supported:
  - Variable length records between 0-255 bytes, with a record size field of 1 bytes.
  - Variable length records between 0-65535 bytes, with a record size field of 2 bytes.
  - Fixed size records, which no record size field.
- Preserve memory resource.
- Performance!
- Easy to use!

ChangeLog:

v.0 03.08.2009
 First proposal, post a draft
v.1 04.08.2009
 add kfifo_init()
 kfifo_put() and kfifo_get() restored to the original behavior (but without locking)
 introduce new kfifo_put_rec() and ...
From: Stefani Seibold
Date: Sunday, August 16, 2009 - 1:44 pm

Since most users want to have the kfifo as part of another
object, reorganize the code to allow including struct kfifo
in another data structure. This requires changing the kfifo_alloc
and kfifo_init prototypes so that we pass an existing kfifo
pointer into them. This patch changes the implementation and
all existing users.

Signed-off-by: Stefani Seibold <stefani@seibold.net>
---
 drivers/char/nozomi.c                       |   21 ++++-----
 drivers/char/sonypi.c                       |   40 ++++++++---------
 drivers/infiniband/hw/cxgb3/cxio_hal.h      |    9 ++-
 drivers/infiniband/hw/cxgb3/cxio_resource.c |   60 ++++++++++++-------------
 drivers/media/video/meye.c                  |   48 +++++++++-----------
 drivers/media/video/meye.h                  |    4 -
 drivers/net/wireless/libertas/cmd.c         |    4 -
 drivers/net/wireless/libertas/dev.h         |    3 -
 drivers/net/wireless/libertas/main.c        |   16 +++---
 drivers/platform/x86/fujitsu-laptop.c       |   18 +++----
 drivers/platform/x86/sony-laptop.c          |   46 +++++++++----------
 drivers/scsi/libiscsi.c                     |   22 +++------
 drivers/scsi/libiscsi_tcp.c                 |   29 ++++++------
 drivers/scsi/libsrp.c                       |   12 ++---
 drivers/usb/host/fhci-sched.c               |   10 ++--
 drivers/usb/host/fhci-tds.c                 |   35 +++++++--------
 drivers/usb/host/fhci.h                     |   10 ++--
 include/linux/kfifo.h                       |   11 ++--
 include/scsi/libiscsi.h                     |    3 -
 include/scsi/libiscsi_tcp.h                 |    2 
 include/scsi/libsrp.h                       |    2 
 kernel/kfifo.c                              |   65 ++++++++++++++--------------
 net/dccp/probe.c                            |   20 +++-----
 23 files changed, 236 insertions(+), 254 deletions(-)

diff -u -N -r linux-2.6.31-rc4-kfifo0/drivers/char/nozomi.c linux-2.6.31-rc4-kfifo1/drivers/char/nozomi.c
--- ...
From: Stefani Seibold
Date: Sunday, August 16, 2009 - 1:46 pm

Move the pointer to the spinlock out of struct kfifo. Most
users in tree do not actually use a spinlock, so the few
exceptions now have to call kfifo_{get,put}_locked, which takes
an extra argument to a spinlock.

Signed-off-by: Stefani Seibold <stefani@seibold.net>
---
 drivers/char/nozomi.c                       |    2 
 drivers/char/sonypi.c                       |   21 ++++---
 drivers/infiniband/hw/cxgb3/cxio_resource.c |   36 +++++++------
 drivers/media/video/meye.c                  |   35 +++++++-----
 drivers/net/wireless/libertas/main.c        |    2 
 drivers/platform/x86/fujitsu-laptop.c       |   18 +++---
 drivers/platform/x86/sony-laptop.c          |   22 ++++----
 drivers/scsi/libiscsi.c                     |    2 
 drivers/scsi/libiscsi_tcp.c                 |    2 
 drivers/scsi/libsrp.c                       |    9 +--
 drivers/usb/host/fhci.h                     |    2 
 include/linux/kfifo.h                       |   76 ++++++++++++----------------
 kernel/kfifo.c                              |   17 ++----
 net/dccp/probe.c                            |    6 +-
 14 files changed, 126 insertions(+), 124 deletions(-)

diff -u -N -r linux-2.6.31-rc4-kfifo1/drivers/char/nozomi.c linux-2.6.31-rc4-kfifo2/drivers/char/nozomi.c
--- linux-2.6.31-rc4-kfifo1/drivers/char/nozomi.c	2009-08-16 21:25:14.000000000 +0200
+++ linux-2.6.31-rc4-kfifo2/drivers/char/nozomi.c	2009-08-11 12:46:56.000000000 +0200
@@ -685,7 +685,7 @@
 
 		for (i = PORT_MDM; i < MAX_PORT; i++) {
 			kfifo_alloc(&dc->port[i].fifo_ul,
-				FIFO_BUFFER_SIZE_UL, GFP_ATOMIC, NULL);
+				FIFO_BUFFER_SIZE_UL, GFP_ATOMIC);
 			memset(&dc->port[i].ctrl_dl, 0, sizeof(struct ctrl_dl));
 			memset(&dc->port[i].ctrl_ul, 0, sizeof(struct ctrl_ul));
 		}
diff -u -N -r linux-2.6.31-rc4-kfifo1/drivers/char/sonypi.c linux-2.6.31-rc4-kfifo2/drivers/char/sonypi.c
--- linux-2.6.31-rc4-kfifo1/drivers/char/sonypi.c	2009-08-16 21:22:46.000000000 +0200
+++ linux-2.6.31-rc4-kfifo2/drivers/char/sonypi.c	2009-08-11 ...
From: Alan Cox
Date: Sunday, August 16, 2009 - 3:58 pm

On Sun, 16 Aug 2009 22:46:30 +0200

NAK this one for the moment

We are about to set fifo loose through all the USB and some other
char/serial drivers all of which will use the spinlock facility.
--

From: Andrew Morton
Date: Sunday, August 16, 2009 - 4:34 pm

That sounds like a good reason for applying this patch first.

kfifo has no business assuming that the caller wants to use
spin_lock() locking.

If we want to add wrapper helpers around kfifo to reduce code
duplication in callers, and if one of those wrapper helpers provides
spinlock-based locking then fine.

But the happens-to-use-spin_lock functions shouldn't be called
kfifo_get(), because that steals namespace from the unlocked functions,
and makes the naming for the happens-to-use-mutex_lock functions look
weird.

--

From: Alan Cox
Date: Sunday, August 16, 2009 - 11:48 pm

All over the kernel unlocked function versions have a leading _ name.
It's the kernel convention.

The other thing I must say I dislike about these patches is the
gratuitious 'let's rename all the functions' approach it takes. The kfifo
API is documented, used and random API of the year type changes mess
stuff up and cause unneeded churn.

The implementation itself is a really really nice idea.


--

From: Andrew Morton
Date: Monday, August 17, 2009 - 12:36 am

Those names are wrong.

They're wrong because they are the spinlock-specific variant.  What are

tisn't.  radix-tree, rbrtee, idr, list_head, prio_tree, flex_array -

It fixes naming mistakes.  Long-term it is the correct thing to do. 
Best to do it now before we get more callers.

--

From: Alan Cox
Date: Monday, August 17, 2009 - 1:08 am

Some random "10 second grep" examples, and this is also used more
generally for the "without extra goo" variant of things

__set_special_pids
__sysrq_put_key_op
__sysrq_get_key_op
__handle_sysrq
__audit_getname
__audit_inode
__audit_node_child

and the without extra goo use includes such minor classics
__get_user
__put_user

the kernel contains lots and lots of

__foo()

foo()
{
	spin_lock(bar);
	__foo()
	spin_unlock(bar)

Why don't we fix all the really dumb naming mistakes then - things like
the chrdev interfaces ? Massive churn, massive confusion. Patches are
always being rejected (and rightfully so) for causing such messes.

And remember: its very hard to fix existing API documentation and books.
It's doubly dangerous (and IMHO a complete no-no) to change the API of an
interface if you don't change it such that old code will not reliably get
a compile time failure.

Alan
--

From: Stefani Seibold
Date: Monday, August 17, 2009 - 1:14 am

As mention: i have no book which describes this interface.

To get reliably a compile time failure was the reason to change the

Stefani


--

From: Andrew Morton
Date: Monday, August 17, 2009 - 1:21 am

None of those functions are part of general container libraries.  All
the ones I mentioned _are_ part of general container libraries.

Plus, as I've said enty en times and keep getting ignored: the current
naming is wrong.  The generic kfifo_get() should not be assuming that

These patches don't make a mess.  Stefani has already fixed all callers

The patchet will cause unmigrated code to fail to build, won't it?
--

From: Alan Cox
Date: Monday, August 17, 2009 - 1:48 am

I simply pasted randomly from the regexp output. The __ semantic for the
less sanity checking/unlocked/non synchronizing version of an API is all
over the kernel. Not suprisingly as it seems to be a Linusism looking at

Yes but it won't fix the API docs.

So I still disagree with you. Adding _locked to the API end doesn't solve
any problems

You asked about mutexes but is get_locked() mutex locked, semaphore
locked, spinlocked, rwlocked ? So it doesn't do what you say.

What it does do is make the code more verbose, wider, more likely to go
over 80 columns and more typing.

Anyway I've made my point. I still think you are wrong on this one Andrew
but I think we have to simply continue to disagree.
--

From: Stefani Seibold
Date: Monday, August 17, 2009 - 2:22 am

I don't think so, because kfifo_*_locked() is only there for a
simplified porting. New user will not normally not use it.

Stefani

--

From: Stefani Seibold
Date: Monday, August 17, 2009 - 12:46 am

Thats is not true in every case. Have a look at list.h - That was the

First: Non of my eight linux kernel developer books does mention this
API. The only place is the in-kernel documentation and the man pages of
the "kernel hackers manual".

The main reason to do this was to design a cleaner interface. Because
there are very few users of this API, i thought it is a good time and
chance to do this.

My first draft version does also not renamed this functions, but there
was some concerns about the new functionality without modification the
function names.

Also the remove of the spinlock made is necessary to rename the
functions for preventing miss-use by out-of-kernel-tree drivers.

I think the break is not so hard if you believe. All you have to do is
to replace or kfifo_get() into kfifo_out_locked() and kfifo_put() into
kfifo_in_locked() if you really need the old behavior.


Thanks for the flowers ;-)


--

From: Alan Cox
Date: Monday, August 17, 2009 - 1:15 am

Of course it isn't true in every case. Show me a *single* kernel
convention that is. It's also not true in no cases. foo_locked isn't used

So if you didn't remove the spinlock you wouldn't have to change the API

Which is very long winded. If you want longwinded and without breaking
stuff you can use

foo_unlocked() or unlocked_foo()

which do occur in the kernel (eg ioctl) when we want people to be
specifically aware of it although according to grep a little less often
than foo_locked() [discounting foo_is_locked which is general tests]

--

From: Stefani Seibold
Date: Monday, August 17, 2009 - 1:28 am

No. The kfifo struct in place does made it also necessary to patch all
this drivers. 

And the spinlock is in most cases useless, because the API works fine if
only one reader and one writer is using the fifo. This is the common

If you like it is very easy to add a compatibility layer, which restores
the old function names. But for what, only for very few users who
depends on it? This will only waste the name space.
  

--

From: Alan Cox
Date: Monday, August 17, 2009 - 1:53 am

That is one good argument for fixing the naming. The USB serial code
probably can be persuaded to use the  single reader/writer assumption as

Ooh the tragedy, we are short many things but namespace strangely is not
one of them. Especially when the names all start kfifo_ and __kfifo_, a
namespace much in demand by other code.

I'd rather have the old names, or the new names than some kind of gunge
middle layer of both. Either choice is better.
--

From: Stefani Seibold
Date: Monday, August 17, 2009 - 2:26 am

The question is: what do you expect? Should i provide a compat layer?
Should i retiring my work? 

Give me a solution for this dilemma. I see at this point no way if you
insist for the spinlock to design a clean interface.

Stefani

--

From: Alan Cox
Date: Monday, August 17, 2009 - 2:51 am

Then I won't insist.

Alan

--

From: Andi Kleen
Date: Monday, August 17, 2009 - 2:52 am

One thing that would be good to ensure is that old unconverted code
gets a clear compile time error, just in case some out of tree
code uses it. Bonus points also for having a short comment in kfifo.h that 
explains how to do the conversion.

Other than that I would be all for getting rid of embedded spinlocks
completely.

-Andi
-- 
ak@linux.intel.com -- Speaking for myself only.
--

From: Stefani Seibold
Date: Monday, August 17, 2009 - 2:56 am

From: Stefani Seibold
Date: Sunday, August 16, 2009 - 1:50 pm

change name of __kfifo_* functions to kfifo_*, because 
the prefix __kfifo should be reserved for internal functions.

Signed-off-by: Stefani Seibold <stefani@seibold.net>
---
 drivers/char/nozomi.c                       |   12 +++++-----
 drivers/infiniband/hw/cxgb3/cxio_resource.c |   10 ++++----
 drivers/net/wireless/libertas/cmd.c         |    4 +--
 drivers/net/wireless/libertas/main.c        |    8 +++----
 drivers/platform/x86/sony-laptop.c          |    2 -
 drivers/scsi/libiscsi.c                     |   14 ++++++------
 drivers/scsi/libiscsi_tcp.c                 |   20 ++++++++---------
 drivers/scsi/libsrp.c                       |    2 -
 drivers/usb/host/fhci.h                     |    6 ++---
 include/linux/kfifo.h                       |   32 ++++++----------------------
 kernel/kfifo.c                              |   12 +++++-----
 net/dccp/probe.c                            |    2 -
 12 files changed, 53 insertions(+), 71 deletions(-)

diff -u -N -r linux-2.6.31-rc4-kfifo2/drivers/char/nozomi.c linux-2.6.31-rc4-kfifo3/drivers/char/nozomi.c
--- linux-2.6.31-rc4-kfifo2/drivers/char/nozomi.c	2009-08-11 12:46:56.000000000 +0200
+++ linux-2.6.31-rc4-kfifo3/drivers/char/nozomi.c	2009-08-11 13:14:26.000000000 +0200
@@ -797,7 +797,7 @@
 	struct tty_struct *tty = tty_port_tty_get(&port->port);
 
 	/* Get data from tty and place in buf for now */
-	size = __kfifo_get(&port->fifo_ul, dc->send_buf,
+	size = kfifo_get(&port->fifo_ul, dc->send_buf,
 			   ul_size < SEND_BUF_MAX ? ul_size : SEND_BUF_MAX);
 
 	if (size == 0) {
@@ -987,11 +987,11 @@
 
 	} else if (old_ctrl.CTS == 0 && ctrl_dl.CTS == 1) {
 
-		if (__kfifo_len(&dc->port[port].fifo_ul)) {
+		if (kfifo_len(&dc->port[port].fifo_ul)) {
 			DBG1("Enable interrupt (0x%04X) on port: %d",
 				enable_ier, port);
 			DBG1("Data in buffer [%d], enable transmit! ",
-				__kfifo_len(&dc->port[port].fifo_ul));
+				kfifo_len(&dc->port[port].fifo_ul));
 			enable_transmit_ul(port, dc);
 		} else {
 			DBG1("No ...
From: Stefani Seibold
Date: Sunday, August 16, 2009 - 1:53 pm

rename kfifo_put... into kfifo_in... to prevent miss use of old non in kernel-tree drivers
ditto for kfifo_get... -> kfifo_out...

Signed-off-by: Stefani Seibold <stefani@seibold.net>
---
 drivers/char/nozomi.c                       |    4 +--
 drivers/char/sonypi.c                       |    8 +++----
 drivers/infiniband/hw/cxgb3/cxio_resource.c |   16 +++++++-------
 drivers/media/video/meye.c                  |   16 +++++++-------
 drivers/net/wireless/libertas/main.c        |    4 +--
 drivers/platform/x86/fujitsu-laptop.c       |    4 +--
 drivers/platform/x86/sony-laptop.c          |    8 +++----
 drivers/scsi/libiscsi.c                     |   14 ++++++------
 drivers/scsi/libiscsi_tcp.c                 |   18 +++++++--------
 drivers/scsi/libsrp.c                       |    6 ++---
 drivers/usb/host/fhci.h                     |    4 +--
 include/linux/kfifo.h                       |   20 ++++++++---------
 kernel/kfifo.c                              |   32 ++++++++++++++--------------
 net/dccp/probe.c                            |    4 +--
 14 files changed, 79 insertions(+), 79 deletions(-)

diff -u -N -r linux-2.6.31-rc4-kfifo3/drivers/char/nozomi.c linux-2.6.31-rc4-kfifo4/drivers/char/nozomi.c
--- linux-2.6.31-rc4-kfifo3/drivers/char/nozomi.c	2009-08-11 13:14:26.000000000 +0200
+++ linux-2.6.31-rc4-kfifo4/drivers/char/nozomi.c	2009-08-11 13:26:07.000000000 +0200
@@ -797,7 +797,7 @@
 	struct tty_struct *tty = tty_port_tty_get(&port->port);
 
 	/* Get data from tty and place in buf for now */
-	size = kfifo_get(&port->fifo_ul, dc->send_buf,
+	size = kfifo_out(&port->fifo_ul, dc->send_buf,
 			   ul_size < SEND_BUF_MAX ? ul_size : SEND_BUF_MAX);
 
 	if (size == 0) {
@@ -1671,7 +1671,7 @@
 		goto exit;
 	}
 
-	rval = kfifo_put(&port->fifo_ul, (unsigned char *)buffer, count);
+	rval = kfifo_in(&port->fifo_ul, (unsigned char *)buffer, count);
 
 	/* notify card */
 	if (unlikely(dc == NULL)) {
diff -u -N -r linux-2.6.31-rc4-kfifo3/drivers/char/sonypi.c ...
From: Stefani Seibold
Date: Sunday, August 16, 2009 - 1:57 pm

Add DECLARE_KFIFO - macro to declare a kfifo and the associated buffer inside a struct
 Add INIT_KFIFO - Initialize a kfifo declared by DECLARED_KFIFO
 Add DEFINE_KFIFO - macro to define and initialize a kfifo as a global or local object
 Add kfifo_size() - returns the size of the fifo in bytes
 Add kfifo_is_empty() - returns true if the fifo is empty
 Add kfifo_is_full() - returns true if the fifo is full
 Add kfifo_avail() - returns the number of bytes available in the FIFO
 Do some code cleanup

Signed-off-by: Stefani Seibold <stefani@seibold.net>
---
 kfifo.h |   85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 83 insertions(+), 2 deletions(-)

diff -u -N -r linux-2.6.31-rc4-kfifo4/include/linux/kfifo.h linux-2.6.31-rc4-kfifo5/include/linux/kfifo.h
--- linux-2.6.31-rc4-kfifo4/include/linux/kfifo.h	2009-08-16 22:16:13.000000000 +0200
+++ linux-2.6.31-rc4-kfifo5/include/linux/kfifo.h	2009-08-16 22:16:43.000000000 +0200
@@ -32,6 +32,51 @@
 	unsigned int out;	/* data is extracted from off. (out % size) */
 };
 
+/*
+ * Macros for declaration and initialization of the kfifo datatype
+ */
+
+#define __kfifo_initializer(s, b) \
+	(struct kfifo) { \
+		.size	= s, \
+		.in	= 0, \
+		.out	= 0, \
+		.buffer = b \
+	}
+
+/**
+ * DECLARE_KFIFO - macro to declare a kfifo and the associated buffer
+ * @name: name of the declared kfifo datatype
+ * @size: size of the fifo buffer
+ *
+ * Note: the macro can be used inside struct or union declaration
+ */
+#define DECLARE_KFIFO(name, size) \
+union { \
+	struct kfifo name; \
+	unsigned char name##kfifo_buffer[size + sizeof(struct kfifo)]; \
+}
+
+/**
+ * INIT_KFIFO - Initialize a kfifo declared by DECLARED_KFIFO
+ * @name: name of the declared kfifo datatype
+ * @size: size of the fifo buffer
+ */
+#define INIT_KFIFO(name) \
+	name = __kfifo_initializer(sizeof(name##kfifo_buffer) - \
+				sizeof(struct kfifo), name##kfifo_buffer)
+
+/**
+ * DEFINE_KFIFO - macro to define and ...
From: Stefani Seibold
Date: Sunday, August 16, 2009 - 2:00 pm

Add kfifo_reset_out() to lockless save discard the fifo output
 Add kfifo_skip() to skip a number of output bytes
 Add kfifo_from_user() to copy user space data into the fifo
 Add kfifo_to_user() to copy fifo data to user space

Signed-off-by: Stefani Seibold <stefani@seibold.net>
---
 include/linux/kfifo.h |   47 ++++++++++++++++
 kernel/kfifo.c        |  139 ++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 170 insertions(+), 16 deletions(-)

diff -u -N -r linux-2.6.31-rc4-kfifo5/include/linux/kfifo.h linux-2.6.31-rc4-kfifo6/include/linux/kfifo.h
--- linux-2.6.31-rc4-kfifo5/include/linux/kfifo.h	2009-08-16 22:16:43.000000000 +0200
+++ linux-2.6.31-rc4-kfifo6/include/linux/kfifo.h	2009-08-16 22:17:08.000000000 +0200
@@ -97,6 +97,16 @@
 }
 
 /**
+ * kfifo_reset_out - skip FIFO contents
+ * @fifo: the fifo to be emptied.
+ */
+static inline void kfifo_reset_out(struct kfifo *fifo)
+{
+	smp_mb();
+	fifo->out = fifo->in;
+}
+
+/**
  * kfifo_size - returns the size of the fifo in bytes
  * @fifo: the fifo to be used.
  */
@@ -203,4 +213,41 @@
 	return ret;
 }
 
+extern void kfifo_skip(struct kfifo *fifo, unsigned int len);
+
+extern __must_check unsigned int kfifo_from_user(struct kfifo *fifo,
+	const void __user *from, unsigned int n);
+
+extern __must_check unsigned int kfifo_to_user(struct kfifo *fifo,
+	void __user *to, unsigned int n);
+
+/**
+ * __kfifo_add_out internal helper function for updating the out offset
+ */
+static inline void __kfifo_add_out(struct kfifo *fifo,
+				unsigned int off)
+{
+	smp_mb();
+	fifo->out += off;
+}
+
+/**
+ * __kfifo_add_in internal helper function for updating the in offset
+ */
+static inline void __kfifo_add_in(struct kfifo *fifo,
+				unsigned int off)
+{
+	smp_wmb();
+	fifo->in += off;
+}
+
+/**
+ * __kfifo_off internal helper function for calculating the index of a
+ * given offeset
+ */
+static inline unsigned int __kfifo_off(struct kfifo *fifo, unsigned int off)
+{
+	return off ...
From: Stefani Seibold
Date: Sunday, August 16, 2009 - 2:03 pm

Add kfifo_in_rec() - puts some record data into the FIFO
 Add kfifo_out_rec() - gets some record data from the FIFO
 Add kfifo_from_user_rec() - puts some data from user space into the FIFO
 Add kfifo_to_user_rec() - gets data from the FIFO and write it to user space
 Add kfifo_peek_rec() - gets the size of the next FIFO record field
 Add kfifo_skip_rec() - skip the next fifo out record

Signed-off-by: Stefani Seibold <stefani@seibold.net>
---
 include/linux/kfifo.h |  318 ++++++++++++++++++++++++++++++++++++++++++++++++++
 kernel/kfifo.c        |  292 +++++++++++++++++++++++++++++++--------------
 2 files changed, 519 insertions(+), 91 deletions(-)

diff -u -N -r linux-2.6.31-rc4-kfifo6/include/linux/kfifo.h linux-2.6.31-rc4-kfifo7/include/linux/kfifo.h
--- linux-2.6.31-rc4-kfifo6/include/linux/kfifo.h	2009-08-16 22:17:08.000000000 +0200
+++ linux-2.6.31-rc4-kfifo7/include/linux/kfifo.h	2009-08-16 22:17:22.000000000 +0200
@@ -250,4 +250,322 @@
 	return off & (fifo->size - 1);
 }
 
+/**
+ * __kfifo_peek_n internal helper function for determinate the length of
+ * the next record in the fifo
+ */
+static inline unsigned int __kfifo_peek_n(struct kfifo *fifo,
+				unsigned int recsize)
+{
+#define	__KFIFO_GET(fifo, off, shift) \
+	((fifo)->buffer[__kfifo_off((fifo), (fifo)->out+(off))] << (shift))
+
+	unsigned int l;
+
+	l = __KFIFO_GET(fifo, 0, 0);
+
+	if (--recsize)
+		l |= __KFIFO_GET(fifo, 1, 8);
+
+	return l;
+}
+
+/**
+ * __kfifo_poke_n internal helper function for storing the length of
+ * the next record into the fifo
+ */
+static inline void __kfifo_poke_n(struct kfifo *fifo,
+			unsigned int recsize, unsigned int n)
+{
+#define	__KFIFO_PUT(fifo, off, val, shift) \
+		( \
+		(fifo)->buffer[__kfifo_off((fifo), (fifo)->in+(off))] = \
+		(unsigned char)((val) >> (shift)) \
+		)
+
+	__KFIFO_PUT(fifo, 0, n, 0);
+
+	if (--recsize)
+		__KFIFO_PUT(fifo, 1, n, 8);
+}
+
+/**
+ * __kfifo_in_... internal functions for put date into the fifo
+ * do not ...
From: Stefani Seibold
Date: Sunday, August 16, 2009 - 2:04 pm

Add kfifo_in_rec() - puts some record data into the FIFO
 Add kfifo_out_rec() - gets some record data from the FIFO
 Add kfifo_from_user_rec() - puts some data from user space into the FIFO
 Add kfifo_to_user_rec() - gets data from the FIFO and write it to user space
 Add kfifo_peek_rec() - gets the size of the next FIFO record field
 Add kfifo_skip_rec() - skip the next fifo out record

Signed-off-by: Stefani Seibold <stefani@seibold.net>
---
 include/linux/kfifo.h |  318 ++++++++++++++++++++++++++++++++++++++++++++++++++
 kernel/kfifo.c        |  292 +++++++++++++++++++++++++++++++--------------
 2 files changed, 519 insertions(+), 91 deletions(-)

diff -u -N -r linux-2.6.31-rc4-kfifo6/include/linux/kfifo.h linux-2.6.31-rc4-kfifo7/include/linux/kfifo.h
--- linux-2.6.31-rc4-kfifo6/include/linux/kfifo.h	2009-08-16 22:17:08.000000000 +0200
+++ linux-2.6.31-rc4-kfifo7/include/linux/kfifo.h	2009-08-16 22:17:22.000000000 +0200
@@ -250,4 +250,322 @@
 	return off & (fifo->size - 1);
 }
 
+/**
+ * __kfifo_peek_n internal helper function for determinate the length of
+ * the next record in the fifo
+ */
+static inline unsigned int __kfifo_peek_n(struct kfifo *fifo,
+				unsigned int recsize)
+{
+#define	__KFIFO_GET(fifo, off, shift) \
+	((fifo)->buffer[__kfifo_off((fifo), (fifo)->out+(off))] << (shift))
+
+	unsigned int l;
+
+	l = __KFIFO_GET(fifo, 0, 0);
+
+	if (--recsize)
+		l |= __KFIFO_GET(fifo, 1, 8);
+
+	return l;
+}
+
+/**
+ * __kfifo_poke_n internal helper function for storing the length of
+ * the next record into the fifo
+ */
+static inline void __kfifo_poke_n(struct kfifo *fifo,
+			unsigned int recsize, unsigned int n)
+{
+#define	__KFIFO_PUT(fifo, off, val, shift) \
+		( \
+		(fifo)->buffer[__kfifo_off((fifo), (fifo)->in+(off))] = \
+		(unsigned char)((val) >> (shift)) \
+		)
+
+	__KFIFO_PUT(fifo, 0, n, 0);
+
+	if (--recsize)
+		__KFIFO_PUT(fifo, 1, n, 8);
+}
+
+/**
+ * __kfifo_in_... internal functions for put date into the fifo
+ * do not ...
From: Stefani Seibold
Date: Sunday, August 16, 2009 - 2:08 pm

Message
[PATCH 0/7] kfifo: add record handling functions
should be
[PATCH 7/7] kfifo: add record handling functions

So i send it again..

I am sorry,
Stefani


--

Previous thread: [RFC -tip] x86,apic: set cpu_has_apic manually for discrete apic by Cyrill Gorcunov on Sunday, August 16, 2009 - 12:57 pm. (2 messages)

Next thread: [patch] fs: Make unload_nls() NULL pointer safe by Thomas Gleixner on Sunday, August 16, 2009 - 2:05 pm. (2 messages)