Branch data Line data Source code
1 : : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2 : : /*
3 : : * Implement malloc()/free() etc on top of our memory region allocator,
4 : : * which provides mem_alloc()/mem_free().
5 : : *
6 : : * Copyright 2013-2015 IBM Corp.
7 : : */
8 : :
9 : : #include <mem_region.h>
10 : : #include <lock.h>
11 : : #include <skiboot.h>
12 : : #include <stack.h>
13 : : #include <string.h>
14 : : #include <mem_region-malloc.h>
15 : :
16 : : #define DEFAULT_ALIGN __alignof__(long)
17 : :
18 : 4316 : void *__memalign(size_t blocksize, size_t bytes, const char *location)
19 : : {
20 : : void *p;
21 : :
22 : 4316 : lock(&skiboot_heap.free_list_lock);
23 : 4316 : p = mem_alloc(&skiboot_heap, bytes, blocksize, location);
24 : 4316 : unlock(&skiboot_heap.free_list_lock);
25 : :
26 : 4316 : return p;
27 : : }
28 : :
29 : 4316 : void *__malloc(size_t bytes, const char *location)
30 : : {
31 : 4316 : return __memalign(DEFAULT_ALIGN, bytes, location);
32 : : }
33 : :
34 : 161 : static bool check_heap_ptr(const void *p)
35 : : {
36 : 161 : struct mem_region *region = &skiboot_heap;
37 : 161 : unsigned long ptr = (unsigned long)p;
38 : :
39 : 161 : if (!ptr)
40 : 3 : return true;
41 : :
42 : 158 : if (ptr < region->start || ptr > region->start + region->len) {
43 : 0 : prerror("Trying to free() a pointer outside heap. Possibly local_alloc().\n");
44 : 0 : backtrace();
45 : 0 : return false;
46 : : }
47 : 158 : return true;
48 : : }
49 : :
50 : 152 : void __free(void *p, const char *location)
51 : : {
52 : 152 : if (!check_heap_ptr(p))
53 : 0 : return;
54 : :
55 : 152 : lock(&skiboot_heap.free_list_lock);
56 : 152 : mem_free(&skiboot_heap, p, location);
57 : 152 : unlock(&skiboot_heap.free_list_lock);
58 : : }
59 : :
60 : 9 : void *__realloc(void *ptr, size_t size, const char *location)
61 : : {
62 : : void *newptr;
63 : :
64 : 9 : if (!check_heap_ptr(ptr))
65 : 0 : return NULL;
66 : :
67 : : /* Two classic malloc corner cases. */
68 : 9 : if (!size) {
69 : 1 : __free(ptr, location);
70 : 1 : return NULL;
71 : : }
72 : 8 : if (!ptr)
73 : 3 : return __malloc(size, location);
74 : :
75 : 5 : lock(&skiboot_heap.free_list_lock);
76 : 5 : if (mem_resize(&skiboot_heap, ptr, size, location)) {
77 : 3 : newptr = ptr;
78 : : } else {
79 : 2 : newptr = mem_alloc(&skiboot_heap, size, DEFAULT_ALIGN,
80 : : location);
81 : 2 : if (newptr) {
82 : 1 : size_t copy = mem_allocated_size(ptr);
83 : 1 : if (copy > size)
84 : 0 : copy = size;
85 : 1 : memcpy(newptr, ptr, copy);
86 : 1 : mem_free(&skiboot_heap, ptr, location);
87 : : }
88 : : }
89 : 5 : unlock(&skiboot_heap.free_list_lock);
90 : 5 : return newptr;
91 : : }
92 : :
93 : 18 : void *__zalloc(size_t bytes, const char *location)
94 : : {
95 : 18 : void *p = __malloc(bytes, location);
96 : :
97 : 18 : if (p)
98 : 17 : memset(p, 0, bytes);
99 : 18 : return p;
100 : : }
|