CUBRID Engine  latest
lea_heap.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
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  */
18 
19 /*
20  * Following is Doug Lea's memory allocator with USE_MALLOC_INSTEAD
21  * feature amendment
22  *
23  * USE_MALLOC_INSTEAD
24  * When this feature is enabled, uses system malloc/free instead of mmap/munmap.
25  *
26  * ENABLE_SEPARATE_MMAP_EVENT_TRACE
27  * Fix the problem that mmaped (malloced when USE_MALLOC_INSTEAD is 1)
28  * memory region (which is returned by mmap_alloc function) is not
29  * automatically freed when destroy_mspace is called.
30  *
31  */
32 
33 #include <stdlib.h>
34 #include <stddef.h>
35 
36 #include "customheaps.h"
37 #include "error_manager.h"
38 #include "system_parameter.h"
39 
40 /* -------------------------------------------------------------------------- */
41 /* DL MALLOC ADAPTATION AND MODIFICATION LAYER */
42 /* -------------------------------------------------------------------------- */
43 /*
44  * use malloc/free instead of mmap/munmap
45  */
46 
47 #define USE_MALLOC_INSTEAD 1
48 #define MOCK_LEA_HEAP_ID ((UINTPTR)(-1))
49 #define system_malloc my_malloc
50 #define system_free my_free
51 
52 static void *my_malloc (size_t sz);
53 static int my_free (void *p);
54 
55 /*
56  * override default DEFAULT_GRANULARITY
57  */
58 #define DEFAULT_GRANULARITY (32U*1024U)
59 
60 /*
61  * prevent mremap use
62  */
63 #if !defined(WINDOWS)
64 #if defined(linux)
65 #undef linux
66 #endif
67 #endif
68 
69 /*
70  * use mspace only
71  */
72 #define ONLY_MSPACES 1
73 
74 /*
75  * Fix the problem that mmaped (malloced when USE_MALLOC_INSTEAD is 1)
76  * memory region (which is returned by mmap_alloc function) is not
77  * automatically freed when destroy_mspace is called.
78  */
81 {
84  void *ptr;
85 };
86 
87 #define MMAP_TRACE_H_SIZE sizeof(MMAP_TRACE_H)
88 
89 #define MMAP_TRACE_H_INIT(h, p) do { \
90  MMAP_TRACE_H *__h = (h); \
91  (__h)->next = (__h)->prev = (__h); \
92  (__h)->ptr = (p); \
93 } while (0)
94 
95 #define MMAP_TRACE_H_REMOVE(h) do { \
96  MMAP_TRACE_H *__h = (h); \
97  (__h)->next->prev = (__h)->prev; \
98  (__h)->prev->next = (__h)->next; \
99 } while (0)
100 
101 #define MMAP_TRACE_H_ADD(p, h) do { \
102  MMAP_TRACE_H *__ih = (p); \
103  MMAP_TRACE_H *__bh = (h); \
104  (__ih)->prev = (__bh); \
105  (__ih)->next = (__bh)->next; \
106  (__bh)->next->prev = (__ih); \
107  (__bh)->next = (__ih); \
108 } while (0)
109 
110 static void mmap_called (void *m, void *ptr, MMAP_TRACE_H * h);
111 static void munmap_is_to_be_called (void *m, void *ptr, MMAP_TRACE_H * h);
112 
113 #define ENABLE_SEPARATE_MMAP_EVENT_TRACE
114 #include "malloc_2_8_3.c"
115 
116 /*
117  * my_malloc - system_malloc hook function
118  * return: memory allocated
119  * sz(in): request memory size
120  */
121 static void *
122 my_malloc (size_t sz)
123 {
124  void *ptr = malloc (sz);
125  if (ptr != NULL)
126  {
127  return ptr;
128  }
129  else
130  {
131  return CMFAIL;
132  }
133 }
134 
135 /*
136  * my_free - system_free hook function
137  * return: memory allocated
138  * p(in):
139  */
140 static int
141 my_free (void *p)
142 {
143  free (p);
144  return 0;
145 }
146 
147 /* ------------------------------------------------------------------------- */
148 /* HL_LEA_HEAP IMPLEMENTATION */
149 /* ------------------------------------------------------------------------- */
150 
151 typedef struct hl_mspace_s HL_MSPACE;
153 {
155  void *base;
156  size_t base_size;
158 };
159 
160 /* Memory layout of HL_MSPACE
161  +-----------+
162  | HL_MSPACE |
163  +-----------+ <-- 8 byte aligned. msp
164  | | mstate (or mspace) m = chunk2mem(msp)
165  +-----------+ <-- m
166  | mstate |
167  | ......... |
168 
169  */
170 #define mspace2hlmspace(m) \
171  (HL_MSPACE *)((char *)mem2chunk(m) - ((sizeof (HL_MSPACE) + 7U) & ~7U))
172 
173 /*
174  * mmap_called - ENABLE_SEPARATE_MMAP_EVENT_TRACE hook function called after
175  * large chunk allocated
176  * return: void
177  * m(in): lea heap mspace pointer
178  * ptr(in): allocated chunk
179  * h(in): embedded trace header
180  */
181 static void
182 mmap_called (void *m, void *ptr, MMAP_TRACE_H * h)
183 {
184  HL_MSPACE *hms = mspace2hlmspace (m);
185  MMAP_TRACE_H_INIT (h, ptr);
186  MMAP_TRACE_H_ADD (h, &hms->header);
187 }
188 
189 /*
190  * munmap_is_to_be_called - ENABLE_SEPARATE_MMAP_EVENT_TRACE hook function
191  * called before large chunk is to be freed.
192  * return: void
193  * m(in): lea heap mspace pointer
194  * ptr(in): memory chunk
195  * h(in): embedded trace header
196  */
197 static void
199 {
200  HL_MSPACE *hms = mspace2hlmspace (m);
201  assert (h->ptr == ptr);
203 }
204 
205 /* EXPORTED FUNCTIONS */
206 #define LEA_HEAP_BASE_SIZE (64U*1024U)
207 
208 /*
209  * hl_register_lea_heap - register new lea heap instance
210  * return: heap handle
211  */
212 UINTPTR
214 {
215 #if !defined (NDEBUG)
217  {
218  return MOCK_LEA_HEAP_ID;
219  }
220  else
221 #endif /* !NDEBUG */
222  {
223  HL_MSPACE *hms;
224 
225  hms = (HL_MSPACE *) malloc (LEA_HEAP_BASE_SIZE);
226  if (hms == NULL)
227  {
228  return 0;
229  }
230 
231  hms->base = (char *) hms + ((sizeof (*hms) + 7U) & ~7U);
232  hms->base_size = LEA_HEAP_BASE_SIZE - (size_t) ((char *) hms->base - (char *) hms);
233  MMAP_TRACE_H_INIT (&hms->header, NULL);
234 
235  hms->ms = (mstate) create_mspace_with_base (hms->base, hms->base_size, 0);
236  if (hms->ms == NULL)
237  {
238  free (hms);
239  return 0;
240  }
241 
242  return ((UINTPTR) hms);
243  }
244 }
245 
246 /*
247  * destroy_mspace_internal - see unregister_leap_heap
248  * return: void
249  * hms(in): leap heap mspace pointer
250  */
251 static void
253 {
254  destroy_mspace (hms->ms);
255  hms->ms = NULL;
256  /* remove unmapped segments */
257  while (hms->header.next != &hms->header)
258  {
259  MMAP_TRACE_H *h = hms->header.next;
260  MMAP_TRACE_H_REMOVE (h); /* unlink from doubley linked list */
261  my_free (h->ptr); /* no need to free h. h is embedded */
262  }
263 }
264 
265 
266 /*
267  * hl_clear_lea_heap - clears lea heap
268  * return: void
269  * heap_id(in): lea heap handle
270  */
271 void
272 hl_clear_lea_heap (UINTPTR heap_id)
273 {
274 #if !defined (NDEBUG)
276  {
277  assert (heap_id == MOCK_LEA_HEAP_ID);
278  }
279  else
280 #endif /* !NDEBUG */
281  {
282  HL_MSPACE *hms = (HL_MSPACE *) heap_id;
283 
284  if (hms != NULL)
285  {
287  hms->ms = (mstate) create_mspace_with_base (hms->base, hms->base_size, 0);
288  assert (hms->ms != NULL);
289  }
290  }
291 }
292 
293 /*
294  * hl_unregister_lea_heap - destoyes lea heap
295  * return: void
296  * heap_id(in): lea heap handle
297  */
298 void
299 hl_unregister_lea_heap (UINTPTR heap_id)
300 {
301 #if !defined (NDEBUG)
303  {
304  assert (heap_id == MOCK_LEA_HEAP_ID);
305  }
306  else
307 #endif /* !NDEBUG */
308  {
309  HL_MSPACE *hms = (HL_MSPACE *) heap_id;
310 
311  if (hms != NULL)
312  {
314  free (hms);
315  }
316  }
317 }
318 
319 /*
320  * hl_lea_alloc - alloc
321  * return: pointer to allocated memory
322  * heap_id(in): lea heap handle
323  * sz(in): requested size
324  */
325 void *
326 hl_lea_alloc (UINTPTR heap_id, size_t sz)
327 {
328 #if !defined (NDEBUG)
330  {
331  return malloc (sz);
332  }
333  else
334 #endif /* !NDEBUG */
335  {
336  HL_MSPACE *hms = (HL_MSPACE *) heap_id;
337  void *p;
338 
339  if (hms != NULL)
340  {
341  p = mspace_malloc (hms->ms, sz);
342  if (p == NULL)
343  {
345  }
346 
347  return p;
348  }
349  return NULL;
350  }
351 }
352 
353 /*
354  * hl_lea_realloc - realloc
355  * return: pointer to re-allocated memory
356  * heap_id(in): lea heap handle
357  * ptr(in): pointer to memory block allocated before
358  * sz(in): requested size
359  */
360 void *
361 hl_lea_realloc (UINTPTR heap_id, void *ptr, size_t sz)
362 {
363 #if !defined (NDEBUG)
365  {
366  return realloc (ptr, sz);
367  }
368  else
369 #endif /* !NDEBUG */
370  {
371  HL_MSPACE *hms = (HL_MSPACE *) heap_id;
372  void *p;
373 
374  if (hms != NULL)
375  {
376  p = mspace_realloc (hms->ms, ptr, sz);
377  if (p == NULL)
378  {
380  }
381 
382  return p;
383  }
384  return NULL;
385  }
386 }
387 
388 /*
389  * hl_lea_free - free
390  * return: void
391  * heap_id(in): lea heap handle
392  * ptr(in): pointer to memory block allocated before
393  */
394 void
395 hl_lea_free (UINTPTR heap_id, void *ptr)
396 {
397 #if !defined (NDEBUG)
399  {
400  free (ptr);
401  }
402  else
403 #endif /* !NDEBUG */
404  {
405  HL_MSPACE *hms = (HL_MSPACE *) heap_id;
406 
407  if (hms != NULL)
408  {
409  mspace_free (hms->ms, ptr);
410  }
411  }
412 }
void * hl_lea_realloc(UINTPTR heap_id, void *ptr, size_t sz)
Definition: lea_heap.c:361
void * base
Definition: lea_heap.c:155
#define MMAP_TRACE_H_ADD(p, h)
Definition: lea_heap.c:101
mstate ms
Definition: lea_heap.c:154
MMAP_TRACE_H * prev
Definition: lea_heap.c:83
#define MMAP_TRACE_H_REMOVE(h)
Definition: lea_heap.c:95
#define MMAP_TRACE_H_INIT(h, p)
Definition: lea_heap.c:89
void hl_lea_free(UINTPTR heap_id, void *ptr)
Definition: lea_heap.c:395
struct malloc_state * mstate
void * hl_lea_alloc(UINTPTR heap_id, size_t sz)
Definition: lea_heap.c:326
static void destroy_mspace_internal(HL_MSPACE *hms)
Definition: lea_heap.c:252
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
static void mmap_called(void *m, void *ptr, MMAP_TRACE_H *h)
Definition: lea_heap.c:182
#define assert(x)
#define MOCK_LEA_HEAP_ID
Definition: lea_heap.c:48
#define LEA_HEAP_BASE_SIZE
Definition: lea_heap.c:206
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
UINTPTR hl_register_lea_heap(void)
Definition: lea_heap.c:213
size_t base_size
Definition: lea_heap.c:156
#define NULL
Definition: freelistheap.h:34
static int my_free(void *p)
Definition: lea_heap.c:141
void * ptr
Definition: lea_heap.c:84
#define mspace2hlmspace(m)
Definition: lea_heap.c:170
#define ARG_FILE_LINE
Definition: error_manager.h:44
void hl_clear_lea_heap(UINTPTR heap_id)
Definition: lea_heap.c:272
static void * my_malloc(size_t sz)
Definition: lea_heap.c:122
#define CMFAIL
static void munmap_is_to_be_called(void *m, void *ptr, MMAP_TRACE_H *h)
Definition: lea_heap.c:198
bool prm_get_bool_value(PARAM_ID prm_id)
MMAP_TRACE_H * next
Definition: lea_heap.c:82
MMAP_TRACE_H header
Definition: lea_heap.c:157
void hl_unregister_lea_heap(UINTPTR heap_id)
Definition: lea_heap.c:299
const char ** p
Definition: dynamic_load.c:945