115 строки
2.6 KiB
C
115 строки
2.6 KiB
C
/*
|
|
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. 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"
|
|
|
|
int U(resize)(U(descriptor) *desc, void *mem, U(size_aau) n) {
|
|
U(size_aau) i;
|
|
head_record *next_head_ptr;
|
|
head_record *head_ptr = PTR_REC_TO_HEAD(mem);
|
|
|
|
/* Flag. */
|
|
int next_block_free;
|
|
|
|
/* Convert n from desired block size in AAUs to BAUs. */
|
|
n += HEAD_AAUS;
|
|
n = DIV_ROUND_UP(n, HMM_BLOCK_ALIGN_UNIT);
|
|
|
|
if (n < MIN_BLOCK_BAUS)
|
|
n = MIN_BLOCK_BAUS;
|
|
|
|
#ifdef HMM_AUDIT_FAIL
|
|
|
|
AUDIT_BLOCK(head_ptr)
|
|
|
|
if (!IS_BLOCK_ALLOCATED(head_ptr))
|
|
HMM_AUDIT_FAIL
|
|
|
|
if (desc->avl_tree_root)
|
|
AUDIT_BLOCK(PTR_REC_TO_HEAD(desc->avl_tree_root))
|
|
|
|
#endif
|
|
|
|
i = head_ptr->block_size;
|
|
|
|
next_head_ptr =
|
|
(head_record *) BAUS_FORWARD(head_ptr, head_ptr->block_size);
|
|
|
|
next_block_free =
|
|
(next_head_ptr == desc->last_freed) ||
|
|
!IS_BLOCK_ALLOCATED(next_head_ptr);
|
|
|
|
if (next_block_free)
|
|
/* Block can expand into next free block. */
|
|
i += BLOCK_BAUS(next_head_ptr);
|
|
|
|
if (n > i)
|
|
/* Not enough room for block to expand. */
|
|
return(-1);
|
|
|
|
if (next_block_free) {
|
|
#ifdef HMM_AUDIT_FAIL
|
|
AUDIT_BLOCK(next_head_ptr)
|
|
#endif
|
|
|
|
if (next_head_ptr == desc->last_freed)
|
|
desc->last_freed = 0;
|
|
else
|
|
U(out_of_free_collection)(desc, next_head_ptr);
|
|
|
|
next_head_ptr =
|
|
(head_record *) BAUS_FORWARD(head_ptr, (U(size_bau)) i);
|
|
}
|
|
|
|
/* Set i to number of "extra" BAUs. */
|
|
i -= n;
|
|
|
|
if (i < MIN_BLOCK_BAUS)
|
|
/* Not enough extra BAUs to be a block on their own, so just keep them
|
|
** in the block being resized.
|
|
*/
|
|
{
|
|
n += i;
|
|
i = n;
|
|
} else {
|
|
/* There are enough "leftover" BAUs in the next block to
|
|
** form a remainder block. */
|
|
|
|
head_record *rem_head_ptr;
|
|
|
|
rem_head_ptr = (head_record *) BAUS_FORWARD(head_ptr, n);
|
|
|
|
rem_head_ptr->previous_block_size = (U(size_bau)) n;
|
|
rem_head_ptr->block_size = (U(size_bau)) i;
|
|
|
|
if (desc->last_freed) {
|
|
#ifdef HMM_AUDIT_FAIL
|
|
AUDIT_BLOCK(desc->last_freed)
|
|
#endif
|
|
|
|
U(into_free_collection)(desc, (head_record *)(desc->last_freed));
|
|
|
|
desc->last_freed = 0;
|
|
}
|
|
|
|
desc->last_freed = rem_head_ptr;
|
|
}
|
|
|
|
head_ptr->block_size = (U(size_bau)) n;
|
|
next_head_ptr->previous_block_size = (U(size_bau)) i;
|
|
|
|
return(0);
|
|
}
|