diff options
author | unknown <konstantin@mysql.com> | 2004-02-02 23:01:58 +0300 |
---|---|---|
committer | unknown <konstantin@mysql.com> | 2004-02-02 23:01:58 +0300 |
commit | 72a84159410872c20a958d272df0dc0a4478476a (patch) | |
tree | f3ac440023264a510364912fe7f9dbaa97266806 /mysys/my_alloc.c | |
parent | 1ad277ca4d15a846e98f87680b008f625b4dcdce (diff) | |
download | mariadb-git-72a84159410872c20a958d272df0dc0a4478476a.tar.gz |
Proposed (version #2) fix for bug #1948:
"system variable query_prealloc_size can be only global"
include/my_sys.h:
Fix for bug #1948:
- added reset_root_defaults function declaration
mysys/my_alloc.c:
Fix for bug #1948:
- implementation and description of reset_root_defaults
sql/set_var.cc:
Fix for bug #1948:
- fix_thd_mem_root and fix_trans_mem_root after update triggers
implemented for variables query_prealloc_size, query_alloc_block_size,
trans_prealloc_size, trans_alloc_block_size
Diffstat (limited to 'mysys/my_alloc.c')
-rw-r--r-- | mysys/my_alloc.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index 4d3b0604984..d03ec5841af 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -47,6 +47,72 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size, #endif } +/* + SYNOPSIS + reset_root_defaults() + mem_root memory root to change defaults of + block_size new value of block size. Must be + greater than ~68 bytes (the exact value depends on + platform and compilation flags) + pre_alloc_size new size of preallocated block. If not zero, + must be equal to or greater than block size, + otherwise means 'no prealloc'. + DESCRIPTION + Function aligns and assigns new value to block size; then it tries to + reuse one of existing blocks as prealloc block, or malloc new one of + requested size. If no blocks can be reused, all unused blocks are freed + before allocation. + */ + +void reset_root_defaults(MEM_ROOT *mem_root, uint block_size, + uint pre_alloc_size) +{ + mem_root->block_size= block_size-MALLOC_OVERHEAD-sizeof(USED_MEM)-8; +#if !(defined(HAVE_purify) && defined(EXTRA_DEBUG)) + if (pre_alloc_size) + { + uint size= pre_alloc_size + ALIGN_SIZE(sizeof(USED_MEM)); + if (!mem_root->pre_alloc || mem_root->pre_alloc->size != size) + { + USED_MEM *mem, **prev= &mem_root->free; + /* + Free unused blocks, so that consequent calls + to reset_root_defaults won't eat away memory. + */ + while (*prev) + { + mem= *prev; + if (mem->size == size) + { + /* We found a suitable block, no need to do anything else */ + mem_root->pre_alloc= mem; + return; + } + if (mem->left + ALIGN_SIZE(sizeof(USED_MEM)) == mem->size) + { + /* remove block from the list and free it */ + *prev= mem->next; + my_free((gptr) mem, MYF(0)); + } + else + prev= &mem->next; + } + /* Allocate new prealloc block and add it to the end of free list */ + if ((mem= (USED_MEM *) my_malloc(size, MYF(0)))) + { + mem->size= size; + mem->left= pre_alloc_size; + mem->next= *prev; + *prev= mem_root->pre_alloc= mem; + } + } + } + else +#endif + mem_root->pre_alloc= 0; +} + + gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size) { #if defined(HAVE_purify) && defined(EXTRA_DEBUG) |