1474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org/*
2474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org *
4474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org *  Use of this source code is governed by a BSD-style license
5474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org *  that can be found in the LICENSE file in the root of the source
6474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org *  tree. An additional intellectual property rights grant can be found
7474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org *  in the file PATENTS.  All contributing project authors may
8474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org *  be found in the AUTHORS file in the root of the source tree.
9474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org */
10474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
11474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
12474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org/* This code is in the public domain.
13474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org** Version: 1.1  Author: Walt Karas
14474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org*/
15474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
16474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "hmm_intrnl.h"
17474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
186fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgint U(resize)(U(descriptor) *desc, void *mem, U(size_aau) n) {
196fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  U(size_aau) i;
206fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  head_record *next_head_ptr;
216fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  head_record *head_ptr = PTR_REC_TO_HEAD(mem);
22474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
236fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  /* Flag. */
246fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  int next_block_free;
25474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
266fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  /* Convert n from desired block size in AAUs to BAUs. */
276fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  n += HEAD_AAUS;
286fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  n = DIV_ROUND_UP(n, HMM_BLOCK_ALIGN_UNIT);
29474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
306fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  if (n < MIN_BLOCK_BAUS)
316fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    n = MIN_BLOCK_BAUS;
32474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
33474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#ifdef HMM_AUDIT_FAIL
34474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
356fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  AUDIT_BLOCK(head_ptr)
36474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
376fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  if (!IS_BLOCK_ALLOCATED(head_ptr))
386fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    HMM_AUDIT_FAIL
39474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
406fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    if (desc->avl_tree_root)
416fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      AUDIT_BLOCK(PTR_REC_TO_HEAD(desc->avl_tree_root))
42474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
43474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#endif
44474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
456fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      i = head_ptr->block_size;
46474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
476fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  next_head_ptr =
486fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    (head_record *) BAUS_FORWARD(head_ptr, head_ptr->block_size);
49474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
506fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  next_block_free =
516fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    (next_head_ptr == desc->last_freed) ||
526fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    !IS_BLOCK_ALLOCATED(next_head_ptr);
53474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
546fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  if (next_block_free)
556fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    /* Block can expand into next free block. */
566fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    i += BLOCK_BAUS(next_head_ptr);
57474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
586fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  if (n > i)
596fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    /* Not enough room for block to expand. */
606fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    return(-1);
61474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
626fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  if (next_block_free) {
63474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#ifdef HMM_AUDIT_FAIL
646fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    AUDIT_BLOCK(next_head_ptr)
65474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#endif
66474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
676fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    if (next_head_ptr == desc->last_freed)
686fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      desc->last_freed = 0;
696fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    else
706fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      U(out_of_free_collection)(desc, next_head_ptr);
71474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
726fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    next_head_ptr =
736fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      (head_record *) BAUS_FORWARD(head_ptr, (U(size_bau)) i);
746fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  }
75474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
766fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  /* Set i to number of "extra" BAUs. */
776fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  i -= n;
78474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
796fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  if (i < MIN_BLOCK_BAUS)
806fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    /* Not enough extra BAUs to be a block on their own, so just keep them
816fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    ** in the block being resized.
826fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    */
836fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  {
846fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    n += i;
856fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    i = n;
866fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  } else {
876fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    /* There are enough "leftover" BAUs in the next block to
886fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    ** form a remainder block. */
89474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
906fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    head_record *rem_head_ptr;
91474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
926fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    rem_head_ptr = (head_record *) BAUS_FORWARD(head_ptr, n);
93474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
946fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    rem_head_ptr->previous_block_size = (U(size_bau)) n;
956fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    rem_head_ptr->block_size = (U(size_bau)) i;
96474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
976fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    if (desc->last_freed) {
98474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#ifdef HMM_AUDIT_FAIL
996fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      AUDIT_BLOCK(desc->last_freed)
100474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#endif
101474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
1026fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      U(into_free_collection)(desc, (head_record *)(desc->last_freed));
103474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
1046fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      desc->last_freed = 0;
105474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
106474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
1076fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    desc->last_freed = rem_head_ptr;
1086fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  }
1096fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
1106fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  head_ptr->block_size = (U(size_bau)) n;
1116fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  next_head_ptr->previous_block_size = (U(size_bau)) i;
112474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
1136fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  return(0);
114474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
115