xref: /freebsd/sys/compat/linuxkpi/common/include/linux/kfifo.h (revision 5945da0bc9ac42f531b1079a246eb8ce4f0d63db)
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/array_size.h>
34 #include <linux/slab.h>
35 #include <linux/gfp.h>
36 
37 /*
38  * INIT_KFIFO() is used to initialize the structure declared with
39  * DECLARE_KFIFO(). It doesn't work with DECLARE_KFIFO_PTR().
40  */
41 #define	INIT_KFIFO(_kf)							\
42 	({								\
43 		(_kf).total = nitems((_kf).head);			\
44 		(_kf).count = 0;					\
45 		(_kf).first = 0;					\
46 		(_kf).last = 0;						\
47 	})
48 
49 #define	DECLARE_KFIFO(_name, _type, _size)				\
50 	struct kfifo_ ## _name {					\
51 		size_t		total;					\
52 		size_t		count;					\
53 		size_t		first;					\
54 		size_t		last;					\
55 		_type		head[_size];				\
56 	} _name
57 
58 #define	DECLARE_KFIFO_PTR(_name, _type)					\
59 	struct kfifo_ ## _name {					\
60 		size_t		total;					\
61 		size_t		count;					\
62 		size_t		first;					\
63 		size_t		last;					\
64 		_type		*head;					\
65 	} _name
66 
67 #define	kfifo_len(_kf)							\
68 ({									\
69 	(_kf)->count;							\
70 })
71 
72 #define	kfifo_is_empty(_kf)						\
73 ({									\
74 	((_kf)->count == 0) ? true : false;				\
75 })
76 
77 #define	kfifo_is_full(_kf)						\
78 ({									\
79 	((_kf)->count == (_kf)->total) ? true : false;			\
80 })
81 
82 #define	kfifo_put(_kf, _e)						\
83 ({									\
84 	bool _rc;							\
85 									\
86 	/* Would overflow. */						\
87 	if (kfifo_is_full(_kf)) {					\
88 		_rc = false;						\
89 	} else {							\
90 		(_kf)->head[(_kf)->last] = (_e);			\
91 		(_kf)->count++;						\
92 		(_kf)->last++;						\
93 		if ((_kf)->last >= (_kf)->total)			\
94 			(_kf)->last = 0;				\
95 		_rc = true;						\
96 	}								\
97 									\
98 	_rc;								\
99 })
100 
101 #define	kfifo_get(_kf, _e)						\
102 ({									\
103 	bool _rc;							\
104 									\
105 	if (kfifo_is_empty(_kf)) {					\
106 		_rc = false;						\
107 	} else {							\
108 		*(_e) = (_kf)->head[(_kf)->first];			\
109 		(_kf)->count--;						\
110 		(_kf)->first++;						\
111 		if ((_kf)->first >= (_kf)->total)			\
112 			(_kf)->first = 0;				\
113 		_rc = true;						\
114 	}								\
115 									\
116 	_rc;								\
117 })
118 
119 #define	kfifo_alloc(_kf, _s, _gfp)					\
120 ({									\
121 	int _error;							\
122 									\
123 	(_kf)->head = kmalloc(sizeof(__typeof(*(_kf)->head)) * (_s), _gfp); \
124 	if ((_kf)->head == NULL)					\
125 		_error = ENOMEM;					\
126 	else {								\
127 		(_kf)->total = (_s);					\
128 		_error = 0;						\
129 	}								\
130 									\
131 	_error;								\
132 })
133 
134 #define	kfifo_free(_kf)							\
135 ({									\
136 	kfree((_kf)->head);						\
137 	(_kf)->head = NULL;						\
138 	(_kf)->total = (_kf)->count = (_kf)->first = (_kf)->last = 0;	\
139 })
140 
141 #endif	/* _LINUXKPI_LINUX_KFIFO_H_*/
142