xref: /freebsd/sys/compat/linuxkpi/common/include/linux/kfifo.h (revision d448578b445da95806ef9af996a0db9754daadeb)
1 /*-
2  * Copyright (c) 2021 Beckhoff Automation GmbH & Co. KG
3  * Copyright (c) 2022 Bjoern A. Zeeb
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  */
27 
28 #ifndef _LINUXKPI_LINUX_KFIFO_H_
29 #define	_LINUXKPI_LINUX_KFIFO_H_
30 
31 #include <sys/types.h>
32 
33 #include <linux/slab.h>
34 #include <linux/gfp.h>
35 
36 /*
37  * INIT_KFIFO() is used to initialize the structure declared with
38  * DECLARE_KFIFO(). It doesn't work with DECLARE_KFIFO_PTR().
39  */
40 #define	INIT_KFIFO(_kf)							\
41 	({								\
42 		(_kf).total = nitems((_kf).head);			\
43 		(_kf).count = 0;					\
44 		(_kf).first = 0;					\
45 		(_kf).last = 0;						\
46 	})
47 
48 #define	DECLARE_KFIFO(_name, _type, _size)				\
49 	struct kfifo_ ## _name {					\
50 		size_t		total;					\
51 		size_t		count;					\
52 		size_t		first;					\
53 		size_t		last;					\
54 		_type		head[_size];				\
55 	} _name
56 
57 #define	DECLARE_KFIFO_PTR(_name, _type)					\
58 	struct kfifo_ ## _name {					\
59 		size_t		total;					\
60 		size_t		count;					\
61 		size_t		first;					\
62 		size_t		last;					\
63 		_type		*head;					\
64 	} _name
65 
66 #define	kfifo_len(_kf)							\
67 ({									\
68 	(_kf)->count;							\
69 })
70 
71 #define	kfifo_is_empty(_kf)						\
72 ({									\
73 	((_kf)->count == 0) ? true : false;				\
74 })
75 
76 #define	kfifo_is_full(_kf)						\
77 ({									\
78 	((_kf)->count == (_kf)->total) ? true : false;			\
79 })
80 
81 #define	kfifo_put(_kf, _e)						\
82 ({									\
83 	bool _rc;							\
84 									\
85 	/* Would overflow. */						\
86 	if (kfifo_is_full(_kf)) {					\
87 		_rc = false;						\
88 	} else {							\
89 		(_kf)->head[(_kf)->last] = (_e);			\
90 		(_kf)->count++;						\
91 		(_kf)->last++;						\
92 		if ((_kf)->last > (_kf)->total)				\
93 			(_kf)->last = 0;				\
94 		_rc = true;						\
95 	}								\
96 									\
97 	_rc;								\
98 })
99 
100 #define	kfifo_get(_kf, _e)						\
101 ({									\
102 	bool _rc;							\
103 									\
104 	if (kfifo_is_empty(_kf)) {					\
105 		_rc = false;						\
106 	} else {							\
107 		*(_e) = (_kf)->head[(_kf)->first];			\
108 		(_kf)->count--;						\
109 		(_kf)->first++;						\
110 		if ((_kf)->first > (_kf)->total)			\
111 			(_kf)->first = 0;				\
112 		_rc = true;						\
113 	}								\
114 									\
115 	_rc;								\
116 })
117 
118 #define	kfifo_alloc(_kf, _s, _gfp)					\
119 ({									\
120 	int _error;							\
121 									\
122 	(_kf)->head = kmalloc(sizeof(__typeof(*(_kf)->head)) * (_s), _gfp); \
123 	if ((_kf)->head == NULL)					\
124 		_error = ENOMEM;					\
125 	else {								\
126 		(_kf)->total = (_s);					\
127 		_error = 0;						\
128 	}								\
129 									\
130 	_error;								\
131 })
132 
133 #define	kfifo_free(_kf)							\
134 ({									\
135 	kfree((_kf)->head);						\
136 	(_kf)->head = NULL;						\
137 	(_kf)->total = (_kf)->count = (_kf)->first = (_kf)->last = 0;	\
138 })
139 
140 #endif	/* _LINUXKPI_LINUX_KFIFO_H_*/
141