]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/compat/linuxkpi/common/include/linux/kfifo.h
LinuxKPI: extend kfifo to be usable
[FreeBSD/FreeBSD.git] / sys / compat / linuxkpi / common / include / linux / kfifo.h
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_*/