Beispiel #1
0
void
mem_heap_block_free(
/*================*/
	mem_heap_t*	heap,	/* in: heap */
	mem_block_t*	block)	/* in: block to free */
{
	ulint	type;
	ulint	len;
	ibool	init_block;	

	if (block->magic_n != MEM_BLOCK_MAGIC_N) {
		mem_analyze_corruption((byte*)block);
	}

	UT_LIST_REMOVE(list, heap->base, block);
		
#ifdef MEM_PERIODIC_CHECK	
	mem_pool_mutex_enter();

	UT_LIST_REMOVE(mem_block_list, mem_block_list, block);

	mem_pool_mutex_exit();
#endif
	type = heap->type;
	len = block->len;
	init_block = block->init_block;
	block->magic_n = MEM_FREED_BLOCK_MAGIC_N;
	
#ifdef UNIV_MEM_DEBUG
	/* In the debug version we set the memory to a random combination
	of hex 0xDE and 0xAD. */

	mem_erase_buf((byte*)block, len);

#endif

	if (init_block) {
		/* Do not have to free: do nothing */

	} else if (type == MEM_HEAP_DYNAMIC) {

		mem_area_free(block, mem_comm_pool);
	} else {
		ut_ad(type & MEM_HEAP_BUFFER);

		if (len >= UNIV_PAGE_SIZE / 2) {
			buf_frame_free((byte*)block);
		} else {
			mem_area_free(block, mem_comm_pool);
		}
	}
}
Beispiel #2
0
/******************************************************************//**
Frees a block from a memory heap. */
UNIV_INTERN
void
mem_heap_block_free(
/*================*/
	mem_heap_t*	heap,	/*!< in: heap */
	mem_block_t*	block)	/*!< in: block to free */
{
	ulint		type;
	ulint		len;
#ifndef UNIV_HOTBACKUP
	buf_block_t*	buf_block	= block->buf_block;
#endif /* !UNIV_HOTBACKUP */

	if (block->magic_n != MEM_BLOCK_MAGIC_N) {
		mem_analyze_corruption(block);
	}

	UT_LIST_REMOVE(list, heap->base, block);

#ifdef MEM_PERIODIC_CHECK
	mem_pool_mutex_enter();

	UT_LIST_REMOVE(mem_block_list, mem_block_list, block);

	mem_pool_mutex_exit();
#endif
	type = heap->type;
	len = block->len;
	block->magic_n = MEM_FREED_BLOCK_MAGIC_N;

#ifdef UNIV_MEM_DEBUG
	/* In the debug version we set the memory to a random combination
	of hex 0xDE and 0xAD. */

	mem_erase_buf((byte*)block, len);
#else /* UNIV_MEM_DEBUG */
	UNIV_MEM_ASSERT_AND_FREE(block, len);
#endif /* UNIV_MEM_DEBUG */

#ifndef UNIV_HOTBACKUP
	if (type == MEM_HEAP_DYNAMIC || len < UNIV_PAGE_SIZE / 2) {

		ut_ad(!buf_block);
		mem_area_free(block, mem_comm_pool);
	} else {
		ut_ad(type & MEM_HEAP_BUFFER);

		buf_block_free(buf_block);
	}
#else /* !UNIV_HOTBACKUP */
	ut_free(block);
#endif /* !UNIV_HOTBACKUP */
}
Beispiel #3
0
/********************************************************************//**
Frees memory to a pool. */
UNIV_INTERN
void
mem_area_free(
/*==========*/
	void*		ptr,	/*!< in, own: pointer to allocated memory
				buffer */
	mem_pool_t*	pool)	/*!< in: memory pool */
{
	mem_area_t*	area;
	mem_area_t*	buddy;
	void*		new_ptr;
	ulint		size;
	ulint		n;

	if (UNIV_LIKELY(srv_use_sys_malloc)) {
		free(ptr);

		return;
	}

	/* It may be that the area was really allocated from the OS with
	regular malloc: check if ptr points within our memory pool */

	if ((byte*)ptr < pool->buf || (byte*)ptr >= pool->buf + pool->size) {
		ut_free(ptr);

		return;
	}

	area = (mem_area_t*) (((byte*)ptr) - MEM_AREA_EXTRA_SIZE);

	if (mem_area_get_free(area)) {
		fprintf(stderr,
			"InnoDB: Error: Freeing element to mem pool"
			" free list though the\n"
			"InnoDB: element is marked free!\n");

		mem_analyze_corruption(area);
		ut_error;
	}

	size = mem_area_get_size(area);
	UNIV_MEM_FREE(ptr, size - MEM_AREA_EXTRA_SIZE);

	if (size == 0) {
		fprintf(stderr,
			"InnoDB: Error: Mem area size is 0. Possibly a"
			" memory overrun of the\n"
			"InnoDB: previous allocated area!\n");

		mem_analyze_corruption(area);
		ut_error;
	}

#ifdef UNIV_LIGHT_MEM_DEBUG
	if (((byte*)area) + size < pool->buf + pool->size) {

		ulint	next_size;

		next_size = mem_area_get_size(
			(mem_area_t*)(((byte*)area) + size));
		if (UNIV_UNLIKELY(!next_size || !ut_is_2pow(next_size))) {
			fprintf(stderr,
				"InnoDB: Error: Memory area size %lu,"
				" next area size %lu not a power of 2!\n"
				"InnoDB: Possibly a memory overrun of"
				" the buffer being freed here.\n",
				(ulong) size, (ulong) next_size);
			mem_analyze_corruption(area);

			ut_error;
		}
	}
#endif
	buddy = mem_area_get_buddy(area, size, pool);

	n = ut_2_log(size);

	mem_pool_mutex_enter(pool);
	mem_n_threads_inside++;

	ut_a(mem_n_threads_inside == 1);

	if (buddy && mem_area_get_free(buddy)
	    && (size == mem_area_get_size(buddy))) {

		/* The buddy is in a free list */

		if ((byte*)buddy < (byte*)area) {
			new_ptr = ((byte*)buddy) + MEM_AREA_EXTRA_SIZE;

			mem_area_set_size(buddy, 2 * size);
			mem_area_set_free(buddy, FALSE);
		} else {
			new_ptr = ptr;

			mem_area_set_size(area, 2 * size);
		}

		/* Remove the buddy from its free list and merge it to area */

		UT_LIST_REMOVE(free_list, pool->free_list[n], buddy);

		pool->reserved += ut_2_exp(n);

		mem_n_threads_inside--;
		mem_pool_mutex_exit(pool);

		mem_area_free(new_ptr, pool);

		return;
	} else {
		UT_LIST_ADD_FIRST(free_list, pool->free_list[n], area);

		mem_area_set_free(area, TRUE);

		ut_ad(pool->reserved >= size);

		pool->reserved -= size;
	}

	mem_n_threads_inside--;
	mem_pool_mutex_exit(pool);

	ut_ad(mem_pool_validate(pool));
}