• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 
12 /* This code is in the public domain.
13 ** Version: 1.1  Author: Walt Karas
14 */
15 
16 #include "hmm_intrnl.h"
17 
U(resize)18 int U(resize)(U(descriptor) *desc, void *mem, U(size_aau) n)
19 {
20     U(size_aau) i;
21     head_record *next_head_ptr;
22     head_record *head_ptr = PTR_REC_TO_HEAD(mem);
23 
24     /* Flag. */
25     int next_block_free;
26 
27     /* Convert n from desired block size in AAUs to BAUs. */
28     n += HEAD_AAUS;
29     n = DIV_ROUND_UP(n, HMM_BLOCK_ALIGN_UNIT);
30 
31     if (n < MIN_BLOCK_BAUS)
32         n = MIN_BLOCK_BAUS;
33 
34 #ifdef HMM_AUDIT_FAIL
35 
36     AUDIT_BLOCK(head_ptr)
37 
38     if (!IS_BLOCK_ALLOCATED(head_ptr))
39         HMM_AUDIT_FAIL
40 
41         if (desc->avl_tree_root)
42             AUDIT_BLOCK(PTR_REC_TO_HEAD(desc->avl_tree_root))
43 
44 #endif
45 
46             i = head_ptr->block_size;
47 
48     next_head_ptr =
49         (head_record *) BAUS_FORWARD(head_ptr, head_ptr->block_size);
50 
51     next_block_free =
52         (next_head_ptr == desc->last_freed) ||
53         !IS_BLOCK_ALLOCATED(next_head_ptr);
54 
55     if (next_block_free)
56         /* Block can expand into next free block. */
57         i += BLOCK_BAUS(next_head_ptr);
58 
59     if (n > i)
60         /* Not enough room for block to expand. */
61         return(-1);
62 
63     if (next_block_free)
64     {
65 #ifdef HMM_AUDIT_FAIL
66         AUDIT_BLOCK(next_head_ptr)
67 #endif
68 
69         if (next_head_ptr == desc->last_freed)
70             desc->last_freed = 0;
71         else
72             U(out_of_free_collection)(desc, next_head_ptr);
73 
74         next_head_ptr =
75             (head_record *) BAUS_FORWARD(head_ptr, (U(size_bau)) i);
76     }
77 
78     /* Set i to number of "extra" BAUs. */
79     i -= n;
80 
81     if (i < MIN_BLOCK_BAUS)
82         /* Not enough extra BAUs to be a block on their own, so just keep them
83         ** in the block being resized.
84         */
85     {
86         n += i;
87         i = n;
88     }
89     else
90     {
91         /* There are enough "leftover" BAUs in the next block to
92         ** form a remainder block. */
93 
94         head_record *rem_head_ptr;
95 
96         rem_head_ptr = (head_record *) BAUS_FORWARD(head_ptr, n);
97 
98         rem_head_ptr->previous_block_size = (U(size_bau)) n;
99         rem_head_ptr->block_size = (U(size_bau)) i;
100 
101         if (desc->last_freed)
102         {
103 #ifdef HMM_AUDIT_FAIL
104             AUDIT_BLOCK(desc->last_freed)
105 #endif
106 
107             U(into_free_collection)(desc, (head_record *)(desc->last_freed));
108 
109             desc->last_freed = 0;
110         }
111 
112         desc->last_freed = rem_head_ptr;
113     }
114 
115     head_ptr->block_size = (U(size_bau)) n;
116     next_head_ptr->previous_block_size = (U(size_bau)) i;
117 
118     return(0);
119 }
120