]>
Commit | Line | Data |
---|---|---|
0de1b425 WT |
1 | /* |
2 | * Copyright (c) 2018, 2019 Nicira, Inc. | |
3 | * | |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at: | |
7 | * | |
8 | * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
15 | */ | |
16 | #include <config.h> | |
17 | ||
18 | #include "dp-packet.h" | |
19 | #include "netdev-afxdp-pool.h" | |
20 | #include "openvswitch/util.h" | |
21 | ||
22 | /* Note: | |
23 | * umem_elem_push* shouldn't overflow because we always pop | |
24 | * elem first, then push back to the stack. | |
25 | */ | |
26 | static inline void | |
27 | umem_elem_push_n__(struct umem_pool *umemp, int n, void **addrs) | |
28 | { | |
29 | void *ptr; | |
30 | ||
31 | ovs_assert(umemp->index + n <= umemp->size); | |
32 | ||
33 | ptr = &umemp->array[umemp->index]; | |
34 | memcpy(ptr, addrs, n * sizeof(void *)); | |
35 | umemp->index += n; | |
36 | } | |
37 | ||
38 | void umem_elem_push_n(struct umem_pool *umemp, int n, void **addrs) | |
39 | { | |
40 | ovs_spin_lock(&umemp->lock); | |
41 | umem_elem_push_n__(umemp, n, addrs); | |
42 | ovs_spin_unlock(&umemp->lock); | |
43 | } | |
44 | ||
45 | static inline void | |
46 | umem_elem_push__(struct umem_pool *umemp, void *addr) | |
47 | { | |
48 | ovs_assert(umemp->index + 1 <= umemp->size); | |
49 | ||
50 | umemp->array[umemp->index++] = addr; | |
51 | } | |
52 | ||
53 | void | |
54 | umem_elem_push(struct umem_pool *umemp, void *addr) | |
55 | { | |
56 | ovs_spin_lock(&umemp->lock); | |
57 | umem_elem_push__(umemp, addr); | |
58 | ovs_spin_unlock(&umemp->lock); | |
59 | } | |
60 | ||
61 | static inline int | |
62 | umem_elem_pop_n__(struct umem_pool *umemp, int n, void **addrs) | |
63 | { | |
64 | void *ptr; | |
65 | ||
66 | if (OVS_UNLIKELY(umemp->index - n < 0)) { | |
67 | return -ENOMEM; | |
68 | } | |
69 | ||
70 | umemp->index -= n; | |
71 | ptr = &umemp->array[umemp->index]; | |
72 | memcpy(addrs, ptr, n * sizeof(void *)); | |
73 | ||
74 | return 0; | |
75 | } | |
76 | ||
77 | int | |
78 | umem_elem_pop_n(struct umem_pool *umemp, int n, void **addrs) | |
79 | { | |
80 | int ret; | |
81 | ||
82 | ovs_spin_lock(&umemp->lock); | |
83 | ret = umem_elem_pop_n__(umemp, n, addrs); | |
84 | ovs_spin_unlock(&umemp->lock); | |
85 | ||
86 | return ret; | |
87 | } | |
88 | ||
89 | static inline void * | |
90 | umem_elem_pop__(struct umem_pool *umemp) | |
91 | { | |
92 | if (OVS_UNLIKELY(umemp->index - 1 < 0)) { | |
93 | return NULL; | |
94 | } | |
95 | ||
96 | return umemp->array[--umemp->index]; | |
97 | } | |
98 | ||
99 | void * | |
100 | umem_elem_pop(struct umem_pool *umemp) | |
101 | { | |
102 | void *ptr; | |
103 | ||
104 | ovs_spin_lock(&umemp->lock); | |
105 | ptr = umem_elem_pop__(umemp); | |
106 | ovs_spin_unlock(&umemp->lock); | |
107 | ||
108 | return ptr; | |
109 | } | |
110 | ||
111 | static void ** | |
112 | umem_pool_alloc__(unsigned int size) | |
113 | { | |
114 | void **bufs; | |
115 | ||
116 | bufs = xmalloc_pagealign(size * sizeof *bufs); | |
117 | memset(bufs, 0, size * sizeof *bufs); | |
118 | ||
119 | return bufs; | |
120 | } | |
121 | ||
122 | int | |
123 | umem_pool_init(struct umem_pool *umemp, unsigned int size) | |
124 | { | |
125 | umemp->array = umem_pool_alloc__(size); | |
126 | if (!umemp->array) { | |
127 | return -ENOMEM; | |
128 | } | |
129 | ||
130 | umemp->size = size; | |
131 | umemp->index = 0; | |
132 | ovs_spin_init(&umemp->lock); | |
133 | return 0; | |
134 | } | |
135 | ||
136 | void | |
137 | umem_pool_cleanup(struct umem_pool *umemp) | |
138 | { | |
139 | free_pagealign(umemp->array); | |
140 | umemp->array = NULL; | |
141 | ovs_spin_destroy(&umemp->lock); | |
142 | } | |
143 | ||
144 | unsigned int | |
145 | umem_pool_count(struct umem_pool *umemp) | |
146 | { | |
147 | return umemp->index; | |
148 | } | |
149 | ||
150 | /* AF_XDP metadata init/destroy. */ | |
151 | int | |
152 | xpacket_pool_init(struct xpacket_pool *xp, unsigned int size) | |
153 | { | |
154 | xp->array = xmalloc_pagealign(size * sizeof *xp->array); | |
155 | xp->size = size; | |
156 | ||
157 | memset(xp->array, 0, size * sizeof *xp->array); | |
158 | ||
159 | return 0; | |
160 | } | |
161 | ||
162 | void | |
163 | xpacket_pool_cleanup(struct xpacket_pool *xp) | |
164 | { | |
165 | free_pagealign(xp->array); | |
166 | xp->array = NULL; | |
167 | } |