xref: /linux/include/linux/kfifo.h (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /*
2*1da177e4SLinus Torvalds  * A simple kernel FIFO implementation.
3*1da177e4SLinus Torvalds  *
4*1da177e4SLinus Torvalds  * Copyright (C) 2004 Stelian Pop <stelian@popies.net>
5*1da177e4SLinus Torvalds  *
6*1da177e4SLinus Torvalds  * This program is free software; you can redistribute it and/or modify
7*1da177e4SLinus Torvalds  * it under the terms of the GNU General Public License as published by
8*1da177e4SLinus Torvalds  * the Free Software Foundation; either version 2 of the License, or
9*1da177e4SLinus Torvalds  * (at your option) any later version.
10*1da177e4SLinus Torvalds  *
11*1da177e4SLinus Torvalds  * This program is distributed in the hope that it will be useful,
12*1da177e4SLinus Torvalds  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*1da177e4SLinus Torvalds  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*1da177e4SLinus Torvalds  * GNU General Public License for more details.
15*1da177e4SLinus Torvalds  *
16*1da177e4SLinus Torvalds  * You should have received a copy of the GNU General Public License
17*1da177e4SLinus Torvalds  * along with this program; if not, write to the Free Software
18*1da177e4SLinus Torvalds  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*1da177e4SLinus Torvalds  *
20*1da177e4SLinus Torvalds  */
21*1da177e4SLinus Torvalds #ifndef _LINUX_KFIFO_H
22*1da177e4SLinus Torvalds #define _LINUX_KFIFO_H
23*1da177e4SLinus Torvalds 
24*1da177e4SLinus Torvalds #ifdef __KERNEL__
25*1da177e4SLinus Torvalds 
26*1da177e4SLinus Torvalds #include <linux/kernel.h>
27*1da177e4SLinus Torvalds #include <linux/spinlock.h>
28*1da177e4SLinus Torvalds 
29*1da177e4SLinus Torvalds struct kfifo {
30*1da177e4SLinus Torvalds 	unsigned char *buffer;	/* the buffer holding the data */
31*1da177e4SLinus Torvalds 	unsigned int size;	/* the size of the allocated buffer */
32*1da177e4SLinus Torvalds 	unsigned int in;	/* data is added at offset (in % size) */
33*1da177e4SLinus Torvalds 	unsigned int out;	/* data is extracted from off. (out % size) */
34*1da177e4SLinus Torvalds 	spinlock_t *lock;	/* protects concurrent modifications */
35*1da177e4SLinus Torvalds };
36*1da177e4SLinus Torvalds 
37*1da177e4SLinus Torvalds extern struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size,
38*1da177e4SLinus Torvalds 				unsigned int __nocast gfp_mask, spinlock_t *lock);
39*1da177e4SLinus Torvalds extern struct kfifo *kfifo_alloc(unsigned int size, unsigned int __nocast gfp_mask,
40*1da177e4SLinus Torvalds 				 spinlock_t *lock);
41*1da177e4SLinus Torvalds extern void kfifo_free(struct kfifo *fifo);
42*1da177e4SLinus Torvalds extern unsigned int __kfifo_put(struct kfifo *fifo,
43*1da177e4SLinus Torvalds 				unsigned char *buffer, unsigned int len);
44*1da177e4SLinus Torvalds extern unsigned int __kfifo_get(struct kfifo *fifo,
45*1da177e4SLinus Torvalds 				unsigned char *buffer, unsigned int len);
46*1da177e4SLinus Torvalds 
47*1da177e4SLinus Torvalds /**
48*1da177e4SLinus Torvalds  * __kfifo_reset - removes the entire FIFO contents, no locking version
49*1da177e4SLinus Torvalds  * @fifo: the fifo to be emptied.
50*1da177e4SLinus Torvalds  */
51*1da177e4SLinus Torvalds static inline void __kfifo_reset(struct kfifo *fifo)
52*1da177e4SLinus Torvalds {
53*1da177e4SLinus Torvalds 	fifo->in = fifo->out = 0;
54*1da177e4SLinus Torvalds }
55*1da177e4SLinus Torvalds 
56*1da177e4SLinus Torvalds /**
57*1da177e4SLinus Torvalds  * kfifo_reset - removes the entire FIFO contents
58*1da177e4SLinus Torvalds  * @fifo: the fifo to be emptied.
59*1da177e4SLinus Torvalds  */
60*1da177e4SLinus Torvalds static inline void kfifo_reset(struct kfifo *fifo)
61*1da177e4SLinus Torvalds {
62*1da177e4SLinus Torvalds 	unsigned long flags;
63*1da177e4SLinus Torvalds 
64*1da177e4SLinus Torvalds 	spin_lock_irqsave(fifo->lock, flags);
65*1da177e4SLinus Torvalds 
66*1da177e4SLinus Torvalds 	__kfifo_reset(fifo);
67*1da177e4SLinus Torvalds 
68*1da177e4SLinus Torvalds 	spin_unlock_irqrestore(fifo->lock, flags);
69*1da177e4SLinus Torvalds }
70*1da177e4SLinus Torvalds 
71*1da177e4SLinus Torvalds /**
72*1da177e4SLinus Torvalds  * kfifo_put - puts some data into the FIFO
73*1da177e4SLinus Torvalds  * @fifo: the fifo to be used.
74*1da177e4SLinus Torvalds  * @buffer: the data to be added.
75*1da177e4SLinus Torvalds  * @len: the length of the data to be added.
76*1da177e4SLinus Torvalds  *
77*1da177e4SLinus Torvalds  * This function copies at most 'len' bytes from the 'buffer' into
78*1da177e4SLinus Torvalds  * the FIFO depending on the free space, and returns the number of
79*1da177e4SLinus Torvalds  * bytes copied.
80*1da177e4SLinus Torvalds  */
81*1da177e4SLinus Torvalds static inline unsigned int kfifo_put(struct kfifo *fifo,
82*1da177e4SLinus Torvalds 				     unsigned char *buffer, unsigned int len)
83*1da177e4SLinus Torvalds {
84*1da177e4SLinus Torvalds 	unsigned long flags;
85*1da177e4SLinus Torvalds 	unsigned int ret;
86*1da177e4SLinus Torvalds 
87*1da177e4SLinus Torvalds 	spin_lock_irqsave(fifo->lock, flags);
88*1da177e4SLinus Torvalds 
89*1da177e4SLinus Torvalds 	ret = __kfifo_put(fifo, buffer, len);
90*1da177e4SLinus Torvalds 
91*1da177e4SLinus Torvalds 	spin_unlock_irqrestore(fifo->lock, flags);
92*1da177e4SLinus Torvalds 
93*1da177e4SLinus Torvalds 	return ret;
94*1da177e4SLinus Torvalds }
95*1da177e4SLinus Torvalds 
96*1da177e4SLinus Torvalds /**
97*1da177e4SLinus Torvalds  * kfifo_get - gets some data from the FIFO
98*1da177e4SLinus Torvalds  * @fifo: the fifo to be used.
99*1da177e4SLinus Torvalds  * @buffer: where the data must be copied.
100*1da177e4SLinus Torvalds  * @len: the size of the destination buffer.
101*1da177e4SLinus Torvalds  *
102*1da177e4SLinus Torvalds  * This function copies at most 'len' bytes from the FIFO into the
103*1da177e4SLinus Torvalds  * 'buffer' and returns the number of copied bytes.
104*1da177e4SLinus Torvalds  */
105*1da177e4SLinus Torvalds static inline unsigned int kfifo_get(struct kfifo *fifo,
106*1da177e4SLinus Torvalds 				     unsigned char *buffer, unsigned int len)
107*1da177e4SLinus Torvalds {
108*1da177e4SLinus Torvalds 	unsigned long flags;
109*1da177e4SLinus Torvalds 	unsigned int ret;
110*1da177e4SLinus Torvalds 
111*1da177e4SLinus Torvalds 	spin_lock_irqsave(fifo->lock, flags);
112*1da177e4SLinus Torvalds 
113*1da177e4SLinus Torvalds 	ret = __kfifo_get(fifo, buffer, len);
114*1da177e4SLinus Torvalds 
115*1da177e4SLinus Torvalds 	/*
116*1da177e4SLinus Torvalds 	 * optimization: if the FIFO is empty, set the indices to 0
117*1da177e4SLinus Torvalds 	 * so we don't wrap the next time
118*1da177e4SLinus Torvalds 	 */
119*1da177e4SLinus Torvalds 	if (fifo->in == fifo->out)
120*1da177e4SLinus Torvalds 		fifo->in = fifo->out = 0;
121*1da177e4SLinus Torvalds 
122*1da177e4SLinus Torvalds 	spin_unlock_irqrestore(fifo->lock, flags);
123*1da177e4SLinus Torvalds 
124*1da177e4SLinus Torvalds 	return ret;
125*1da177e4SLinus Torvalds }
126*1da177e4SLinus Torvalds 
127*1da177e4SLinus Torvalds /**
128*1da177e4SLinus Torvalds  * __kfifo_len - returns the number of bytes available in the FIFO, no locking version
129*1da177e4SLinus Torvalds  * @fifo: the fifo to be used.
130*1da177e4SLinus Torvalds  */
131*1da177e4SLinus Torvalds static inline unsigned int __kfifo_len(struct kfifo *fifo)
132*1da177e4SLinus Torvalds {
133*1da177e4SLinus Torvalds 	return fifo->in - fifo->out;
134*1da177e4SLinus Torvalds }
135*1da177e4SLinus Torvalds 
136*1da177e4SLinus Torvalds /**
137*1da177e4SLinus Torvalds  * kfifo_len - returns the number of bytes available in the FIFO
138*1da177e4SLinus Torvalds  * @fifo: the fifo to be used.
139*1da177e4SLinus Torvalds  */
140*1da177e4SLinus Torvalds static inline unsigned int kfifo_len(struct kfifo *fifo)
141*1da177e4SLinus Torvalds {
142*1da177e4SLinus Torvalds 	unsigned long flags;
143*1da177e4SLinus Torvalds 	unsigned int ret;
144*1da177e4SLinus Torvalds 
145*1da177e4SLinus Torvalds 	spin_lock_irqsave(fifo->lock, flags);
146*1da177e4SLinus Torvalds 
147*1da177e4SLinus Torvalds 	ret = __kfifo_len(fifo);
148*1da177e4SLinus Torvalds 
149*1da177e4SLinus Torvalds 	spin_unlock_irqrestore(fifo->lock, flags);
150*1da177e4SLinus Torvalds 
151*1da177e4SLinus Torvalds 	return ret;
152*1da177e4SLinus Torvalds }
153*1da177e4SLinus Torvalds 
154*1da177e4SLinus Torvalds #else
155*1da177e4SLinus Torvalds #warning "don't include kernel headers in userspace"
156*1da177e4SLinus Torvalds #endif /* __KERNEL__ */
157*1da177e4SLinus Torvalds #endif
158