⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mem0pool.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 2 页
字号:
/************************************************************************The lowest-level memory management(c) 1997 Innobase OyCreated 5/12/1997 Heikki Tuuri*************************************************************************/#include "mem0pool.h"#ifdef UNIV_NONINL#include "mem0pool.ic"#endif#include "sync0sync.h"#include "ut0mem.h"#include "ut0lst.h"#include "ut0byte.h"#include "mem0mem.h"/* We would like to use also the buffer frames to allocate memory. Thiswould be desirable, because then the memory consumption of the databasewould be fixed, and we might even lock the buffer pool to the main memory.The problem here is that the buffer management routines can themselves callmemory allocation, while the buffer pool mutex is reserved.The main components of the memory consumption are:1. buffer pool,2. parsed and optimized SQL statements,3. data dictionary cache,4. log buffer,5. locks for each transaction,6. hash table for the adaptive index,7. state and buffers for each SQL query currently being executed,8. session for each user, and9. stack for each OS thread.Items 1-3 are managed by an LRU algorithm. Items 5 and 6 can potentiallyconsume very much memory. Items 7 and 8 should consume quite little memory,and the OS should take care of item 9, which too should consume little memory.A solution to the memory management:1. the buffer pool size is set separately;2. log buffer size is set separately;3. the common pool size for all the other entries, except 8, is set separately.Problems: we may waste memory if the common pool is set too big. Anotherproblem is the locks, which may take very much space in big transactions.Then the shared pool size should be set very big. We can allow locks to takespace from the buffer pool, but the SQL optimizer is then unaware of theusable size of the buffer pool. We could also combine the objects in thecommon pool and the buffers in the buffer pool into a single LRU list andmanage it uniformly, but this approach does not take into account the parsingand other costs unique to SQL statements.So, let the SQL statements and the data dictionary entries form one singleLRU list, let us call it the dictionary LRU list. The locks for a transactioncan be seen as a part of the state of the transaction. Hence, they should bestored in the common pool. We still have the problem of a very big updatetransaction, for example, which will set very many x-locks on rows, and thelocks will consume a lot of memory, say, half of the buffer pool size.Another problem is what to do if we are not able to malloc a requestedblock of memory from the common pool. Then we can truncate the LRU list ofthe dictionary cache. If it does not help, a system error results.Because 5 and 6 may potentially consume very much memory, we let them growinto the buffer pool. We may let the locks of a transaction take framesfrom the buffer pool, when the corresponding memory heap block has grown tothe size of a buffer frame. Similarly for the hash node cells of the locks,and for the adaptive index. Thus, for each individual transaction, its lockscan occupy at most about the size of the buffer frame of memory in the commonpool, and after that its locks will grow into the buffer pool. *//* Mask used to extract the free bit from area->size */#define MEM_AREA_FREE	1/* The smallest memory area total size */#define MEM_AREA_MIN_SIZE	(2 * MEM_AREA_EXTRA_SIZE)/* Data structure for a memory pool. The space is allocated using the buddyalgorithm, where free list i contains areas of size 2 to power i. */struct mem_pool_struct{	byte*		buf;		/* memory pool */	ulint		size;		/* memory common pool size */	ulint		reserved;	/* amount of currently allocated					memory */	mutex_t		mutex;		/* mutex protecting this struct */	UT_LIST_BASE_NODE_T(mem_area_t)			free_list[64];	/* lists of free memory areas: an					area is put to the list whose number					is the 2-logarithm of the area size */};/* The common memory pool */mem_pool_t*	mem_comm_pool	= NULL;/* We use this counter to check that the mem pool mutex does not leak;this is to track a strange assertion failure reported atmysql@lists.mysql.com */ulint		mem_n_threads_inside		= 0;/************************************************************************Reserves the mem pool mutex. */voidmem_pool_mutex_enter(void)/*======================*/{	mutex_enter(&(mem_comm_pool->mutex));}/************************************************************************Releases the mem pool mutex. */voidmem_pool_mutex_exit(void)/*=====================*/{	mutex_exit(&(mem_comm_pool->mutex));}/************************************************************************Returns memory area size. */UNIV_INLINEulintmem_area_get_size(/*==============*/				/* out: size */	mem_area_t*	area)	/* in: area */{	return(area->size_and_free & ~MEM_AREA_FREE);}/************************************************************************Sets memory area size. */UNIV_INLINEvoidmem_area_set_size(/*==============*/	mem_area_t*	area,	/* in: area */	ulint		size)	/* in: size */{	area->size_and_free = (area->size_and_free & MEM_AREA_FREE)				| size;}/************************************************************************Returns memory area free bit. */UNIV_INLINEiboolmem_area_get_free(/*==============*/				/* out: TRUE if free */	mem_area_t*	area)	/* in: area */{	ut_ad(TRUE == MEM_AREA_FREE);	return(area->size_and_free & MEM_AREA_FREE);}/************************************************************************Sets memory area free bit. */UNIV_INLINEvoidmem_area_set_free(/*==============*/	mem_area_t*	area,	/* in: area */	ibool		free)	/* in: free bit value */{	ut_ad(TRUE == MEM_AREA_FREE);		area->size_and_free = (area->size_and_free & ~MEM_AREA_FREE)				| free;}/************************************************************************Creates a memory pool. */mem_pool_t*mem_pool_create(/*============*/			/* out: memory pool */	ulint	size)	/* in: pool size in bytes */{	mem_pool_t*	pool;	mem_area_t*	area;	ulint		i;	ulint		used;	ut_a(size > 10000);		pool = ut_malloc(sizeof(mem_pool_t));	/* We do not set the memory to zero (FALSE) in the pool,	but only when allocated at a higher level in mem0mem.c.	This is to avoid masking useful Purify warnings. */	pool->buf = ut_malloc_low(size, FALSE, TRUE);	pool->size = size;	mutex_create(&(pool->mutex));	mutex_set_level(&(pool->mutex), SYNC_MEM_POOL);	/* Initialize the free lists */	for (i = 0; i < 64; i++) {		UT_LIST_INIT(pool->free_list[i]);	}	used = 0;	while (size - used >= MEM_AREA_MIN_SIZE) {		i = ut_2_log(size - used);		if (ut_2_exp(i) > size - used) {			/* ut_2_log rounds upward */					i--;		}		area = (mem_area_t*)(pool->buf + used);		mem_area_set_size(area, ut_2_exp(i));		mem_area_set_free(area, TRUE);		UT_LIST_ADD_FIRST(free_list, pool->free_list[i], area);		used = used + ut_2_exp(i);	}	ut_ad(size >= used);	pool->reserved = 0;		return(pool);}/************************************************************************Fills the specified free list. */staticiboolmem_pool_fill_free_list(/*====================*/				/* out: TRUE if we were able to insert a				block to the free list */	ulint		i,	/* in: free list index */	mem_pool_t*	pool)	/* in: memory pool */{	mem_area_t*	area;	mem_area_t*	area2;	ibool		ret;#ifdef UNIV_SYNC_DEBUG	ut_ad(mutex_own(&(pool->mutex)));#endif /* UNIV_SYNC_DEBUG */	if (i >= 63) {		/* We come here when we have run out of space in the		memory pool: */     		return(FALSE);	}	area = UT_LIST_GET_FIRST(pool->free_list[i + 1]);	if (area == NULL) {	        if (UT_LIST_GET_LEN(pool->free_list[i + 1]) > 0) {	    		ut_print_timestamp(stderr);	                fprintf(stderr,"  InnoDB: Error: mem pool free list %lu length is %lu\n""InnoDB: though the list is empty!\n",			(ulong) i + 1,			(ulong) UT_LIST_GET_LEN(pool->free_list[i + 1]));		}		ret = mem_pool_fill_free_list(i + 1, pool);		if (ret == FALSE) {			return(FALSE);		}		area = UT_LIST_GET_FIRST(pool->free_list[i + 1]);	}	if (UT_LIST_GET_LEN(pool->free_list[i + 1]) == 0) {	        mem_analyze_corruption((byte*)area);		ut_error;	}	UT_LIST_REMOVE(free_list, pool->free_list[i + 1], area);	area2 = (mem_area_t*)(((byte*)area) + ut_2_exp(i));	mem_area_set_size(area2, ut_2_exp(i));	mem_area_set_free(area2, TRUE);	UT_LIST_ADD_FIRST(free_list, pool->free_list[i], area2);		mem_area_set_size(area, ut_2_exp(i));	UT_LIST_ADD_FIRST(free_list, pool->free_list[i], area);	return(TRUE);}	/************************************************************************Allocates memory from a pool. NOTE: This low-level function should only beused in mem0mem.*! */void*mem_area_alloc(/*===========*/				/* out, own: allocated memory buffer */	ulint		size,	/* in: allocated size in bytes; for optimum				space usage, the size should be a power of 2				minus MEM_AREA_EXTRA_SIZE */	mem_pool_t*	pool)	/* in: memory pool */{	mem_area_t*	area;	ulint		n;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -