summaryrefslogtreecommitdiffstats
path: root/vpx_mem/memory_manager/hmm_shrink.c
blob: 5ef9b233f3cec4f61edc7154bdd6c9b49d74f698 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*
 *  Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license and patent
 *  grant that can be found in the LICENSE file in the root of the source
 *  tree. All contributing project authors may be found in the AUTHORS
 *  file in the root of the source tree.
 */


/* This code is in the public domain.
** Version: 1.1  Author: Walt Karas
*/

#include "hmm_intrnl.h"

void U(shrink_chunk)(U(descriptor) *desc, U(size_bau) n_baus_to_shrink)
{
    head_record *dummy_end_block = (head_record *)
                                   BAUS_BACKWARD(desc->end_of_shrinkable_chunk, DUMMY_END_BLOCK_BAUS);

#ifdef HMM_AUDIT_FAIL

    if (dummy_end_block->block_size != 0)
        /* Chunk does not have valid dummy end block. */
        HMM_AUDIT_FAIL

#endif

        if (n_baus_to_shrink)
        {
            head_record *last_block = (head_record *)
                                      BAUS_BACKWARD(
                                          dummy_end_block, dummy_end_block->previous_block_size);

#ifdef HMM_AUDIT_FAIL
            AUDIT_BLOCK(last_block)
#endif

            if (last_block == desc->last_freed)
            {
                U(size_bau) bs = BLOCK_BAUS(last_block);

                /* Chunk will not be shrunk out of existence if
                ** 1.  There is at least one allocated block in the chunk
                **     and the amount to shrink is exactly the size of the
                **     last block, OR
                ** 2.  After the last block is shrunk, there will be enough
                **     BAUs left in it to form a minimal size block. */
                int chunk_will_survive =
                    (PREV_BLOCK_BAUS(last_block) && (n_baus_to_shrink == bs)) ||
                    (n_baus_to_shrink <= (U(size_bau))(bs - MIN_BLOCK_BAUS));

                if (chunk_will_survive ||
                    (!PREV_BLOCK_BAUS(last_block) &&
                     (n_baus_to_shrink ==
                      (U(size_bau))(bs + DUMMY_END_BLOCK_BAUS))))
                {
                    desc->last_freed = 0;

                    if (chunk_will_survive)
                    {
                        bs -= n_baus_to_shrink;

                        if (bs)
                        {
                            /* The last (non-dummy) block was not completely
                            ** eliminated by the shrink. */

                            last_block->block_size = bs;

                            /* Create new dummy end record.
                            */
                            dummy_end_block =
                                (head_record *) BAUS_FORWARD(last_block, bs);
                            dummy_end_block->previous_block_size = bs;
                            dummy_end_block->block_size = 0;

#ifdef HMM_AUDIT_FAIL

                            if (desc->avl_tree_root)
                                AUDIT_BLOCK(PTR_REC_TO_HEAD(desc->avl_tree_root))
#endif

                                U(into_free_collection)(desc, last_block);
                        }
                        else
                        {
                            /* The last (non-dummy) block was completely
                            ** eliminated by the shrink.  Make its head
                            ** the new dummy end block.
                            */
                            last_block->block_size = 0;
                            last_block->previous_block_size &= ~HIGH_BIT_BAU_SIZE;
                        }
                    }
                }

#ifdef HMM_AUDIT_FAIL
                else
                    HMM_AUDIT_FAIL
#endif
                }

#ifdef HMM_AUDIT_FAIL
            else
                HMM_AUDIT_FAIL
#endif
            }
}