Line data Source code
1 : /*
2 : * Copyright 2012-15 Advanced Micro Devices, Inc.
3 : *
4 : * Permission is hereby granted, free of charge, to any person obtaining a
5 : * copy of this software and associated documentation files (the "Software"),
6 : * to deal in the Software without restriction, including without limitation
7 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 : * and/or sell copies of the Software, and to permit persons to whom the
9 : * Software is furnished to do so, subject to the following conditions:
10 : *
11 : * The above copyright notice and this permission notice shall be included in
12 : * all copies or substantial portions of the Software.
13 : *
14 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 : * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 : * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 : * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 : * OTHER DEALINGS IN THE SOFTWARE.
21 : *
22 : * Authors: AMD
23 : *
24 : */
25 :
26 : #include "dm_services.h"
27 : #include "include/vector.h"
28 :
29 0 : bool dal_vector_construct(
30 : struct vector *vector,
31 : struct dc_context *ctx,
32 : uint32_t capacity,
33 : uint32_t struct_size)
34 : {
35 0 : vector->container = NULL;
36 :
37 0 : if (!struct_size || !capacity) {
38 : /* Container must be non-zero size*/
39 0 : BREAK_TO_DEBUGGER();
40 0 : return false;
41 : }
42 :
43 0 : vector->container = kcalloc(capacity, struct_size, GFP_KERNEL);
44 0 : if (vector->container == NULL)
45 : return false;
46 0 : vector->capacity = capacity;
47 0 : vector->struct_size = struct_size;
48 0 : vector->count = 0;
49 0 : vector->ctx = ctx;
50 0 : return true;
51 : }
52 :
53 0 : static bool dal_vector_presized_costruct(
54 : struct vector *vector,
55 : struct dc_context *ctx,
56 : uint32_t count,
57 : void *initial_value,
58 : uint32_t struct_size)
59 : {
60 : uint32_t i;
61 :
62 0 : vector->container = NULL;
63 :
64 0 : if (!struct_size || !count) {
65 : /* Container must be non-zero size*/
66 0 : BREAK_TO_DEBUGGER();
67 : return false;
68 : }
69 :
70 0 : vector->container = kcalloc(count, struct_size, GFP_KERNEL);
71 :
72 0 : if (vector->container == NULL)
73 : return false;
74 :
75 : /* If caller didn't supply initial value then the default
76 : * of all zeros is expected, which is exactly what dal_alloc()
77 : * initialises the memory to. */
78 0 : if (NULL != initial_value) {
79 0 : for (i = 0; i < count; ++i)
80 0 : memmove(
81 0 : vector->container + i * struct_size,
82 : initial_value,
83 : struct_size);
84 : }
85 :
86 0 : vector->capacity = count;
87 0 : vector->struct_size = struct_size;
88 0 : vector->count = count;
89 : return true;
90 : }
91 :
92 0 : struct vector *dal_vector_presized_create(
93 : struct dc_context *ctx,
94 : uint32_t size,
95 : void *initial_value,
96 : uint32_t struct_size)
97 : {
98 0 : struct vector *vector = kzalloc(sizeof(struct vector), GFP_KERNEL);
99 :
100 0 : if (vector == NULL)
101 : return NULL;
102 :
103 0 : if (dal_vector_presized_costruct(
104 : vector, ctx, size, initial_value, struct_size))
105 : return vector;
106 :
107 0 : BREAK_TO_DEBUGGER();
108 0 : kfree(vector);
109 0 : return NULL;
110 : }
111 :
112 0 : struct vector *dal_vector_create(
113 : struct dc_context *ctx,
114 : uint32_t capacity,
115 : uint32_t struct_size)
116 : {
117 0 : struct vector *vector = kzalloc(sizeof(struct vector), GFP_KERNEL);
118 :
119 0 : if (vector == NULL)
120 : return NULL;
121 :
122 0 : if (dal_vector_construct(vector, ctx, capacity, struct_size))
123 : return vector;
124 :
125 0 : BREAK_TO_DEBUGGER();
126 0 : kfree(vector);
127 0 : return NULL;
128 : }
129 :
130 0 : void dal_vector_destruct(
131 : struct vector *vector)
132 : {
133 0 : kfree(vector->container);
134 0 : vector->count = 0;
135 0 : vector->capacity = 0;
136 0 : }
137 :
138 0 : void dal_vector_destroy(
139 : struct vector **vector)
140 : {
141 0 : if (vector == NULL || *vector == NULL)
142 : return;
143 0 : dal_vector_destruct(*vector);
144 0 : kfree(*vector);
145 0 : *vector = NULL;
146 : }
147 :
148 0 : uint32_t dal_vector_get_count(
149 : const struct vector *vector)
150 : {
151 0 : return vector->count;
152 : }
153 :
154 0 : void *dal_vector_at_index(
155 : const struct vector *vector,
156 : uint32_t index)
157 : {
158 0 : if (vector->container == NULL || index >= vector->count)
159 : return NULL;
160 0 : return vector->container + (index * vector->struct_size);
161 : }
162 :
163 0 : bool dal_vector_remove_at_index(
164 : struct vector *vector,
165 : uint32_t index)
166 : {
167 0 : if (index >= vector->count)
168 : return false;
169 :
170 0 : if (index != vector->count - 1)
171 0 : memmove(
172 0 : vector->container + (index * vector->struct_size),
173 0 : vector->container + ((index + 1) * vector->struct_size),
174 0 : (vector->count - index - 1) * vector->struct_size);
175 0 : vector->count -= 1;
176 :
177 0 : return true;
178 : }
179 :
180 0 : void dal_vector_set_at_index(
181 : const struct vector *vector,
182 : const void *what,
183 : uint32_t index)
184 : {
185 0 : void *where = dal_vector_at_index(vector, index);
186 :
187 0 : if (!where) {
188 0 : BREAK_TO_DEBUGGER();
189 0 : return;
190 : }
191 0 : memmove(
192 : where,
193 : what,
194 0 : vector->struct_size);
195 : }
196 :
197 : static inline uint32_t calc_increased_capacity(
198 : uint32_t old_capacity)
199 : {
200 0 : return old_capacity * 2;
201 : }
202 :
203 0 : bool dal_vector_insert_at(
204 : struct vector *vector,
205 : const void *what,
206 : uint32_t position)
207 : {
208 : uint8_t *insert_address;
209 :
210 0 : if (vector->count == vector->capacity) {
211 0 : if (!dal_vector_reserve(
212 : vector,
213 : calc_increased_capacity(vector->capacity)))
214 : return false;
215 : }
216 :
217 0 : insert_address = vector->container + (vector->struct_size * position);
218 :
219 0 : if (vector->count && position < vector->count)
220 0 : memmove(
221 0 : insert_address + vector->struct_size,
222 : insert_address,
223 0 : vector->struct_size * (vector->count - position));
224 :
225 0 : memmove(
226 : insert_address,
227 : what,
228 0 : vector->struct_size);
229 :
230 0 : vector->count++;
231 :
232 0 : return true;
233 : }
234 :
235 0 : bool dal_vector_append(
236 : struct vector *vector,
237 : const void *item)
238 : {
239 0 : return dal_vector_insert_at(vector, item, vector->count);
240 : }
241 :
242 0 : struct vector *dal_vector_clone(
243 : const struct vector *vector)
244 : {
245 : struct vector *vec_cloned;
246 : uint32_t count;
247 :
248 : /* create new vector */
249 0 : count = dal_vector_get_count(vector);
250 :
251 0 : if (count == 0)
252 : /* when count is 0 we still want to create clone of the vector
253 : */
254 0 : vec_cloned = dal_vector_create(
255 : vector->ctx,
256 : vector->capacity,
257 : vector->struct_size);
258 : else
259 : /* Call "presized create" version, independently of how the
260 : * original vector was created.
261 : * The owner of original vector must know how to treat the new
262 : * vector - as "presized" or as "regular".
263 : * But from vector point of view it doesn't matter. */
264 0 : vec_cloned = dal_vector_presized_create(vector->ctx, count,
265 : NULL,/* no initial value */
266 : vector->struct_size);
267 :
268 0 : if (NULL == vec_cloned) {
269 0 : BREAK_TO_DEBUGGER();
270 0 : return NULL;
271 : }
272 :
273 : /* copy vector's data */
274 0 : memmove(vec_cloned->container, vector->container,
275 0 : vec_cloned->struct_size * vec_cloned->capacity);
276 :
277 0 : return vec_cloned;
278 : }
279 :
280 0 : uint32_t dal_vector_capacity(const struct vector *vector)
281 : {
282 0 : return vector->capacity;
283 : }
284 :
285 0 : bool dal_vector_reserve(struct vector *vector, uint32_t capacity)
286 : {
287 : void *new_container;
288 :
289 0 : if (capacity <= vector->capacity)
290 : return true;
291 :
292 0 : new_container = krealloc(vector->container,
293 0 : capacity * vector->struct_size, GFP_KERNEL);
294 :
295 0 : if (new_container) {
296 0 : vector->container = new_container;
297 0 : vector->capacity = capacity;
298 0 : return true;
299 : }
300 :
301 : return false;
302 : }
303 :
304 0 : void dal_vector_clear(struct vector *vector)
305 : {
306 0 : vector->count = 0;
307 0 : }
|