summaryrefslogtreecommitdiff
path: root/vpx_mem/memory_manager/hmm_shrink.c
diff options
context:
space:
mode:
Diffstat (limited to 'vpx_mem/memory_manager/hmm_shrink.c')
-rw-r--r--vpx_mem/memory_manager/hmm_shrink.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/vpx_mem/memory_manager/hmm_shrink.c b/vpx_mem/memory_manager/hmm_shrink.c
new file mode 100644
index 000000000..5ef9b233f
--- /dev/null
+++ b/vpx_mem/memory_manager/hmm_shrink.c
@@ -0,0 +1,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
+ }
+}