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 #define	INIT_KFIFO(x)	0
37 #define	DECLARE_KFIFO(x, y, z)
38 
39 #define	DECLARE_KFIFO_PTR(_name, _type)					\
40 	struct kfifo_ ## _name {					\
41 		size_t		total;					\
42 		size_t		count;					\
43 		size_t		first;					\
44 		size_t		last;					\
45 		_type		*head;					\
46 	} _name
47 
48 #define	kfifo_len(_kf)							\
49 ({									\
50 	(_kf)->count;							\
51 })
52 
53 #define	kfifo_is_empty(_kf)						\
54 ({									\
55 	((_kf)->count == 0) ? true : false;				\
56 })
57 
58 #define	kfifo_is_full(_kf)						\
59 ({									\
60 	((_kf)->count == (_kf)->total) ? true : false;			\
61 })
62 
63 #define	kfifo_put(_kf, _e)						\
64 ({									\
65 	bool _rc;							\
66 									\
67 	/* Would overflow. */						\
68 	if (kfifo_is_full(_kf)) {					\
69 		_rc = false;						\
70 	} else {							\
71 		(_kf)->head[(_kf)->last] = (_e);			\
72 		(_kf)->count++;						\
73 		(_kf)->last++;						\
74 		if ((_kf)->last > (_kf)->total)				\
75 			(_kf)->last = 0;				\
76 		_rc = true;						\
77 	}								\
78 									\
79 	_rc;								\
80 })
81 
82 #define	kfifo_get(_kf, _e)						\
83 ({									\
84 	bool _rc;							\
85 									\
86 	if (kfifo_is_empty(_kf)) {					\
87 		_rc = false;						\
88 	} else {							\
89 		*(_e) = (_kf)->head[(_kf)->first];			\
90 		(_kf)->count--;						\
91 		(_kf)->first++;						\
92 		if ((_kf)->first > (_kf)->total)			\
93 			(_kf)->first = 0;				\
94 		_rc = true;						\
95 	}								\
96 									\
97 	_rc;								\
98 })
99 
100 #define	kfifo_alloc(_kf, _s, _gfp)					\
101 ({									\
102 	int _error;							\
103 									\
104 	(_kf)->head = kmalloc(sizeof(__typeof(*(_kf)->head)) * (_s), _gfp); \
105 	if ((_kf)->head == NULL)					\
106 		_error = ENOMEM;					\
107 	else {								\
108 		(_kf)->total = (_s);					\
109 		_error = 0;						\
110 	}								\
111 									\
112 	_error;								\
113 })
114 
115 #define	kfifo_free(_kf)							\
116 ({									\
117 	kfree((_kf)->head);						\
118 	(_kf)->head = NULL;						\
119 	(_kf)->total = (_kf)->count = (_kf)->first = (_kf)->last = 0;	\
120 })
121 
122 #endif	/* _LINUXKPI_LINUX_KFIFO_H_*/
123