summaryrefslogtreecommitdiff
path: root/mysys/my_alloc.c
diff options
context:
space:
mode:
authorunknown <konstantin@mysql.com>2004-02-02 23:01:58 +0300
committerunknown <konstantin@mysql.com>2004-02-02 23:01:58 +0300
commite0b0ec6b2c98f05547018655b6030a8d62bc511f (patch)
treef3ac440023264a510364912fe7f9dbaa97266806 /mysys/my_alloc.c
parent883f11b68c402b106dbff2542435782a8af3b55d (diff)
downloadmariadb-git-e0b0ec6b2c98f05547018655b6030a8d62bc511f.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.c66
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)