Home | History | Annotate | Download | only in memory_manager
      1 /*
      2  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 
     12 /* This code is in the public domain.
     13 ** Version: 1.1  Author: Walt Karas
     14 */
     15 
     16 #include "hmm_intrnl.h"
     17 
     18 int U(resize)(U(descriptor) *desc, void *mem, U(size_aau) n)
     19 {
     20     U(size_aau) i;
     21     head_record *next_head_ptr;
     22     head_record *head_ptr = PTR_REC_TO_HEAD(mem);
     23 
     24     /* Flag. */
     25     int next_block_free;
     26 
     27     /* Convert n from desired block size in AAUs to BAUs. */
     28     n += HEAD_AAUS;
     29     n = DIV_ROUND_UP(n, HMM_BLOCK_ALIGN_UNIT);
     30 
     31     if (n < MIN_BLOCK_BAUS)
     32         n = MIN_BLOCK_BAUS;
     33 
     34 #ifdef HMM_AUDIT_FAIL
     35 
     36     AUDIT_BLOCK(head_ptr)
     37 
     38     if (!IS_BLOCK_ALLOCATED(head_ptr))
     39         HMM_AUDIT_FAIL
     40 
     41         if (desc->avl_tree_root)
     42             AUDIT_BLOCK(PTR_REC_TO_HEAD(desc->avl_tree_root))
     43 
     44 #endif
     45 
     46             i = head_ptr->block_size;
     47 
     48     next_head_ptr =
     49         (head_record *) BAUS_FORWARD(head_ptr, head_ptr->block_size);
     50 
     51     next_block_free =
     52         (next_head_ptr == desc->last_freed) ||
     53         !IS_BLOCK_ALLOCATED(next_head_ptr);
     54 
     55     if (next_block_free)
     56         /* Block can expand into next free block. */
     57         i += BLOCK_BAUS(next_head_ptr);
     58 
     59     if (n > i)
     60         /* Not enough room for block to expand. */
     61         return(-1);
     62 
     63     if (next_block_free)
     64     {
     65 #ifdef HMM_AUDIT_FAIL
     66         AUDIT_BLOCK(next_head_ptr)
     67 #endif
     68 
     69         if (next_head_ptr == desc->last_freed)
     70             desc->last_freed = 0;
     71         else
     72             U(out_of_free_collection)(desc, next_head_ptr);
     73 
     74         next_head_ptr =
     75             (head_record *) BAUS_FORWARD(head_ptr, (U(size_bau)) i);
     76     }
     77 
     78     /* Set i to number of "extra" BAUs. */
     79     i -= n;
     80 
     81     if (i < MIN_BLOCK_BAUS)
     82         /* Not enough extra BAUs to be a block on their own, so just keep them
     83         ** in the block being resized.
     84         */
     85     {
     86         n += i;
     87         i = n;
     88     }
     89     else
     90     {
     91         /* There are enough "leftover" BAUs in the next block to
     92         ** form a remainder block. */
     93 
     94         head_record *rem_head_ptr;
     95 
     96         rem_head_ptr = (head_record *) BAUS_FORWARD(head_ptr, n);
     97 
     98         rem_head_ptr->previous_block_size = (U(size_bau)) n;
     99         rem_head_ptr->block_size = (U(size_bau)) i;
    100 
    101         if (desc->last_freed)
    102         {
    103 #ifdef HMM_AUDIT_FAIL
    104             AUDIT_BLOCK(desc->last_freed)
    105 #endif
    106 
    107             U(into_free_collection)(desc, (head_record *)(desc->last_freed));
    108 
    109             desc->last_freed = 0;
    110         }
    111 
    112         desc->last_freed = rem_head_ptr;
    113     }
    114 
    115     head_ptr->block_size = (U(size_bau)) n;
    116     next_head_ptr->previous_block_size = (U(size_bau)) i;
    117 
    118     return(0);
    119 }
    120