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 | bool dal_vector_construct( |
30 | struct vector *vector, |
31 | struct dc_context *ctx, |
32 | uint32_t capacity, |
33 | uint32_t struct_size) |
34 | { |
35 | vector->container = NULL; |
36 | |
37 | if (!struct_size || !capacity) { |
38 | /* Container must be non-zero size*/ |
39 | BREAK_TO_DEBUGGER(); |
40 | return false; |
41 | } |
42 | |
43 | vector->container = kcalloc(n: capacity, size: struct_size, GFP_KERNEL); |
44 | if (vector->container == NULL) |
45 | return false; |
46 | vector->capacity = capacity; |
47 | vector->struct_size = struct_size; |
48 | vector->count = 0; |
49 | vector->ctx = ctx; |
50 | return true; |
51 | } |
52 | |
53 | static bool dal_vector_presized_costruct(struct vector *vector, |
54 | struct dc_context *ctx, |
55 | uint32_t count, |
56 | void *initial_value, |
57 | uint32_t struct_size) |
58 | { |
59 | uint32_t i; |
60 | |
61 | vector->container = NULL; |
62 | |
63 | if (!struct_size || !count) { |
64 | /* Container must be non-zero size*/ |
65 | BREAK_TO_DEBUGGER(); |
66 | return false; |
67 | } |
68 | |
69 | vector->container = kcalloc(n: count, size: struct_size, GFP_KERNEL); |
70 | |
71 | if (vector->container == NULL) |
72 | return false; |
73 | |
74 | /* If caller didn't supply initial value then the default |
75 | * of all zeros is expected, which is exactly what dal_alloc() |
76 | * initialises the memory to. */ |
77 | if (NULL != initial_value) { |
78 | for (i = 0; i < count; ++i) |
79 | memmove( |
80 | vector->container + i * struct_size, |
81 | initial_value, |
82 | struct_size); |
83 | } |
84 | |
85 | vector->capacity = count; |
86 | vector->struct_size = struct_size; |
87 | vector->count = count; |
88 | return true; |
89 | } |
90 | |
91 | struct vector *dal_vector_presized_create( |
92 | struct dc_context *ctx, |
93 | uint32_t size, |
94 | void *initial_value, |
95 | uint32_t struct_size) |
96 | { |
97 | struct vector *vector = kzalloc(size: sizeof(struct vector), GFP_KERNEL); |
98 | |
99 | if (vector == NULL) |
100 | return NULL; |
101 | |
102 | if (dal_vector_presized_costruct( |
103 | vector, ctx, count: size, initial_value, struct_size)) |
104 | return vector; |
105 | |
106 | BREAK_TO_DEBUGGER(); |
107 | kfree(objp: vector); |
108 | return NULL; |
109 | } |
110 | |
111 | struct vector *dal_vector_create( |
112 | struct dc_context *ctx, |
113 | uint32_t capacity, |
114 | uint32_t struct_size) |
115 | { |
116 | struct vector *vector = kzalloc(size: sizeof(struct vector), GFP_KERNEL); |
117 | |
118 | if (vector == NULL) |
119 | return NULL; |
120 | |
121 | if (dal_vector_construct(vector, ctx, capacity, struct_size)) |
122 | return vector; |
123 | |
124 | BREAK_TO_DEBUGGER(); |
125 | kfree(objp: vector); |
126 | return NULL; |
127 | } |
128 | |
129 | void dal_vector_destruct( |
130 | struct vector *vector) |
131 | { |
132 | kfree(objp: vector->container); |
133 | vector->count = 0; |
134 | vector->capacity = 0; |
135 | } |
136 | |
137 | void dal_vector_destroy( |
138 | struct vector **vector) |
139 | { |
140 | if (vector == NULL || *vector == NULL) |
141 | return; |
142 | dal_vector_destruct(vector: *vector); |
143 | kfree(objp: *vector); |
144 | *vector = NULL; |
145 | } |
146 | |
147 | uint32_t dal_vector_get_count( |
148 | const struct vector *vector) |
149 | { |
150 | return vector->count; |
151 | } |
152 | |
153 | void *dal_vector_at_index( |
154 | const struct vector *vector, |
155 | uint32_t index) |
156 | { |
157 | if (vector->container == NULL || index >= vector->count) |
158 | return NULL; |
159 | return vector->container + (index * vector->struct_size); |
160 | } |
161 | |
162 | bool dal_vector_remove_at_index( |
163 | struct vector *vector, |
164 | uint32_t index) |
165 | { |
166 | if (index >= vector->count) |
167 | return false; |
168 | |
169 | if (index != vector->count - 1) |
170 | memmove( |
171 | vector->container + (index * vector->struct_size), |
172 | vector->container + ((index + 1) * vector->struct_size), |
173 | (vector->count - index - 1) * vector->struct_size); |
174 | vector->count -= 1; |
175 | |
176 | return true; |
177 | } |
178 | |
179 | void dal_vector_set_at_index( |
180 | const struct vector *vector, |
181 | const void *what, |
182 | uint32_t index) |
183 | { |
184 | void *where = dal_vector_at_index(vector, index); |
185 | |
186 | if (!where) { |
187 | BREAK_TO_DEBUGGER(); |
188 | return; |
189 | } |
190 | memmove( |
191 | where, |
192 | what, |
193 | vector->struct_size); |
194 | } |
195 | |
196 | static inline uint32_t calc_increased_capacity( |
197 | uint32_t old_capacity) |
198 | { |
199 | return old_capacity * 2; |
200 | } |
201 | |
202 | bool dal_vector_insert_at( |
203 | struct vector *vector, |
204 | const void *what, |
205 | uint32_t position) |
206 | { |
207 | uint8_t *insert_address; |
208 | |
209 | if (vector->count == vector->capacity) { |
210 | if (!dal_vector_reserve( |
211 | vector, |
212 | capacity: calc_increased_capacity(old_capacity: vector->capacity))) |
213 | return false; |
214 | } |
215 | |
216 | insert_address = vector->container + (vector->struct_size * position); |
217 | |
218 | if (vector->count && position < vector->count) |
219 | memmove( |
220 | insert_address + vector->struct_size, |
221 | insert_address, |
222 | vector->struct_size * (vector->count - position)); |
223 | |
224 | memmove( |
225 | insert_address, |
226 | what, |
227 | vector->struct_size); |
228 | |
229 | vector->count++; |
230 | |
231 | return true; |
232 | } |
233 | |
234 | bool dal_vector_append( |
235 | struct vector *vector, |
236 | const void *item) |
237 | { |
238 | return dal_vector_insert_at(vector, what: item, position: vector->count); |
239 | } |
240 | |
241 | struct vector *dal_vector_clone( |
242 | const struct vector *vector) |
243 | { |
244 | struct vector *vec_cloned; |
245 | uint32_t count; |
246 | |
247 | /* create new vector */ |
248 | count = dal_vector_get_count(vector); |
249 | |
250 | if (count == 0) |
251 | /* when count is 0 we still want to create clone of the vector |
252 | */ |
253 | vec_cloned = dal_vector_create( |
254 | ctx: vector->ctx, |
255 | capacity: vector->capacity, |
256 | struct_size: vector->struct_size); |
257 | else |
258 | /* Call "presized create" version, independently of how the |
259 | * original vector was created. |
260 | * The owner of original vector must know how to treat the new |
261 | * vector - as "presized" or as "regular". |
262 | * But from vector point of view it doesn't matter. */ |
263 | vec_cloned = dal_vector_presized_create(ctx: vector->ctx, size: count, |
264 | NULL,/* no initial value */ |
265 | struct_size: vector->struct_size); |
266 | |
267 | if (NULL == vec_cloned) { |
268 | BREAK_TO_DEBUGGER(); |
269 | return NULL; |
270 | } |
271 | |
272 | /* copy vector's data */ |
273 | memmove(vec_cloned->container, vector->container, |
274 | vec_cloned->struct_size * vec_cloned->capacity); |
275 | |
276 | return vec_cloned; |
277 | } |
278 | |
279 | uint32_t dal_vector_capacity(const struct vector *vector) |
280 | { |
281 | return vector->capacity; |
282 | } |
283 | |
284 | bool dal_vector_reserve(struct vector *vector, uint32_t capacity) |
285 | { |
286 | void *new_container; |
287 | |
288 | if (capacity <= vector->capacity) |
289 | return true; |
290 | |
291 | new_container = krealloc(objp: vector->container, |
292 | new_size: capacity * vector->struct_size, GFP_KERNEL); |
293 | |
294 | if (new_container) { |
295 | vector->container = new_container; |
296 | vector->capacity = capacity; |
297 | return true; |
298 | } |
299 | |
300 | return false; |
301 | } |
302 | |
303 | void dal_vector_clear(struct vector *vector) |
304 | { |
305 | vector->count = 0; |
306 | } |
307 | |