@@ -266,8 +266,8 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length)
266
266
{
267
267
size_t get_size , block_size ;
268
268
uchar * point ;
269
- reg1 USED_MEM * next = 0 ;
270
- reg2 USED_MEM * * prev ;
269
+ USED_MEM * next = 0 ;
270
+ USED_MEM * * prev ;
271
271
size_t original_length __attribute__((unused )) = length ;
272
272
DBUG_ENTER ("alloc_root" );
273
273
DBUG_PRINT ("enter" ,("root: %p" , mem_root ));
@@ -425,10 +425,10 @@ void *multi_alloc_root(MEM_ROOT *root, ...)
425
425
#if !(defined(HAVE_valgrind ) && defined(EXTRA_DEBUG ))
426
426
/** Mark all data in blocks free for reusage */
427
427
428
- static inline void mark_blocks_free (MEM_ROOT * root )
428
+ static void mark_blocks_free (MEM_ROOT * root )
429
429
{
430
- reg1 USED_MEM * next ;
431
- reg2 USED_MEM * * last ;
430
+ USED_MEM * next ;
431
+ USED_MEM * * last ;
432
432
433
433
/* iterate through (partially) free blocks, mark them free */
434
434
last = & root -> free ;
@@ -451,7 +451,6 @@ static inline void mark_blocks_free(MEM_ROOT* root)
451
451
/* Now everything is set; Indicate that nothing is used anymore */
452
452
root -> used = 0 ;
453
453
root -> first_block_usage = 0 ;
454
- root -> block_num = 4 ;
455
454
}
456
455
#endif
457
456
@@ -477,7 +476,7 @@ static inline void mark_blocks_free(MEM_ROOT* root)
477
476
478
477
void free_root (MEM_ROOT * root , myf MyFlags )
479
478
{
480
- reg1 USED_MEM * next ,* old ;
479
+ USED_MEM * next ,* old ;
481
480
DBUG_ENTER ("free_root" );
482
481
DBUG_PRINT ("enter" ,("root: %p flags: %lu" , root , MyFlags ));
483
482
@@ -567,45 +566,61 @@ void move_root(MEM_ROOT *to, MEM_ROOT *from)
567
566
from -> used = 0 ;
568
567
}
569
568
570
-
571
-
572
569
/*
573
- Remember last MEM_ROOT block.
570
+ Prepare MEM_ROOT to a later truncation. Everything allocated after
571
+ that point can be freed while keeping earlier allocations intact.
574
572
575
- This allows one to free all new allocated blocks.
573
+ For this to work we cannot allow new allocations in partially filled blocks,
574
+ so remove all non-empty blocks from the memroot. For simplicity, let's
575
+ also remove all used blocks.
576
576
*/
577
-
578
- USED_MEM * get_last_memroot_block (MEM_ROOT * root )
577
+ void root_make_savepoint (MEM_ROOT * root , MEM_ROOT_SAVEPOINT * sv )
579
578
{
580
- return root -> used ? root -> used : root -> pre_alloc ;
579
+ USED_MEM * * prev = & root -> free , * block = * prev ;
580
+ for ( ; block ; prev = & block -> next , block = * prev )
581
+ if (block -> left < block -> size - ALIGN_SIZE (sizeof (USED_MEM )))
582
+ break ;
583
+ sv -> root = root ;
584
+ sv -> free = block ;
585
+ sv -> used = root -> used ;
586
+ sv -> first_block_usage = root -> first_block_usage ;
587
+ * prev = 0 ;
588
+ root -> used = 0 ;
581
589
}
582
590
583
591
/*
584
- Free all newly allocated blocks
585
- */
592
+ Restore MEM_ROOT to the state before the savepoint was made.
586
593
587
- void free_all_new_blocks (MEM_ROOT * root , USED_MEM * last_block )
594
+ Restore old free and used lists.
595
+ Mark all new (after savepoint) used and partially used blocks free
596
+ and put them into the free list.
597
+ */
598
+ void root_free_to_savepoint (const MEM_ROOT_SAVEPOINT * sv )
588
599
{
589
- USED_MEM * old , * next ;
590
- if (!root -> used )
591
- return ; /* Nothing allocated */
592
- return ;
593
- /*
594
- Free everying allocated up to, but not including, last_block.
595
- However do not go past pre_alloc as we do not want to free
596
- that one. This should not be a problem as in almost all normal
597
- usage pre_alloc is last in the list.
598
- */
600
+ MEM_ROOT * root = sv -> root ;
601
+ USED_MEM * * prev = & root -> free , * block = * prev ;
599
602
600
- for ( next = root -> used ;
601
- next && next != last_block && next != root -> pre_alloc ; )
603
+ /* iterate through (partially) free blocks, mark them free */
604
+ for ( ; block ; prev = & block -> next , block = * prev )
602
605
{
603
- old = next ; next = next -> next ;
604
- root_free ( root , old , old -> size );
606
+ block -> left = block -> size - ALIGN_SIZE ( sizeof ( USED_MEM )) ;
607
+ TRASH_MEM ( block );
605
608
}
606
- root -> used = next ;
607
- root -> block_num = 4 ;
608
- root -> first_block_usage = 0 ;
609
+
610
+ /* Combine the free and the used list */
611
+ * prev = block = root -> used ;
612
+
613
+ /* now go through the used blocks and mark them free */
614
+ for ( ; block ; prev = & block -> next , block = * prev )
615
+ {
616
+ block -> left = block -> size - ALIGN_SIZE (sizeof (USED_MEM ));
617
+ TRASH_MEM (block );
618
+ }
619
+
620
+ /* restore free and used lists from savepoint */
621
+ * prev = sv -> free ;
622
+ root -> used = sv -> used ;
623
+ root -> first_block_usage = prev == & root -> free ? sv -> first_block_usage : 0 ;
609
624
}
610
625
611
626
/**
@@ -615,7 +630,7 @@ void free_all_new_blocks(MEM_ROOT *root, USED_MEM *last_block)
615
630
#if defined(HAVE_MMAP ) && defined(HAVE_MPROTECT ) && defined(MAP_ANONYMOUS )
616
631
void protect_root (MEM_ROOT * root , int prot )
617
632
{
618
- reg1 USED_MEM * next ,* old ;
633
+ USED_MEM * next ,* old ;
619
634
DBUG_ENTER ("protect_root" );
620
635
DBUG_PRINT ("enter" ,("root: %p prot: %d" , root , prot ));
621
636
0 commit comments