/* * 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); }