Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2019 Intel Corporation
3 : : */
4 : :
5 : : #include <stdint.h>
6 : : #include <stddef.h>
7 : : #include <stdio.h>
8 : : #include <string.h>
9 : : #include <sys/queue.h>
10 : :
11 : : #include <rte_errno.h>
12 : : #include <rte_memcpy.h>
13 : : #include <rte_memory.h>
14 : : #include <rte_eal.h>
15 : : #include <rte_eal_memconfig.h>
16 : : #include <rte_common.h>
17 : : #include <rte_spinlock.h>
18 : :
19 : : #include <eal_trace_internal.h>
20 : :
21 : : #include <rte_malloc.h>
22 : : #include "malloc_elem.h"
23 : : #include "malloc_heap.h"
24 : : #include "eal_memalloc.h"
25 : : #include "eal_memcfg.h"
26 : : #include "eal_private.h"
27 : :
28 : :
29 : : /* Free the memory space back to heap */
30 : : static void
31 : 109717 : mem_free(void *addr, const bool trace_ena)
32 : : {
33 [ + + ]: 109717 : if (trace_ena)
34 : 109714 : rte_eal_trace_mem_free(addr);
35 : :
36 [ + + ]: 109717 : if (addr == NULL) return;
37 [ - + ]: 109115 : if (malloc_heap_free(malloc_elem_from_data(addr)) < 0)
38 : 0 : EAL_LOG(ERR, "Error: Invalid memory");
39 : : }
40 : :
41 : : void
42 : 109714 : rte_free(void *addr)
43 : : {
44 : 109714 : mem_free(addr, true);
45 : 109714 : }
46 : :
47 : : void
48 : 3 : eal_free_no_trace(void *addr)
49 : : {
50 : 3 : mem_free(addr, false);
51 : 3 : }
52 : :
53 : : static void *
54 : 111605 : malloc_socket(const char *type, size_t size, unsigned int align,
55 : : int socket_arg, const bool trace_ena)
56 : : {
57 : : void *ptr;
58 : :
59 : : /* return NULL if size is 0 or alignment is not power-of-2 */
60 [ + + + + ]: 111605 : if (size == 0 || (align && !rte_is_power_of_2(align)))
61 : : return NULL;
62 : :
63 : : /* if there are no hugepages and if we are not allocating from an
64 : : * external heap, use memory from any socket available. checking for
65 : : * socket being external may return -1 in case of invalid socket, but
66 : : * that's OK - if there are no hugepages, it doesn't matter.
67 : : */
68 [ + + + + ]: 223188 : if (rte_malloc_heap_socket_is_external(socket_arg) != 1 &&
69 : 111589 : !rte_eal_has_hugepages())
70 : : socket_arg = SOCKET_ID_ANY;
71 : :
72 : 111597 : ptr = malloc_heap_alloc(size, socket_arg, 0,
73 : : align == 0 ? 1 : align, 0, false);
74 : :
75 [ + + ]: 111602 : if (trace_ena)
76 : 111597 : rte_eal_trace_mem_malloc(type, size, align, socket_arg, ptr);
77 : : return ptr;
78 : : }
79 : :
80 : : /*
81 : : * Allocate memory on specified heap.
82 : : */
83 : : void *
84 : 111600 : rte_malloc_socket(const char *type, size_t size, unsigned int align,
85 : : int socket_arg)
86 : : {
87 : 111600 : return malloc_socket(type, size, align, socket_arg, true);
88 : : }
89 : :
90 : : void *
91 : 5 : eal_malloc_no_trace(const char *type, size_t size, unsigned int align)
92 : : {
93 : 5 : return malloc_socket(type, size, align, SOCKET_ID_ANY, false);
94 : : }
95 : :
96 : : /*
97 : : * Allocate memory on default heap.
98 : : */
99 : : void *
100 : 71088 : rte_malloc(const char *type, size_t size, unsigned align)
101 : : {
102 : 71088 : return rte_malloc_socket(type, size, align, SOCKET_ID_ANY);
103 : : }
104 : :
105 : : /*
106 : : * Allocate zero'd memory on specified heap.
107 : : */
108 : : void *
109 : 40387 : rte_zmalloc_socket(const char *type, size_t size, unsigned align, int socket)
110 : : {
111 : 40387 : void *ptr = rte_malloc_socket(type, size, align, socket);
112 : :
113 [ + + ]: 40388 : if (ptr != NULL) {
114 : : struct malloc_elem *elem = malloc_elem_from_data(ptr);
115 : :
116 [ - + ]: 40358 : if (elem->dirty) {
117 : : memset(ptr, 0, size);
118 : : } else {
119 : : #ifdef RTE_MALLOC_DEBUG
120 : : /*
121 : : * If DEBUG is enabled, then freed memory is marked
122 : : * with a poison value and set to zero on allocation.
123 : : * If DEBUG is disabled then memory is already zeroed.
124 : : */
125 : : memset(ptr, 0, size);
126 : : #endif
127 : : }
128 : : }
129 : :
130 : 40388 : rte_eal_trace_mem_zmalloc(type, size, align, socket, ptr);
131 : 40388 : return ptr;
132 : : }
133 : :
134 : : /*
135 : : * Allocate zero'd memory on default heap.
136 : : */
137 : : void *
138 : 34780 : rte_zmalloc(const char *type, size_t size, unsigned align)
139 : : {
140 : 34780 : return rte_zmalloc_socket(type, size, align, SOCKET_ID_ANY);
141 : : }
142 : :
143 : : /*
144 : : * Allocate zero'd memory on specified heap.
145 : : */
146 : : void *
147 : 59 : rte_calloc_socket(const char *type, size_t num, size_t size, unsigned align, int socket)
148 : : {
149 : 59 : return rte_zmalloc_socket(type, num * size, align, socket);
150 : : }
151 : :
152 : : /*
153 : : * Allocate zero'd memory on default heap.
154 : : */
155 : : void *
156 : 217 : rte_calloc(const char *type, size_t num, size_t size, unsigned align)
157 : : {
158 : 217 : return rte_zmalloc(type, num * size, align);
159 : : }
160 : :
161 : : /*
162 : : * Resize allocated memory on specified heap.
163 : : */
164 : : void *
165 : 74 : rte_realloc_socket(void *ptr, size_t size, unsigned int align, int socket)
166 : : {
167 : : size_t user_size;
168 : :
169 [ + + ]: 74 : if (ptr == NULL)
170 : 55 : return rte_malloc_socket(NULL, size, align, socket);
171 : :
172 : : struct malloc_elem *elem = malloc_elem_from_data(ptr);
173 [ - + ]: 19 : if (elem == NULL) {
174 : 0 : EAL_LOG(ERR, "Error: memory corruption detected");
175 : 0 : return NULL;
176 : : }
177 : :
178 : : user_size = size;
179 : :
180 : 19 : size = RTE_CACHE_LINE_ROUNDUP(size), align = RTE_CACHE_LINE_ROUNDUP(align);
181 : :
182 : : /* check requested socket id and alignment matches first, and if ok,
183 : : * see if we can resize block
184 : : */
185 [ + + ]: 19 : if ((socket == SOCKET_ID_ANY ||
186 [ + + ]: 9 : (unsigned int)socket == elem->heap->socket_id) &&
187 [ + + + + ]: 35 : RTE_PTR_ALIGN(ptr, align) == ptr &&
188 : 17 : malloc_heap_resize(elem, size) == 0) {
189 : 3 : rte_eal_trace_mem_realloc(size, align, socket, ptr);
190 : :
191 : : asan_set_redzone(elem, user_size);
192 : :
193 : 3 : return ptr;
194 : : }
195 : :
196 : : /* either requested socket id doesn't match, alignment is off
197 : : * or we have no room to expand,
198 : : * so move the data.
199 : : */
200 : 16 : void *new_ptr = rte_malloc_socket(NULL, size, align, socket);
201 [ + - ]: 16 : if (new_ptr == NULL)
202 : : return NULL;
203 : : /* elem: |pad|data_elem|data|trailer| */
204 : : const size_t old_size = old_malloc_size(elem);
205 [ + - ]: 16 : rte_memcpy(new_ptr, ptr, old_size < size ? old_size : size);
206 : 16 : rte_free(ptr);
207 : :
208 : 16 : rte_eal_trace_mem_realloc(size, align, socket, new_ptr);
209 : 16 : return new_ptr;
210 : : }
211 : :
212 : : /*
213 : : * Resize allocated memory.
214 : : */
215 : : void *
216 : 3 : rte_realloc(void *ptr, size_t size, unsigned int align)
217 : : {
218 : 3 : return rte_realloc_socket(ptr, size, align, SOCKET_ID_ANY);
219 : : }
220 : :
221 : : int
222 [ + + ]: 101862 : rte_malloc_validate(const void *ptr, size_t *size)
223 : : {
224 : : const struct malloc_elem *elem = malloc_elem_from_data(ptr);
225 [ + - ]: 101861 : if (!malloc_elem_cookies_ok(elem))
226 : : return -1;
227 [ + + ]: 101861 : if (size != NULL)
228 : 50932 : *size = elem->size - elem->pad - MALLOC_ELEM_OVERHEAD;
229 : : return 0;
230 : : }
231 : :
232 : : /*
233 : : * Function to retrieve data for heap on given socket
234 : : */
235 : : int
236 : 14 : rte_malloc_get_socket_stats(int socket,
237 : : struct rte_malloc_socket_stats *socket_stats)
238 : : {
239 : 14 : struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
240 : : int heap_idx;
241 : :
242 : 14 : heap_idx = malloc_socket_to_heap_id(socket);
243 [ + - ]: 14 : if (heap_idx < 0)
244 : : return -1;
245 : :
246 : 14 : return malloc_heap_get_stats(&mcfg->malloc_heaps[heap_idx],
247 : : socket_stats);
248 : : }
249 : :
250 : : /*
251 : : * Function to dump contents of all heaps
252 : : */
253 : : void
254 : 0 : rte_malloc_dump_heaps(FILE *f)
255 : : {
256 : 0 : struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
257 : : unsigned int idx;
258 : :
259 [ # # ]: 0 : for (idx = 0; idx < RTE_MAX_HEAPS; idx++) {
260 : : fprintf(f, "Heap id: %u\n", idx);
261 : 0 : malloc_heap_dump(&mcfg->malloc_heaps[idx], f);
262 : : }
263 : 0 : }
264 : :
265 : : int
266 : 1 : rte_malloc_heap_get_socket(const char *name)
267 : : {
268 : 1 : struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
269 : : struct malloc_heap *heap = NULL;
270 : : unsigned int idx;
271 : : int ret;
272 : :
273 [ + - ]: 1 : if (name == NULL ||
274 [ + - - + ]: 1 : strnlen(name, RTE_HEAP_NAME_MAX_LEN) == 0 ||
275 : : strnlen(name, RTE_HEAP_NAME_MAX_LEN) ==
276 : : RTE_HEAP_NAME_MAX_LEN) {
277 : 0 : rte_errno = EINVAL;
278 : 0 : return -1;
279 : : }
280 : 1 : rte_mcfg_mem_read_lock();
281 [ + - ]: 3 : for (idx = 0; idx < RTE_MAX_HEAPS; idx++) {
282 : 3 : struct malloc_heap *tmp = &mcfg->malloc_heaps[idx];
283 : :
284 [ + + ]: 3 : if (!strncmp(name, tmp->name, RTE_HEAP_NAME_MAX_LEN)) {
285 : : heap = tmp;
286 : : break;
287 : : }
288 : : }
289 : :
290 [ + - ]: 1 : if (heap != NULL) {
291 : 1 : ret = heap->socket_id;
292 : : } else {
293 : 0 : rte_errno = ENOENT;
294 : : ret = -1;
295 : : }
296 : 1 : rte_mcfg_mem_read_unlock();
297 : :
298 : 1 : return ret;
299 : : }
300 : :
301 : : int
302 : 112902 : rte_malloc_heap_socket_is_external(int socket_id)
303 : : {
304 : 112902 : struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
305 : : unsigned int idx;
306 : : int ret = -1;
307 : :
308 [ + + ]: 112900 : if (socket_id == SOCKET_ID_ANY)
309 : : return 0;
310 : :
311 : 4941 : rte_mcfg_mem_read_lock();
312 [ + + ]: 5926 : for (idx = 0; idx < RTE_MAX_HEAPS; idx++) {
313 : : struct malloc_heap *tmp = &mcfg->malloc_heaps[idx];
314 : :
315 [ + + ]: 5896 : if ((int)tmp->socket_id == socket_id) {
316 : : /* external memory always has large socket ID's */
317 : 4911 : ret = tmp->socket_id >= RTE_MAX_NUMA_NODES;
318 : 4911 : break;
319 : : }
320 : : }
321 : 4941 : rte_mcfg_mem_read_unlock();
322 : :
323 : 4941 : return ret;
324 : : }
325 : :
326 : : /*
327 : : * Print stats on memory type. If type is NULL, info on all types is printed
328 : : */
329 : : void
330 : 3 : rte_malloc_dump_stats(FILE *f, __rte_unused const char *type)
331 : : {
332 : 3 : struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
333 : : unsigned int heap_id;
334 : : struct rte_malloc_socket_stats sock_stats;
335 : :
336 : : /* Iterate through all initialised heaps */
337 [ + + ]: 99 : for (heap_id = 0; heap_id < RTE_MAX_HEAPS; heap_id++) {
338 : 96 : struct malloc_heap *heap = &mcfg->malloc_heaps[heap_id];
339 : :
340 : 96 : malloc_heap_get_stats(heap, &sock_stats);
341 : :
342 : : fprintf(f, "Heap id:%u\n", heap_id);
343 : 96 : fprintf(f, "\tHeap name:%s\n", heap->name);
344 : 96 : fprintf(f, "\tHeap_size:%zu,\n", sock_stats.heap_totalsz_bytes);
345 : 96 : fprintf(f, "\tFree_size:%zu,\n", sock_stats.heap_freesz_bytes);
346 : 96 : fprintf(f, "\tAlloc_size:%zu,\n", sock_stats.heap_allocsz_bytes);
347 : 96 : fprintf(f, "\tGreatest_free_size:%zu,\n",
348 : : sock_stats.greatest_free_size);
349 : 96 : fprintf(f, "\tAlloc_count:%u,\n",sock_stats.alloc_count);
350 : 96 : fprintf(f, "\tFree_count:%u,\n", sock_stats.free_count);
351 : : }
352 : 3 : return;
353 : : }
354 : :
355 : : /*
356 : : * Return the IO address of a virtual address obtained through rte_malloc
357 : : */
358 : : rte_iova_t
359 [ + - ]: 6050 : rte_malloc_virt2iova(const void *addr)
360 : : {
361 : : const struct rte_memseg *ms;
362 : : struct malloc_elem *elem = malloc_elem_from_data(addr);
363 : :
364 [ + - ]: 6050 : if (elem == NULL)
365 : : return RTE_BAD_IOVA;
366 : :
367 [ + - + + ]: 6050 : if (!elem->msl->external && rte_eal_iova_mode() == RTE_IOVA_VA)
368 : : return (uintptr_t) addr;
369 : :
370 : 5121 : ms = rte_mem_virt2memseg(addr, elem->msl);
371 [ + - ]: 5121 : if (ms == NULL)
372 : : return RTE_BAD_IOVA;
373 : :
374 [ + - ]: 5121 : if (ms->iova == RTE_BAD_IOVA)
375 : : return RTE_BAD_IOVA;
376 : :
377 : 5121 : return ms->iova + RTE_PTR_DIFF(addr, ms->addr);
378 : : }
379 : :
380 : : static struct malloc_heap *
381 : 3 : find_named_heap(const char *name)
382 : : {
383 : 3 : struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
384 : : unsigned int i;
385 : :
386 [ + - ]: 9 : for (i = 0; i < RTE_MAX_HEAPS; i++) {
387 : 9 : struct malloc_heap *heap = &mcfg->malloc_heaps[i];
388 : :
389 [ + + ]: 9 : if (!strncmp(name, heap->name, RTE_HEAP_NAME_MAX_LEN))
390 : 3 : return heap;
391 : : }
392 : : return NULL;
393 : : }
394 : :
395 : : int
396 : 1 : rte_malloc_heap_memory_add(const char *heap_name, void *va_addr, size_t len,
397 : : rte_iova_t iova_addrs[], unsigned int n_pages, size_t page_sz)
398 : : {
399 : : struct malloc_heap *heap = NULL;
400 : : struct rte_memseg_list *msl;
401 : : unsigned int n;
402 : : int ret;
403 : :
404 [ + - + - ]: 1 : if (heap_name == NULL || va_addr == NULL ||
405 [ + - ]: 1 : page_sz == 0 || !rte_is_power_of_2(page_sz) ||
406 [ + - + - ]: 1 : RTE_ALIGN(len, page_sz) != len ||
407 : 1 : !rte_is_aligned(va_addr, page_sz) ||
408 [ + - + - ]: 1 : ((len / page_sz) != n_pages && iova_addrs != NULL) ||
409 [ + - - + ]: 1 : strnlen(heap_name, RTE_HEAP_NAME_MAX_LEN) == 0 ||
410 : : strnlen(heap_name, RTE_HEAP_NAME_MAX_LEN) ==
411 : : RTE_HEAP_NAME_MAX_LEN) {
412 : 0 : rte_errno = EINVAL;
413 : 0 : return -1;
414 : : }
415 : 1 : rte_mcfg_mem_write_lock();
416 : :
417 : : /* find our heap */
418 : 1 : heap = find_named_heap(heap_name);
419 [ - + ]: 1 : if (heap == NULL) {
420 : 0 : rte_errno = ENOENT;
421 : : ret = -1;
422 : 0 : goto unlock;
423 : : }
424 [ - + ]: 1 : if (heap->socket_id < RTE_MAX_NUMA_NODES) {
425 : : /* cannot add memory to internal heaps */
426 : 0 : rte_errno = EPERM;
427 : : ret = -1;
428 : 0 : goto unlock;
429 : : }
430 : 1 : n = len / page_sz;
431 : :
432 : 1 : msl = malloc_heap_create_external_seg(va_addr, iova_addrs, n, page_sz,
433 : : heap_name, heap->socket_id);
434 [ - + ]: 1 : if (msl == NULL) {
435 : : ret = -1;
436 : 0 : goto unlock;
437 : : }
438 : :
439 : 1 : rte_spinlock_lock(&heap->lock);
440 : 1 : ret = malloc_heap_add_external_memory(heap, msl);
441 : 1 : msl->heap = 1; /* mark it as heap segment */
442 : : rte_spinlock_unlock(&heap->lock);
443 : :
444 : 1 : unlock:
445 : 1 : rte_mcfg_mem_write_unlock();
446 : :
447 : 1 : return ret;
448 : : }
449 : :
450 : : int
451 : 1 : rte_malloc_heap_memory_remove(const char *heap_name, void *va_addr, size_t len)
452 : : {
453 : : struct malloc_heap *heap = NULL;
454 : : struct rte_memseg_list *msl;
455 : : int ret;
456 : :
457 [ + - + - ]: 1 : if (heap_name == NULL || va_addr == NULL || len == 0 ||
458 [ + - - + ]: 1 : strnlen(heap_name, RTE_HEAP_NAME_MAX_LEN) == 0 ||
459 : : strnlen(heap_name, RTE_HEAP_NAME_MAX_LEN) ==
460 : : RTE_HEAP_NAME_MAX_LEN) {
461 : 0 : rte_errno = EINVAL;
462 : 0 : return -1;
463 : : }
464 : 1 : rte_mcfg_mem_write_lock();
465 : : /* find our heap */
466 : 1 : heap = find_named_heap(heap_name);
467 [ - + ]: 1 : if (heap == NULL) {
468 : 0 : rte_errno = ENOENT;
469 : : ret = -1;
470 : 0 : goto unlock;
471 : : }
472 [ - + ]: 1 : if (heap->socket_id < RTE_MAX_NUMA_NODES) {
473 : : /* cannot remove memory from internal heaps */
474 : 0 : rte_errno = EPERM;
475 : : ret = -1;
476 : 0 : goto unlock;
477 : : }
478 : :
479 : 1 : msl = malloc_heap_find_external_seg(va_addr, len);
480 [ - + ]: 1 : if (msl == NULL) {
481 : : ret = -1;
482 : 0 : goto unlock;
483 : : }
484 : :
485 : 1 : rte_spinlock_lock(&heap->lock);
486 : 1 : ret = malloc_heap_remove_external_memory(heap, va_addr, len);
487 : : rte_spinlock_unlock(&heap->lock);
488 [ - + ]: 1 : if (ret != 0)
489 : 0 : goto unlock;
490 : :
491 : 1 : ret = malloc_heap_destroy_external_seg(msl);
492 : :
493 : 1 : unlock:
494 : 1 : rte_mcfg_mem_write_unlock();
495 : :
496 : 1 : return ret;
497 : : }
498 : :
499 : : static int
500 : 0 : sync_memory(const char *heap_name, void *va_addr, size_t len, bool attach)
501 : : {
502 : : struct malloc_heap *heap = NULL;
503 : : struct rte_memseg_list *msl;
504 : : int ret;
505 : :
506 [ # # # # ]: 0 : if (heap_name == NULL || va_addr == NULL || len == 0 ||
507 [ # # # # ]: 0 : strnlen(heap_name, RTE_HEAP_NAME_MAX_LEN) == 0 ||
508 : : strnlen(heap_name, RTE_HEAP_NAME_MAX_LEN) ==
509 : : RTE_HEAP_NAME_MAX_LEN) {
510 : 0 : rte_errno = EINVAL;
511 : 0 : return -1;
512 : : }
513 : 0 : rte_mcfg_mem_read_lock();
514 : :
515 : : /* find our heap */
516 : 0 : heap = find_named_heap(heap_name);
517 [ # # ]: 0 : if (heap == NULL) {
518 : 0 : rte_errno = ENOENT;
519 : : ret = -1;
520 : 0 : goto unlock;
521 : : }
522 : : /* we shouldn't be able to sync to internal heaps */
523 [ # # ]: 0 : if (heap->socket_id < RTE_MAX_NUMA_NODES) {
524 : 0 : rte_errno = EPERM;
525 : : ret = -1;
526 : 0 : goto unlock;
527 : : }
528 : :
529 : : /* find corresponding memseg list to sync to */
530 : 0 : msl = malloc_heap_find_external_seg(va_addr, len);
531 [ # # ]: 0 : if (msl == NULL) {
532 : : ret = -1;
533 : 0 : goto unlock;
534 : : }
535 : :
536 [ # # ]: 0 : if (attach) {
537 : 0 : ret = rte_fbarray_attach(&msl->memseg_arr);
538 [ # # ]: 0 : if (ret == 0) {
539 : : /* notify all subscribers that a new memory area was
540 : : * added.
541 : : */
542 : 0 : eal_memalloc_mem_event_notify(RTE_MEM_EVENT_ALLOC,
543 : : va_addr, len);
544 : : } else {
545 : : ret = -1;
546 : 0 : goto unlock;
547 : : }
548 : : } else {
549 : : /* notify all subscribers that a memory area is about to
550 : : * be removed.
551 : : */
552 : 0 : eal_memalloc_mem_event_notify(RTE_MEM_EVENT_FREE,
553 : 0 : msl->base_va, msl->len);
554 : 0 : ret = rte_fbarray_detach(&msl->memseg_arr);
555 : : if (ret < 0) {
556 : : ret = -1;
557 : : goto unlock;
558 : : }
559 : : }
560 : 0 : unlock:
561 : 0 : rte_mcfg_mem_read_unlock();
562 : 0 : return ret;
563 : : }
564 : :
565 : : int
566 : 0 : rte_malloc_heap_memory_attach(const char *heap_name, void *va_addr, size_t len)
567 : : {
568 : 0 : return sync_memory(heap_name, va_addr, len, true);
569 : : }
570 : :
571 : : int
572 : 0 : rte_malloc_heap_memory_detach(const char *heap_name, void *va_addr, size_t len)
573 : : {
574 : 0 : return sync_memory(heap_name, va_addr, len, false);
575 : : }
576 : :
577 : : int
578 : 1 : rte_malloc_heap_create(const char *heap_name)
579 : : {
580 : 1 : struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
581 : : struct malloc_heap *heap = NULL;
582 : : int i, ret;
583 : :
584 [ + - ]: 1 : if (heap_name == NULL ||
585 [ + - - + ]: 1 : strnlen(heap_name, RTE_HEAP_NAME_MAX_LEN) == 0 ||
586 : : strnlen(heap_name, RTE_HEAP_NAME_MAX_LEN) ==
587 : : RTE_HEAP_NAME_MAX_LEN) {
588 : 0 : rte_errno = EINVAL;
589 : 0 : return -1;
590 : : }
591 : : /* check if there is space in the heap list, or if heap with this name
592 : : * already exists.
593 : : */
594 : 1 : rte_mcfg_mem_write_lock();
595 : :
596 [ + - ]: 3 : for (i = 0; i < RTE_MAX_HEAPS; i++) {
597 : 3 : struct malloc_heap *tmp = &mcfg->malloc_heaps[i];
598 : : /* existing heap */
599 [ - + ]: 3 : if (strncmp(heap_name, tmp->name,
600 : : RTE_HEAP_NAME_MAX_LEN) == 0) {
601 : 0 : EAL_LOG(ERR, "Heap %s already exists",
602 : : heap_name);
603 : 0 : rte_errno = EEXIST;
604 : : ret = -1;
605 : 0 : goto unlock;
606 : : }
607 : : /* empty heap */
608 [ + + ]: 3 : if (strnlen(tmp->name, RTE_HEAP_NAME_MAX_LEN) == 0) {
609 : : heap = tmp;
610 : : break;
611 : : }
612 : : }
613 [ - + ]: 1 : if (heap == NULL) {
614 : 0 : EAL_LOG(ERR, "Cannot create new heap: no space");
615 : 0 : rte_errno = ENOSPC;
616 : : ret = -1;
617 : 0 : goto unlock;
618 : : }
619 : :
620 : : /* we're sure that we can create a new heap, so do it */
621 : 1 : ret = malloc_heap_create(heap, heap_name);
622 : 1 : unlock:
623 : 1 : rte_mcfg_mem_write_unlock();
624 : :
625 : 1 : return ret;
626 : : }
627 : :
628 : : int
629 : 1 : rte_malloc_heap_destroy(const char *heap_name)
630 : : {
631 : : struct malloc_heap *heap = NULL;
632 : : int ret;
633 : :
634 [ + - ]: 1 : if (heap_name == NULL ||
635 [ + - - + ]: 1 : strnlen(heap_name, RTE_HEAP_NAME_MAX_LEN) == 0 ||
636 : : strnlen(heap_name, RTE_HEAP_NAME_MAX_LEN) ==
637 : : RTE_HEAP_NAME_MAX_LEN) {
638 : 0 : rte_errno = EINVAL;
639 : 0 : return -1;
640 : : }
641 : 1 : rte_mcfg_mem_write_lock();
642 : :
643 : : /* start from non-socket heaps */
644 : 1 : heap = find_named_heap(heap_name);
645 [ - + ]: 1 : if (heap == NULL) {
646 : 0 : EAL_LOG(ERR, "Heap %s not found", heap_name);
647 : 0 : rte_errno = ENOENT;
648 : : ret = -1;
649 : 0 : goto unlock;
650 : : }
651 : : /* we shouldn't be able to destroy internal heaps */
652 [ - + ]: 1 : if (heap->socket_id < RTE_MAX_NUMA_NODES) {
653 : 0 : rte_errno = EPERM;
654 : : ret = -1;
655 : 0 : goto unlock;
656 : : }
657 : : /* sanity checks done, now we can destroy the heap */
658 : 1 : rte_spinlock_lock(&heap->lock);
659 : 1 : ret = malloc_heap_destroy(heap);
660 : : rte_spinlock_unlock(&heap->lock);
661 : 1 : unlock:
662 : 1 : rte_mcfg_mem_write_unlock();
663 : :
664 : 1 : return ret;
665 : : }
|