1/*****************************************************************************
2
3Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
4
5This program is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License, version 2.0,
7as published by the Free Software Foundation.
8
9This program is also distributed with certain software (including
10but not limited to OpenSSL) that is licensed under separate terms,
11as designated in a particular file or component or in included license
12documentation.  The authors of MySQL hereby grant you an additional
13permission to link the program and your derivative works with the
14separately licensed software that they have included with MySQL.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19GNU General Public License, version 2.0, for more details.
20
21You should have received a copy of the GNU General Public License along with
22this program; if not, write to the Free Software Foundation, Inc.,
2351 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
24
25*****************************************************************************/
26
27/********************************************************************//**
28@file include/mem0mem.ic
29The memory management
30
31Created 6/8/1994 Heikki Tuuri
32*************************************************************************/
33
34#include "mem0dbg.ic"
35#ifndef UNIV_HOTBACKUP
36# include "mem0pool.h"
37#endif /* !UNIV_HOTBACKUP */
38
39#ifdef UNIV_DEBUG
40# define mem_heap_create_block(heap, n, type, file_name, line)		\
41	mem_heap_create_block_func(heap, n, file_name, line, type)
42# define mem_heap_create_at(N, file_name, line)				\
43	mem_heap_create_func(N, file_name, line, MEM_HEAP_DYNAMIC)
44#else /* UNIV_DEBUG */
45# define mem_heap_create_block(heap, n, type, file_name, line)		\
46	mem_heap_create_block_func(heap, n, type)
47# define mem_heap_create_at(N, file_name, line)				\
48	mem_heap_create_func(N, MEM_HEAP_DYNAMIC)
49#endif /* UNIV_DEBUG */
50/***************************************************************//**
51Creates a memory heap block where data can be allocated.
52@return own: memory heap block, NULL if did not succeed (only possible
53for MEM_HEAP_BTR_SEARCH type heaps) */
54UNIV_INTERN
55mem_block_t*
56mem_heap_create_block_func(
57/*=======================*/
58	mem_heap_t*	heap,	/*!< in: memory heap or NULL if first block
59				should be created */
60	ulint		n,	/*!< in: number of bytes needed for user data */
61#ifdef UNIV_DEBUG
62	const char*	file_name,/*!< in: file name where created */
63	ulint		line,	/*!< in: line where created */
64#endif /* UNIV_DEBUG */
65	ulint		type);	/*!< in: type of heap: MEM_HEAP_DYNAMIC or
66				MEM_HEAP_BUFFER */
67/******************************************************************//**
68Frees a block from a memory heap. */
69UNIV_INTERN
70void
71mem_heap_block_free(
72/*================*/
73	mem_heap_t*	heap,	/*!< in: heap */
74	mem_block_t*	block);	/*!< in: block to free */
75#ifndef UNIV_HOTBACKUP
76/******************************************************************//**
77Frees the free_block field from a memory heap. */
78UNIV_INTERN
79void
80mem_heap_free_block_free(
81/*=====================*/
82	mem_heap_t*	heap);	/*!< in: heap */
83#endif /* !UNIV_HOTBACKUP */
84/***************************************************************//**
85Adds a new block to a memory heap.
86@return created block, NULL if did not succeed (only possible for
87MEM_HEAP_BTR_SEARCH type heaps) */
88UNIV_INTERN
89mem_block_t*
90mem_heap_add_block(
91/*===============*/
92	mem_heap_t*	heap,	/*!< in: memory heap */
93	ulint		n);	/*!< in: number of bytes user needs */
94
95UNIV_INLINE
96void
97mem_block_set_len(mem_block_t* block, ulint len)
98{
99	ut_ad(len > 0);
100
101	block->len = len;
102}
103
104UNIV_INLINE
105ulint
106mem_block_get_len(mem_block_t* block)
107{
108	return(block->len);
109}
110
111UNIV_INLINE
112void
113mem_block_set_type(mem_block_t* block, ulint type)
114{
115	ut_ad((type == MEM_HEAP_DYNAMIC) || (type == MEM_HEAP_BUFFER)
116	      || (type == MEM_HEAP_BUFFER + MEM_HEAP_BTR_SEARCH));
117
118	block->type = type;
119}
120
121UNIV_INLINE
122ulint
123mem_block_get_type(mem_block_t* block)
124{
125	return(block->type);
126}
127
128UNIV_INLINE
129void
130mem_block_set_free(mem_block_t* block, ulint free)
131{
132	ut_ad(free > 0);
133	ut_ad(free <= mem_block_get_len(block));
134
135	block->free = free;
136}
137
138UNIV_INLINE
139ulint
140mem_block_get_free(mem_block_t* block)
141{
142	return(block->free);
143}
144
145UNIV_INLINE
146void
147mem_block_set_start(mem_block_t* block, ulint start)
148{
149	ut_ad(start > 0);
150
151	block->start = start;
152}
153
154UNIV_INLINE
155ulint
156mem_block_get_start(mem_block_t* block)
157{
158	return(block->start);
159}
160
161/***************************************************************//**
162Allocates and zero-fills n bytes of memory from a memory heap.
163@return	allocated, zero-filled storage */
164UNIV_INLINE
165void*
166mem_heap_zalloc(
167/*============*/
168	mem_heap_t*	heap,	/*!< in: memory heap */
169	ulint		n)	/*!< in: number of bytes; if the heap is allowed
170				to grow into the buffer pool, this must be
171				<= MEM_MAX_ALLOC_IN_BUF */
172{
173	ut_ad(heap);
174	ut_ad(!(heap->type & MEM_HEAP_BTR_SEARCH));
175	return(memset(mem_heap_alloc(heap, n), 0, n));
176}
177
178/***************************************************************//**
179Allocates n bytes of memory from a memory heap.
180@return allocated storage, NULL if did not succeed (only possible for
181MEM_HEAP_BTR_SEARCH type heaps) */
182UNIV_INLINE
183void*
184mem_heap_alloc(
185/*===========*/
186	mem_heap_t*	heap,	/*!< in: memory heap */
187	ulint		n)	/*!< in: number of bytes; if the heap is allowed
188				to grow into the buffer pool, this must be
189				<= MEM_MAX_ALLOC_IN_BUF */
190{
191	mem_block_t*	block;
192	void*		buf;
193	ulint		free;
194
195	ut_ad(mem_heap_check(heap));
196
197	block = UT_LIST_GET_LAST(heap->base);
198
199	ut_ad(!(block->type & MEM_HEAP_BUFFER) || (n <= MEM_MAX_ALLOC_IN_BUF));
200
201	/* Check if there is enough space in block. If not, create a new
202	block to the heap */
203
204	if (mem_block_get_len(block)
205	    < mem_block_get_free(block) + MEM_SPACE_NEEDED(n)) {
206
207		block = mem_heap_add_block(heap, n);
208
209		if (block == NULL) {
210
211			return(NULL);
212		}
213	}
214
215	free = mem_block_get_free(block);
216
217	buf = (byte*) block + free;
218
219	mem_block_set_free(block, free + MEM_SPACE_NEEDED(n));
220
221#ifdef UNIV_MEM_DEBUG
222	UNIV_MEM_ALLOC(buf,
223		       n + MEM_FIELD_HEADER_SIZE + MEM_FIELD_TRAILER_SIZE);
224
225	/* In the debug version write debugging info to the field */
226	mem_field_init((byte*) buf, n);
227
228	/* Advance buf to point at the storage which will be given to the
229	caller */
230	buf = (byte*) buf + MEM_FIELD_HEADER_SIZE;
231
232#endif
233	UNIV_MEM_ALLOC(buf, n);
234	return(buf);
235}
236
237/*****************************************************************//**
238Returns a pointer to the heap top.
239@return	pointer to the heap top */
240UNIV_INLINE
241byte*
242mem_heap_get_heap_top(
243/*==================*/
244	mem_heap_t*	heap)	/*!< in: memory heap */
245{
246	mem_block_t*	block;
247	byte*		buf;
248
249	ut_ad(mem_heap_check(heap));
250
251	block = UT_LIST_GET_LAST(heap->base);
252
253	buf = (byte*) block + mem_block_get_free(block);
254
255	return(buf);
256}
257
258/*****************************************************************//**
259Frees the space in a memory heap exceeding the pointer given. The
260pointer must have been acquired from mem_heap_get_heap_top. The first
261memory block of the heap is not freed. */
262UNIV_INLINE
263void
264mem_heap_free_heap_top(
265/*===================*/
266	mem_heap_t*	heap,	/*!< in: heap from which to free */
267	byte*		old_top)/*!< in: pointer to old top of heap */
268{
269	mem_block_t*	block;
270	mem_block_t*	prev_block;
271#if defined UNIV_MEM_DEBUG || defined UNIV_DEBUG
272	ibool		error;
273	ulint		total_size;
274	ulint		size;
275
276	ut_ad(mem_heap_check(heap));
277
278	/* Validate the heap and get its total allocated size */
279	mem_heap_validate_or_print(heap, NULL, FALSE, &error, &total_size,
280				   NULL, NULL);
281	ut_a(!error);
282
283	/* Get the size below top pointer */
284	mem_heap_validate_or_print(heap, old_top, FALSE, &error, &size, NULL,
285				   NULL);
286	ut_a(!error);
287
288#endif
289
290	block = UT_LIST_GET_LAST(heap->base);
291
292	while (block != NULL) {
293		if (((byte*) block + mem_block_get_free(block) >= old_top)
294		    && ((byte*) block <= old_top)) {
295			/* Found the right block */
296
297			break;
298		}
299
300		/* Store prev_block value before freeing the current block
301		(the current block will be erased in freeing) */
302
303		prev_block = UT_LIST_GET_PREV(list, block);
304
305		mem_heap_block_free(heap, block);
306
307		block = prev_block;
308	}
309
310	ut_ad(block);
311
312	/* Set the free field of block */
313	mem_block_set_free(block, old_top - (byte*) block);
314
315	ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
316	UNIV_MEM_ASSERT_W(old_top, (byte*) block + block->len - old_top);
317#if defined UNIV_MEM_DEBUG
318	/* In the debug version erase block from top up */
319	mem_erase_buf(old_top, (byte*) block + block->len - old_top);
320
321	/* Update allocated memory count */
322	mutex_enter(&mem_hash_mutex);
323	mem_current_allocated_memory -= (total_size - size);
324	mutex_exit(&mem_hash_mutex);
325#endif /* UNIV_MEM_DEBUG */
326	UNIV_MEM_ALLOC(old_top, (byte*) block + block->len - old_top);
327
328	/* If free == start, we may free the block if it is not the first
329	one */
330
331	if ((heap != block) && (mem_block_get_free(block)
332				== mem_block_get_start(block))) {
333		mem_heap_block_free(heap, block);
334	}
335}
336
337/*****************************************************************//**
338Empties a memory heap. The first memory block of the heap is not freed. */
339UNIV_INLINE
340void
341mem_heap_empty(
342/*===========*/
343	mem_heap_t*	heap)	/*!< in: heap to empty */
344{
345	mem_heap_free_heap_top(heap, (byte*) heap + mem_block_get_start(heap));
346#ifndef UNIV_HOTBACKUP
347	if (heap->free_block) {
348		mem_heap_free_block_free(heap);
349	}
350#endif /* !UNIV_HOTBACKUP */
351}
352
353/*****************************************************************//**
354Returns a pointer to the topmost element in a memory heap. The size of the
355element must be given.
356@return	pointer to the topmost element */
357UNIV_INLINE
358void*
359mem_heap_get_top(
360/*=============*/
361	mem_heap_t*	heap,	/*!< in: memory heap */
362	ulint		n)	/*!< in: size of the topmost element */
363{
364	mem_block_t*	block;
365	byte*		buf;
366
367	ut_ad(mem_heap_check(heap));
368
369	block = UT_LIST_GET_LAST(heap->base);
370
371	buf = (byte*) block + mem_block_get_free(block) - MEM_SPACE_NEEDED(n);
372
373#ifdef UNIV_MEM_DEBUG
374	ut_ad(mem_block_get_start(block) <= (ulint) (buf - (byte*) block));
375
376	/* In the debug version, advance buf to point at the storage which
377	was given to the caller in the allocation*/
378
379	buf += MEM_FIELD_HEADER_SIZE;
380
381	/* Check that the field lengths agree */
382	ut_ad(n == mem_field_header_get_len(buf));
383#endif
384
385	return((void*) buf);
386}
387
388/*****************************************************************//**
389Frees the topmost element in a memory heap. The size of the element must be
390given. */
391UNIV_INLINE
392void
393mem_heap_free_top(
394/*==============*/
395	mem_heap_t*	heap,	/*!< in: memory heap */
396	ulint		n)	/*!< in: size of the topmost element */
397{
398	mem_block_t*	block;
399
400	ut_ad(mem_heap_check(heap));
401
402	block = UT_LIST_GET_LAST(heap->base);
403
404	/* Subtract the free field of block */
405	mem_block_set_free(block, mem_block_get_free(block)
406			   - MEM_SPACE_NEEDED(n));
407	UNIV_MEM_ASSERT_W((byte*) block + mem_block_get_free(block), n);
408#ifdef UNIV_MEM_DEBUG
409
410	ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
411
412	/* In the debug version check the consistency, and erase field */
413	mem_field_erase((byte*) block + mem_block_get_free(block), n);
414#endif
415
416	/* If free == start, we may free the block if it is not the first
417	one */
418
419	if ((heap != block) && (mem_block_get_free(block)
420				== mem_block_get_start(block))) {
421		mem_heap_block_free(heap, block);
422	} else {
423		/* Avoid a bogus UNIV_MEM_ASSERT_W() warning in a
424		subsequent invocation of mem_heap_free_top().
425		Originally, this was UNIV_MEM_FREE(), to catch writes
426		to freed memory. */
427		UNIV_MEM_ALLOC((byte*) block + mem_block_get_free(block), n);
428	}
429}
430
431/*****************************************************************//**
432NOTE: Use the corresponding macros instead of this function. Creates a
433memory heap. For debugging purposes, takes also the file name and line as
434argument.
435@return own: memory heap, NULL if did not succeed (only possible for
436MEM_HEAP_BTR_SEARCH type heaps) */
437UNIV_INLINE
438mem_heap_t*
439mem_heap_create_func(
440/*=================*/
441	ulint		n,		/*!< in: desired start block size,
442					this means that a single user buffer
443					of size n will fit in the block,
444					0 creates a default size block */
445#ifdef UNIV_DEBUG
446	const char*	file_name,	/*!< in: file name where created */
447	ulint		line,		/*!< in: line where created */
448#endif /* UNIV_DEBUG */
449	ulint		type)		/*!< in: heap type */
450{
451	mem_block_t*   block;
452
453	if (!n) {
454		n = MEM_BLOCK_START_SIZE;
455	}
456
457	block = mem_heap_create_block(NULL, n, type, file_name, line);
458
459	if (block == NULL) {
460
461		return(NULL);
462	}
463
464	UT_LIST_INIT(block->base);
465
466	/* Add the created block itself as the first block in the list */
467	UT_LIST_ADD_FIRST(list, block->base, block);
468
469#ifdef UNIV_MEM_DEBUG
470
471	mem_hash_insert(block, file_name, line);
472
473#endif
474
475	return(block);
476}
477
478/*****************************************************************//**
479NOTE: Use the corresponding macro instead of this function. Frees the space
480occupied by a memory heap. In the debug version erases the heap memory
481blocks. */
482UNIV_INLINE
483void
484mem_heap_free_func(
485/*===============*/
486	mem_heap_t*	heap,		/*!< in, own: heap to be freed */
487	const char*	file_name MY_ATTRIBUTE((unused)),
488					/*!< in: file name where freed */
489	ulint		line  MY_ATTRIBUTE((unused)))
490{
491	mem_block_t*	block;
492	mem_block_t*	prev_block;
493
494	ut_ad(mem_heap_check(heap));
495
496	block = UT_LIST_GET_LAST(heap->base);
497
498#ifdef UNIV_MEM_DEBUG
499
500	/* In the debug version remove the heap from the hash table of heaps
501	and check its consistency */
502
503	mem_hash_remove(heap, file_name, line);
504
505#endif
506#ifndef UNIV_HOTBACKUP
507	if (heap->free_block) {
508		mem_heap_free_block_free(heap);
509	}
510#endif /* !UNIV_HOTBACKUP */
511
512	while (block != NULL) {
513		/* Store the contents of info before freeing current block
514		(it is erased in freeing) */
515
516		prev_block = UT_LIST_GET_PREV(list, block);
517
518		mem_heap_block_free(heap, block);
519
520		block = prev_block;
521	}
522}
523
524/***************************************************************//**
525NOTE: Use the corresponding macro instead of this function.
526Allocates a single buffer of memory from the dynamic memory of
527the C compiler. Is like malloc of C. The buffer must be freed
528with mem_free.
529@return	own: free storage */
530UNIV_INLINE
531void*
532mem_alloc_func(
533/*===========*/
534	ulint		n,		/*!< in: desired number of bytes */
535#ifdef UNIV_DEBUG
536	const char*	file_name,	/*!< in: file name where created */
537	ulint		line,		/*!< in: line where created */
538#endif /* UNIV_DEBUG */
539	ulint*		size)		/*!< out: allocated size in bytes,
540					or NULL */
541{
542	mem_heap_t*	heap;
543	void*		buf;
544
545	heap = mem_heap_create_at(n, file_name, line);
546
547	/* Note that as we created the first block in the heap big enough
548	for the buffer requested by the caller, the buffer will be in the
549	first block and thus we can calculate the pointer to the heap from
550	the pointer to the buffer when we free the memory buffer. */
551
552	if (size) {
553		/* Adjust the allocation to the actual size of the
554		memory block. */
555		ulint	m = mem_block_get_len(heap)
556			- mem_block_get_free(heap);
557#ifdef UNIV_MEM_DEBUG
558		m -= MEM_FIELD_HEADER_SIZE + MEM_FIELD_TRAILER_SIZE;
559#endif /* UNIV_MEM_DEBUG */
560		ut_ad(m >= n);
561		n = m;
562		*size = m;
563	}
564
565	buf = mem_heap_alloc(heap, n);
566
567	ut_a((byte*) heap == (byte*) buf - MEM_BLOCK_HEADER_SIZE
568	     - MEM_FIELD_HEADER_SIZE);
569	return(buf);
570}
571
572/***************************************************************//**
573NOTE: Use the corresponding macro instead of this function. Frees a single
574buffer of storage from the dynamic memory of the C compiler. Similar to the
575free of C. */
576UNIV_INLINE
577void
578mem_free_func(
579/*==========*/
580	void*		ptr,		/*!< in, own: buffer to be freed */
581	const char*	file_name,	/*!< in: file name where created */
582	ulint		line)		/*!< in: line where created */
583{
584	mem_heap_t*   heap;
585
586	heap = (mem_heap_t*)((byte*) ptr - MEM_BLOCK_HEADER_SIZE
587			     - MEM_FIELD_HEADER_SIZE);
588	mem_heap_free_func(heap, file_name, line);
589}
590
591/*****************************************************************//**
592Returns the space in bytes occupied by a memory heap. */
593UNIV_INLINE
594ulint
595mem_heap_get_size(
596/*==============*/
597	mem_heap_t*	heap)	/*!< in: heap */
598{
599	ulint		size	= 0;
600
601	ut_ad(mem_heap_check(heap));
602
603	size = heap->total_size;
604
605#ifndef UNIV_HOTBACKUP
606	if (heap->free_block) {
607		size += UNIV_PAGE_SIZE;
608	}
609#endif /* !UNIV_HOTBACKUP */
610
611	return(size);
612}
613
614/**********************************************************************//**
615Duplicates a NUL-terminated string.
616@return	own: a copy of the string, must be deallocated with mem_free */
617UNIV_INLINE
618char*
619mem_strdup(
620/*=======*/
621	const char*	str)	/*!< in: string to be copied */
622{
623	ulint	len = strlen(str) + 1;
624	return((char*) memcpy(mem_alloc(len), str, len));
625}
626
627/**********************************************************************//**
628Makes a NUL-terminated copy of a nonterminated string.
629@return	own: a copy of the string, must be deallocated with mem_free */
630UNIV_INLINE
631char*
632mem_strdupl(
633/*========*/
634	const char*	str,	/*!< in: string to be copied */
635	ulint		len)	/*!< in: length of str, in bytes */
636{
637	char*	s = (char*) mem_alloc(len + 1);
638	s[len] = 0;
639	return((char*) memcpy(s, str, len));
640}
641
642/**********************************************************************//**
643Makes a NUL-terminated copy of a nonterminated string,
644allocated from a memory heap.
645@return	own: a copy of the string */
646UNIV_INLINE
647char*
648mem_heap_strdupl(
649/*=============*/
650	mem_heap_t*	heap,	/*!< in: memory heap where string is allocated */
651	const char*	str,	/*!< in: string to be copied */
652	ulint		len)	/*!< in: length of str, in bytes */
653{
654	char*	s = (char*) mem_heap_alloc(heap, len + 1);
655	s[len] = 0;
656	return((char*) memcpy(s, str, len));
657}
658