1 /*
2 * SPDX-FileCopyrightText: Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 * SPDX-License-Identifier: MIT
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23 #ifndef NV_CONTAINERS_RINGBUF_H
24 #define NV_CONTAINERS_RINGBUF_H
25
26 #include "nvtypes.h"
27 #include "nvstatus.h"
28 #include "nvmisc.h"
29 #include "nvctassert.h"
30 #include "utils/nvassert.h"
31 #include "nvport/nvport.h"
32 #include "containers/type_safety.h"
33
34 typedef struct RingBufBase
35 {
36 NvU64 head;
37 NvU64 tail;
38 NvU64 logSz;
39 NvU8 *arr;
40 } RingBufBase;
41
42 #define RINGBUF_ARRAY_SIZE(pBuf) (1llu << ((pBuf)->logSz))
43
44 #define RINGBUF_ARRAY_MASK(pBuf) (RINGBUF_ARRAY_SIZE(pBuf) - 1llu)
45
46 #define MAKE_RINGBUF(containedType, outputType, logSz) \
47 typedef struct outputType { \
48 union { \
49 RingBufBase base; \
50 PORT_MEM_ALLOCATOR *pAllocator; \
51 }; \
52 union { \
53 containedType elem[1llu << (logSz)]; \
54 NvU8 lgSz[((logSz) < 64) ? (logSz) : -1]; /* Ternary to ensure we get CT error when logSz >= 64 */ \
55 }; \
56 } outputType
57
58 #define MAKE_RINGBUF_DYNAMIC(containedType, outputType) \
59 typedef union outputType { \
60 struct { \
61 RingBufBase base; \
62 PORT_MEM_ALLOCATOR *pAllocator; \
63 }; \
64 containedType *elem; \
65 } outputType
66
67 #if NV_TYPEOF_SUPPORTED
68
69 #define FOR_EACH_IN_RINGBUF(pBuf, idx, ptr) \
70 { \
71 (idx) = (pBuf)->base.tail; \
72 while((idx) != (pBuf)->base.head) \
73 { \
74 (ptr) = (typeof(&((pBuf)->elem)[0])) &(pBuf)->base.arr[((idx) & RINGBUF_ARRAY_MASK(&((pBuf)->base))) * \
75 sizeof(*((pBuf)->elem))]; \
76 (idx)++;
77
78 #else
79
80 #define FOR_EACH_IN_RINGBUF(pBuf, idx, ptr) \
81 { \
82 (idx) = (pBuf)->base.tail; \
83 while((idx) != (pBuf)->base.head) \
84 { \
85 (ptr) = (void *)&(pBuf)->base.arr[((idx) & RINGBUF_ARRAY_MASK(&((pBuf)->base))) * \
86 sizeof(*((pBuf)->elem))]; \
87 (idx)++;
88
89 #endif // NV_TYPEOF_SUPPORTED
90
91 #define FOR_EACH_END_RINGBUF() \
92 } \
93 }
94
95
96 #define ringbufConstructDynamic(pBuf, logSz, pAlloc) \
97 (pBuf->pAllocator = pAlloc, ringbufConstructDynamic_IMPL(&((pBuf)->base), logSz, sizeof(*((pBuf)->elem)), pAlloc))
98
99 #define ringbufConstruct(pBuf) \
100 ringbufConstruct_IMPL(&((pBuf)->base), sizeof((pBuf)->lgSz), (void*)((pBuf)->elem))
101
102 #define ringbufDestruct(pBuf) \
103 ringbufDestruct_IMPL(&((pBuf)->base), ((void*)&((pBuf)->pAllocator)) == ((void*)&((pBuf)->base)) ? NULL : ((pBuf)->pAllocator) )
104
105 #if NV_TYPEOF_SUPPORTED
106
107 #define ringbufPopN(pBuf, pMax) \
108 (typeof(&((pBuf)->elem)[0])) ringbufPopN_IMPL(&((pBuf)->base), sizeof(*((pBuf)->elem)), pMax)
109
110 #define ringbufPeekN(pBuf, pMax) \
111 (typeof(&((pBuf)->elem)[0])) ringbufPeekN_IMPL(&((pBuf)->base), sizeof(*((pBuf)->elem)), pMax)
112
113 #define ringbufAppendN(pBuf, pEles, num, bOver) \
114 ringbufAppendN_IMPL(&((pBuf)->base), sizeof(*((pBuf)->elem)), (NvU8*)pEles, num, bOver)
115
116 #define ringbufPop(pBuf) \
117 (typeof(&((pBuf)->elem)[0])) ringbufPop_IMPL(&((pBuf)->base), sizeof(*((pBuf)->elem)))
118
119 #define ringbufPeek(pBuf) \
120 (typeof(&((pBuf)->elem)[0])) ringbufPeek_IMPL(&((pBuf)->base), sizeof(*((pBuf)->elem)))
121
122 #else
123
124 #define ringbufPopN(pBuf, pMax) \
125 (void *)ringbufPopN_IMPL(&((pBuf)->base), sizeof(*((pBuf)->elem)), pMax)
126
127 #define ringbufPeekN(pBuf, pMax) \
128 (void *)ringbufPeekN_IMPL(&((pBuf)->base), sizeof(*((pBuf)->elem)), pMax)
129
130 #define ringbufAppendN(pBuf, pEles, num, bOver) \
131 ringbufAppendN_IMPL(&((pBuf)->base), sizeof(*((pBuf)->elem)), (NvU8*)pEles, num, bOver)
132
133 #define ringbufPop(pBuf) \
134 (void *)ringbufPop_IMPL(&((pBuf)->base), sizeof(*((pBuf)->elem)))
135
136 #define ringbufPeek(pBuf) \
137 (void *)ringbufPeek_IMPL(&((pBuf)->base), sizeof(*((pBuf)->elem)))
138
139 #endif // NV_TYPEOF_SUPPORTED
140
141 #define ringbufAppend(pBuf, pEle, bOver) \
142 ringbufAppend_IMPL(&((pBuf)->base), sizeof(*((pBuf)->elem)), (NvU8*)pEle, bOver)
143
144 #define ringbufCurrentSize(pBuf) \
145 ringbufCurrentSize_IMPL(&((pBuf)->base))
146
147 NvBool ringbufConstructDynamic_IMPL(RingBufBase *pBase, NvU64 logSz, NvU64 eleSz, PORT_MEM_ALLOCATOR *pAlloc);
148 NvBool ringbufConstruct_IMPL(RingBufBase *pBase, NvU64 logSz, void *arr);
149 void ringbufDestruct_IMPL(RingBufBase *pBase, void *alloc);
150 void *ringbufPopN_IMPL(RingBufBase *pBase, NvU64 eleSz, NvU64 *pMax);
151 void *ringbufPeekN_IMPL(RingBufBase *pBase, NvU64 eleSz, NvU64 *pMax);
152 NvBool ringbufAppendN_IMPL(RingBufBase *pBase, NvU64 eleSz, NvU8 *pEle, NvU64 num, NvBool bOverwrite);
153 NvU64 ringbufCurrentSize_IMPL(RingBufBase *pBase);
154
ringbufPeek_IMPL(RingBufBase * pBase,NvU64 eleSz)155 static inline void *ringbufPeek_IMPL(RingBufBase *pBase, NvU64 eleSz)
156 {
157 NvU64 max = 1;
158 return ringbufPeekN_IMPL(pBase, eleSz, &max);
159 }
ringbufPop_IMPL(RingBufBase * pBase,NvU64 eleSz)160 static inline void *ringbufPop_IMPL(RingBufBase *pBase, NvU64 eleSz)
161 {
162 NvU64 max = 1;
163 return ringbufPopN_IMPL(pBase, eleSz, &max);
164 }
ringbufAppend_IMPL(RingBufBase * pBase,NvU64 eleSz,NvU8 * pEle,NvBool bOverwrite)165 static inline NvBool ringbufAppend_IMPL(RingBufBase *pBase, NvU64 eleSz, NvU8 *pEle, NvBool bOverwrite)
166 {
167 return ringbufAppendN_IMPL(pBase, eleSz, pEle, 1, bOverwrite);
168 }
169 #endif
170