Motr  M0
memory.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2015-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 
30 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_MEMORY
31 #include "lib/arith.h" /* min_type, m0_is_po2 */
32 #include "lib/assert.h"
33 #include "lib/atomic.h"
34 #include "lib/trace.h"
35 #include "lib/memory.h"
36 #include "lib/finject.h"
37 #include "lib/misc.h" /* m0_round_down */
38 
39 enum { U_POISON_BYTE = 0x5f };
40 
41 #ifdef ENABLE_DEV_MODE
42 #define DEV_MODE (true)
43 #else
44 #define DEV_MODE (false)
45 #endif
46 
47 #ifdef ENABLE_FREE_POISON
48 static void poison_before_free(void *data, size_t size)
49 {
50  memset(data, U_POISON_BYTE, size);
51 }
52 
59 static bool is_poisoned(uint64_t val)
60 {
61  M0_CASSERT(U_POISON_BYTE == 0x5f);
62  return (val & 0x00ffffffff000000ULL) == 0x005f5f5f5f000000ULL;
63 }
64 
65 M0_INTERNAL bool m0_is_poisoned(const void *p)
66 {
67  /*
68  * Check two cases: "p" is a ...
69  *
70  * - pointer to a freed object, is_poisoned(*p) is true;
71  * - pointer field within a freed object, is_poisoned(p) is true;
72  */
73  return is_poisoned((uint64_t)p) || is_poisoned(*(const uint64_t *)p);
74 }
75 #else
76 static void poison_before_free(void *data, size_t size)
77 {;}
78 
79 M0_INTERNAL bool m0_is_poisoned(const void *ptr)
80 {
81  return false;
82 }
83 #endif
84 
85 M0_INTERNAL void *m0_arch_alloc (size_t size);
86 M0_INTERNAL void m0_arch_free (void *data);
87 M0_INTERNAL void m0_arch_allocated_zero(void *data, size_t size);
88 M0_INTERNAL void *m0_arch_alloc_nz (size_t size);
89 M0_INTERNAL void m0_arch_memory_pagein(void *addr, size_t size);
90 M0_INTERNAL size_t m0_arch_alloc_size(void *data);
91 M0_INTERNAL void *m0_arch_alloc_wired(size_t size, unsigned shift);
92 M0_INTERNAL void m0_arch_free_wired(void *data, size_t size, unsigned shift);
93 M0_INTERNAL void *m0_arch_alloc_aligned(size_t alignment, size_t size);
94 M0_INTERNAL void m0_arch_free_aligned(void *data, size_t size, unsigned shft);
95 M0_INTERNAL int m0_arch_pagesize_get(void);
96 M0_INTERNAL int m0_arch_pageshift_get(void);
97 M0_INTERNAL int m0_arch_dont_dump(void *p, size_t size);
98 M0_INTERNAL int m0_arch_memory_init (void);
99 M0_INTERNAL void m0_arch_memory_fini (void);
100 
101 static struct m0_atomic64 allocated;
104 
105 static void alloc_tail(void *area, size_t size)
106 {
107  if (DEV_MODE && area != NULL) {
108  size_t asize = m0_arch_alloc_size(area);
109 
110  m0_atomic64_add(&allocated, asize);
112  }
113 }
114 
115 M0_INTERNAL void *m0_alloc_nz(size_t size)
116 {
117  void *area;
118 
119  M0_ENTRY("size=%zi", size);
120  area = m0_arch_alloc_nz(size);
121  alloc_tail(area, size);
122  M0_LEAVE("ptr=%p size=%zi", area, size);
123  return area;
124 }
125 
126 void *m0_alloc(size_t size)
127 {
128  void *area;
129 
130  M0_ENTRY("size=%zi", size);
131  if (M0_FI_ENABLED("fail_allocation"))
132  return NULL;
133  area = m0_arch_alloc(size);
134  alloc_tail(area, size);
135  if (area != NULL) {
137  } else if (!M0_FI_ENABLED("keep_quiet")) {
138  M0_LOG(M0_ERROR, "Failed to allocate %zi bytes.", size);
139  m0_backtrace();
140  }
141  M0_LEAVE("ptr=%p size=%zi", area, size);
142  return area;
143 }
144 M0_EXPORTED(m0_alloc);
145 
146 void m0_free(void *data)
147 {
148  if (data != NULL) {
149  size_t size = m0_arch_alloc_size(data);
150 
151  M0_LOG(M0_DEBUG, "%p", data);
152 
153  if (DEV_MODE) {
156  }
159  }
160 }
161 M0_EXPORTED(m0_free);
162 
163 M0_INTERNAL void m0_memory_pagein(void *addr, size_t size)
164 {
166 }
167 
168 M0_INTERNAL void *m0_alloc_aligned(size_t size, unsigned shift)
169 {
170  void *result;
171  size_t alignment;
172 
173  if (M0_FI_ENABLED("fail_allocation"))
174  return NULL;
175 
176  /*
177  * posix_memalign(3):
178  *
179  * The requested alignment must be a power of 2 at least as
180  * large as sizeof(void *).
181  */
182 
183  alignment = max_type(size_t, 1 << shift, sizeof result);
184  M0_ASSERT(m0_is_po2(alignment));
185  result = m0_arch_alloc_aligned(alignment, size);
186  if (result != NULL)
187  m0_arch_allocated_zero(result, size);
188  return result;
189 }
190 M0_EXPORTED(m0_alloc_aligned);
191 
192 M0_INTERNAL void m0_free_aligned(void *data, size_t size, unsigned shift)
193 {
194  if (data != NULL) {
195  M0_PRE(m0_addr_is_aligned(data, shift));
197  m0_arch_free_aligned(data, size, shift);
198  }
199 }
200 M0_EXPORTED(m0_free_aligned);
201 
202 M0_INTERNAL void *m0_alloc_wired(size_t size, unsigned shift)
203 {
204  return m0_arch_alloc_wired(size, shift);
205 }
206 
207 M0_INTERNAL void m0_free_wired(void *data, size_t size, unsigned shift)
208 {
209  if (data != NULL) {
211  m0_arch_free_wired(data, size, shift);
212  }
213 }
214 
215 M0_INTERNAL size_t m0_allocated(void)
216 {
217  return m0_atomic64_get(&allocated);
218 }
219 M0_EXPORTED(m0_allocated);
220 
221 M0_INTERNAL size_t m0_allocated_total(void)
222 {
224 }
225 M0_EXPORTED(m0_allocated_total);
226 
227 M0_INTERNAL size_t m0_freed_total(void)
228 {
230 }
231 M0_EXPORTED(m0_freed_total);
232 
233 M0_INTERNAL int m0_pagesize_get(void)
234 {
235  return m0_arch_pagesize_get();
236 }
237 
238 M0_INTERNAL int m0_pageshift_get(void)
239 {
240  return m0_arch_pageshift_get();
241 }
242 
243 M0_INTERNAL int m0_dont_dump(void *p, size_t size)
244 {
245  int pagesize = m0_pagesize_get();
246  M0_PRE(((unsigned long)p / pagesize * pagesize) == (unsigned long)p);
247 
248  return m0_arch_dont_dump(p, size);
249 }
250 
251 M0_INTERNAL int m0_memory_init(void)
252 {
256  return m0_arch_memory_init();
257 }
258 
259 M0_INTERNAL void m0_memory_fini(void)
260 {
261  M0_LOG(M0_DEBUG, "allocated=%" PRIu64 " cumulative_alloc=%" PRIu64 " "
262  "cumulative_free=%"PRIu64, m0_atomic64_get(&allocated),
266 }
267 
268 #undef DEV_MODE
269 #undef M0_TRACE_SUBSYSTEM
270 
273 /*
274  * Local variables:
275  * c-indentation-style: "K&R"
276  * c-basic-offset: 8
277  * tab-width: 8
278  * fill-column: 80
279  * scroll-step: 1
280  * End:
281  */
282 /*
283  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
284  */
static void ptr(struct m0_addb2__context *ctx, const uint64_t *v, char *buf)
Definition: dump.c:440
void m0_backtrace(void)
Definition: assert.c:72
static struct m0_addb2_philter p
Definition: consumer.c:40
#define M0_PRE(cond)
#define NULL
Definition: misc.h:38
static bool m0_addr_is_aligned(const void *addr, unsigned shift)
Definition: memory.h:107
Definition: idx_mock.c:52
M0_INTERNAL void m0_arch_free_wired(void *data, size_t size, unsigned shift)
Definition: memory.c:109
#define M0_LOG(level,...)
Definition: trace.h:167
M0_LEAVE()
M0_INTERNAL void m0_arch_memory_pagein(void *addr, size_t size)
Definition: memory.c:78
M0_INTERNAL size_t m0_allocated_total(void)
Definition: memory.c:221
static void m0_atomic64_sub(struct m0_atomic64 *a, int64_t num)
#define M0_CASSERT(cond)
M0_INTERNAL size_t m0_arch_alloc_size(void *data)
Definition: memory.c:83
static bool m0_is_po2(uint64_t val)
Definition: arith.h:153
struct m0_bufvec data
Definition: di.c:40
static void alloc_tail(void *area, size_t size)
Definition: memory.c:105
M0_INTERNAL void * m0_alloc_wired(size_t size, unsigned shift)
Definition: memory.c:202
M0_INTERNAL void m0_free_aligned(void *data, size_t size, unsigned shift)
Definition: memory.c:192
M0_INTERNAL int m0_pageshift_get(void)
Definition: memory.c:238
static struct m0_atomic64 allocated
Definition: memory.c:101
M0_INTERNAL int m0_arch_pagesize_get(void)
Definition: memory.c:133
M0_INTERNAL void m0_arch_free_aligned(void *addr, size_t size, unsigned shift)
Definition: memory.c:98
M0_INTERNAL size_t m0_allocated(void)
Definition: memory.c:215
M0_INTERNAL void m0_free_wired(void *data, size_t size, unsigned shift)
Definition: memory.c:207
#define M0_ENTRY(...)
Definition: trace.h:170
M0_INTERNAL int m0_pagesize_get(void)
Definition: memory.c:233
M0_INTERNAL void * m0_alloc_nz(size_t size)
Definition: memory.c:115
#define PRIu64
Definition: types.h:58
static struct m0_atomic64 cumulative_free
Definition: memory.c:103
#define DEV_MODE
Definition: memory.c:44
M0_INTERNAL void * m0_arch_alloc(size_t size)
Definition: memory.c:37
M0_INTERNAL int m0_dont_dump(void *p, size_t size)
Definition: memory.c:243
#define M0_ASSERT(cond)
M0_INTERNAL int m0_arch_memory_init(void)
Definition: memory.c:124
static void poison_before_free(void *data, size_t size)
Definition: memory.c:76
void * m0_alloc(size_t size)
Definition: memory.c:126
M0_INTERNAL void m0_arch_free(void *data)
Definition: memory.c:62
M0_INTERNAL void * m0_arch_alloc_nz(size_t size)
Definition: memory.c:72
Definition: xcode.h:73
M0_INTERNAL bool m0_is_poisoned(const void *ptr)
Definition: memory.c:79
M0_INTERNAL void * m0_arch_alloc_aligned(size_t alignment, size_t size)
Definition: memory.c:88
M0_INTERNAL void m0_memory_fini(void)
Definition: memory.c:259
static int64_t m0_atomic64_get(const struct m0_atomic64 *a)
M0_INTERNAL void m0_arch_allocated_zero(void *data, size_t size)
Definition: memory.c:67
M0_INTERNAL size_t m0_freed_total(void)
Definition: memory.c:227
#define M0_FI_ENABLED(tag)
Definition: finject.h:231
m0_bcount_t size
Definition: di.c:39
M0_INTERNAL void m0_memory_pagein(void *addr, size_t size)
Definition: memory.c:163
M0_INTERNAL int m0_arch_pageshift_get(void)
Definition: memory.c:138
M0_INTERNAL void * m0_arch_alloc_wired(size_t size, unsigned shift)
Definition: memory.c:104
#define max_type(t, a, b)
Definition: arith.h:82
M0_INTERNAL int m0_memory_init(void)
Definition: memory.c:251
M0_INTERNAL void * m0_alloc_aligned(size_t size, unsigned shift)
Definition: memory.c:168
static void m0_atomic64_add(struct m0_atomic64 *a, int64_t num)
static struct m0_atomic64 cumulative_alloc
Definition: memory.c:102
void m0_free(void *data)
Definition: memory.c:146
M0_INTERNAL void m0_arch_memory_fini(void)
Definition: memory.c:129
static void m0_atomic64_set(struct m0_atomic64 *a, int64_t num)
M0_INTERNAL int m0_arch_dont_dump(void *p, size_t size)
Definition: memory.c:119