2010-05-18 17:58:33 +02:00
|
|
|
/*
|
2010-09-09 14:16:39 +02:00
|
|
|
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
|
2010-05-18 17:58:33 +02:00
|
|
|
*
|
2010-06-18 18:39:21 +02:00
|
|
|
* Use of this source code is governed by a BSD-style license
|
2010-06-04 22:19:40 +02:00
|
|
|
* that can be found in the LICENSE file in the root of the source
|
|
|
|
* tree. An additional intellectual property rights grant can be found
|
2010-06-18 18:39:21 +02:00
|
|
|
* in the file PATENTS. All contributing project authors may
|
2010-06-04 22:19:40 +02:00
|
|
|
* be found in the AUTHORS file in the root of the source tree.
|
2010-05-18 17:58:33 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/* 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
|
|
|
|
}
|
|
|
|
}
|