/* * 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 */ #ifndef HMM_INTRNL_H_ #define HMM_INTRNL_H_ #ifdef __uClinux__ # include <lddk.h> #endif #include "heapmm.h" #define U(BASE) HMM_UNIQUE(BASE) /* Mask of high bit of variable of size_bau type. */ #define HIGH_BIT_BAU_SIZE \ ((U(size_bau)) ~ (((U(size_bau)) ~ (U(size_bau)) 0) >> 1)) /* Add a given number of AAUs to pointer. */ #define AAUS_FORWARD(PTR, AAU_OFFSET) \ (((char *) (PTR)) + ((AAU_OFFSET) * ((U(size_aau)) HMM_ADDR_ALIGN_UNIT))) /* Subtract a given number of AAUs from pointer. */ #define AAUS_BACKWARD(PTR, AAU_OFFSET) \ (((char *) (PTR)) - ((AAU_OFFSET) * ((U(size_aau)) HMM_ADDR_ALIGN_UNIT))) /* Add a given number of BAUs to a pointer. */ #define BAUS_FORWARD(PTR, BAU_OFFSET) \ AAUS_FORWARD((PTR), (BAU_OFFSET) * ((U(size_aau)) HMM_BLOCK_ALIGN_UNIT)) /* Subtract a given number of BAUs to a pointer. */ #define BAUS_BACKWARD(PTR, BAU_OFFSET) \ AAUS_BACKWARD((PTR), (BAU_OFFSET) * ((U(size_aau)) HMM_BLOCK_ALIGN_UNIT)) typedef struct head_struct { /* Sizes in Block Alignment Units. */ HMM_UNIQUE(size_bau) previous_block_size, block_size; } head_record; typedef struct ptr_struct { struct ptr_struct *self, *prev, *next; } ptr_record; /* Divide and round up any fraction to the next whole number. */ #define DIV_ROUND_UP(NUMER, DENOM) (((NUMER) + (DENOM) - 1) / (DENOM)) /* Number of AAUs in a block head. */ #define HEAD_AAUS DIV_ROUND_UP(sizeof(head_record), HMM_ADDR_ALIGN_UNIT) /* Number of AAUs in a block pointer record. */ #define PTR_RECORD_AAUS DIV_ROUND_UP(sizeof(ptr_record), HMM_ADDR_ALIGN_UNIT) /* Number of BAUs in a dummy end record (at end of chunk). */ #define DUMMY_END_BLOCK_BAUS DIV_ROUND_UP(HEAD_AAUS, HMM_BLOCK_ALIGN_UNIT) /* Minimum number of BAUs in a block (allowing room for the pointer record. */ #define MIN_BLOCK_BAUS \ DIV_ROUND_UP(HEAD_AAUS + PTR_RECORD_AAUS, HMM_BLOCK_ALIGN_UNIT) /* Return number of BAUs in block (masking off high bit containing block ** status). */ #define BLOCK_BAUS(HEAD_PTR) \ (((head_record *) (HEAD_PTR))->block_size & ~HIGH_BIT_BAU_SIZE) /* Return number of BAUs in previous block (masking off high bit containing ** block status). */ #define PREV_BLOCK_BAUS(HEAD_PTR) \ (((head_record *) (HEAD_PTR))->previous_block_size & ~HIGH_BIT_BAU_SIZE) /* Set number of BAUs in previous block, preserving high bit containing ** block status. */ #define SET_PREV_BLOCK_BAUS(HEAD_PTR, N_BAUS) \ { register head_record *h_ptr = (head_record *) (HEAD_PTR); \ h_ptr->previous_block_size &= HIGH_BIT_BAU_SIZE; \ h_ptr->previous_block_size |= (N_BAUS); } /* Convert pointer to pointer record of block to pointer to block's head ** record. */ #define PTR_REC_TO_HEAD(PTR_REC_PTR) \ ((head_record *) AAUS_BACKWARD(PTR_REC_PTR, HEAD_AAUS)) /* Convert pointer to block head to pointer to block's pointer record. */ #define HEAD_TO_PTR_REC(HEAD_PTR) \ ((ptr_record *) AAUS_FORWARD(HEAD_PTR, HEAD_AAUS)) /* Returns non-zero if block is allocated. */ #define IS_BLOCK_ALLOCATED(HEAD_PTR) \ (((((head_record *) (HEAD_PTR))->block_size | \ ((head_record *) (HEAD_PTR))->previous_block_size) & \ HIGH_BIT_BAU_SIZE) == 0) #define MARK_BLOCK_ALLOCATED(HEAD_PTR) \ { register head_record *h_ptr = (head_record *) (HEAD_PTR); \ h_ptr->block_size &= ~HIGH_BIT_BAU_SIZE; \ h_ptr->previous_block_size &= ~HIGH_BIT_BAU_SIZE; } /* Mark a block as free when it is not the first block in a bin (and ** therefore not a node in the AVL tree). */ #define MARK_SUCCESSIVE_BLOCK_IN_FREE_BIN(HEAD_PTR) \ { register head_record *h_ptr = (head_record *) (HEAD_PTR); \ h_ptr->block_size |= HIGH_BIT_BAU_SIZE; } /* Prototypes for internal functions implemented in one file and called in ** another. */ void U(into_free_collection)(U(descriptor) *desc, head_record *head_ptr); void U(out_of_free_collection)(U(descriptor) *desc, head_record *head_ptr); void *U(alloc_from_bin)( U(descriptor) *desc, ptr_record *bin_front_ptr, U(size_bau) n_baus); #ifdef HMM_AUDIT_FAIL /* Simply contains a reference to the HMM_AUDIT_FAIL macro and a ** dummy return. */ int U(audit_block_fail_dummy_return)(void); /* Auditing a block consists of checking that the size in its head ** matches the previous block size in the head of the next block. */ #define AUDIT_BLOCK_AS_EXPR(HEAD_PTR) \ ((BLOCK_BAUS(HEAD_PTR) == \ PREV_BLOCK_BAUS(BAUS_FORWARD(HEAD_PTR, BLOCK_BAUS(HEAD_PTR)))) ? \ 0 : U(audit_block_fail_dummy_return)()) #define AUDIT_BLOCK(HEAD_PTR) \ { void *h_ptr = (HEAD_PTR); AUDIT_BLOCK_AS_EXPR(h_ptr); } #endif /* Interface to AVL tree generic package instantiation. */ #define AVL_UNIQUE(BASE) U(avl_ ## BASE) #define AVL_HANDLE ptr_record * #define AVL_KEY U(size_bau) #define AVL_MAX_DEPTH 64 #include "cavl_if.h" #endif /* Include once. */