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#ifndef HMM_INTRNL_H_ 17#define HMM_INTRNL_H_ 18 19#ifdef __uClinux__ 20# include <lddk.h> 21#endif 22 23#include "heapmm.h" 24 25#define U(BASE) HMM_UNIQUE(BASE) 26 27/* Mask of high bit of variable of size_bau type. */ 28#define HIGH_BIT_BAU_SIZE \ 29 ((U(size_bau)) ~ (((U(size_bau)) ~ (U(size_bau)) 0) >> 1)) 30 31/* Add a given number of AAUs to pointer. */ 32#define AAUS_FORWARD(PTR, AAU_OFFSET) \ 33 (((char *) (PTR)) + ((AAU_OFFSET) * ((U(size_aau)) HMM_ADDR_ALIGN_UNIT))) 34 35/* Subtract a given number of AAUs from pointer. */ 36#define AAUS_BACKWARD(PTR, AAU_OFFSET) \ 37 (((char *) (PTR)) - ((AAU_OFFSET) * ((U(size_aau)) HMM_ADDR_ALIGN_UNIT))) 38 39/* Add a given number of BAUs to a pointer. */ 40#define BAUS_FORWARD(PTR, BAU_OFFSET) \ 41 AAUS_FORWARD((PTR), (BAU_OFFSET) * ((U(size_aau)) HMM_BLOCK_ALIGN_UNIT)) 42 43/* Subtract a given number of BAUs to a pointer. */ 44#define BAUS_BACKWARD(PTR, BAU_OFFSET) \ 45 AAUS_BACKWARD((PTR), (BAU_OFFSET) * ((U(size_aau)) HMM_BLOCK_ALIGN_UNIT)) 46 47typedef struct head_struct 48{ 49 /* Sizes in Block Alignment Units. */ 50 HMM_UNIQUE(size_bau) previous_block_size, block_size; 51} 52head_record; 53 54typedef struct ptr_struct 55{ 56 struct ptr_struct *self, *prev, *next; 57} 58ptr_record; 59 60/* Divide and round up any fraction to the next whole number. */ 61#define DIV_ROUND_UP(NUMER, DENOM) (((NUMER) + (DENOM) - 1) / (DENOM)) 62 63/* Number of AAUs in a block head. */ 64#define HEAD_AAUS DIV_ROUND_UP(sizeof(head_record), HMM_ADDR_ALIGN_UNIT) 65 66/* Number of AAUs in a block pointer record. */ 67#define PTR_RECORD_AAUS DIV_ROUND_UP(sizeof(ptr_record), HMM_ADDR_ALIGN_UNIT) 68 69/* Number of BAUs in a dummy end record (at end of chunk). */ 70#define DUMMY_END_BLOCK_BAUS DIV_ROUND_UP(HEAD_AAUS, HMM_BLOCK_ALIGN_UNIT) 71 72/* Minimum number of BAUs in a block (allowing room for the pointer record. */ 73#define MIN_BLOCK_BAUS \ 74 DIV_ROUND_UP(HEAD_AAUS + PTR_RECORD_AAUS, HMM_BLOCK_ALIGN_UNIT) 75 76/* Return number of BAUs in block (masking off high bit containing block 77** status). */ 78#define BLOCK_BAUS(HEAD_PTR) \ 79 (((head_record *) (HEAD_PTR))->block_size & ~HIGH_BIT_BAU_SIZE) 80 81/* Return number of BAUs in previous block (masking off high bit containing 82** block status). */ 83#define PREV_BLOCK_BAUS(HEAD_PTR) \ 84 (((head_record *) (HEAD_PTR))->previous_block_size & ~HIGH_BIT_BAU_SIZE) 85 86/* Set number of BAUs in previous block, preserving high bit containing 87** block status. */ 88#define SET_PREV_BLOCK_BAUS(HEAD_PTR, N_BAUS) \ 89 { register head_record *h_ptr = (head_record *) (HEAD_PTR); \ 90 h_ptr->previous_block_size &= HIGH_BIT_BAU_SIZE; \ 91 h_ptr->previous_block_size |= (N_BAUS); } 92 93/* Convert pointer to pointer record of block to pointer to block's head 94** record. */ 95#define PTR_REC_TO_HEAD(PTR_REC_PTR) \ 96 ((head_record *) AAUS_BACKWARD(PTR_REC_PTR, HEAD_AAUS)) 97 98/* Convert pointer to block head to pointer to block's pointer record. */ 99#define HEAD_TO_PTR_REC(HEAD_PTR) \ 100 ((ptr_record *) AAUS_FORWARD(HEAD_PTR, HEAD_AAUS)) 101 102/* Returns non-zero if block is allocated. */ 103#define IS_BLOCK_ALLOCATED(HEAD_PTR) \ 104 (((((head_record *) (HEAD_PTR))->block_size | \ 105 ((head_record *) (HEAD_PTR))->previous_block_size) & \ 106 HIGH_BIT_BAU_SIZE) == 0) 107 108#define MARK_BLOCK_ALLOCATED(HEAD_PTR) \ 109 { register head_record *h_ptr = (head_record *) (HEAD_PTR); \ 110 h_ptr->block_size &= ~HIGH_BIT_BAU_SIZE; \ 111 h_ptr->previous_block_size &= ~HIGH_BIT_BAU_SIZE; } 112 113/* Mark a block as free when it is not the first block in a bin (and 114** therefore not a node in the AVL tree). */ 115#define MARK_SUCCESSIVE_BLOCK_IN_FREE_BIN(HEAD_PTR) \ 116 { register head_record *h_ptr = (head_record *) (HEAD_PTR); \ 117 h_ptr->block_size |= HIGH_BIT_BAU_SIZE; } 118 119/* Prototypes for internal functions implemented in one file and called in 120** another. 121*/ 122 123void U(into_free_collection)(U(descriptor) *desc, head_record *head_ptr); 124 125void U(out_of_free_collection)(U(descriptor) *desc, head_record *head_ptr); 126 127void *U(alloc_from_bin)( 128 U(descriptor) *desc, ptr_record *bin_front_ptr, U(size_bau) n_baus); 129 130#ifdef HMM_AUDIT_FAIL 131 132/* Simply contains a reference to the HMM_AUDIT_FAIL macro and a 133** dummy return. */ 134int U(audit_block_fail_dummy_return)(void); 135 136 137/* Auditing a block consists of checking that the size in its head 138** matches the previous block size in the head of the next block. */ 139#define AUDIT_BLOCK_AS_EXPR(HEAD_PTR) \ 140 ((BLOCK_BAUS(HEAD_PTR) == \ 141 PREV_BLOCK_BAUS(BAUS_FORWARD(HEAD_PTR, BLOCK_BAUS(HEAD_PTR)))) ? \ 142 0 : U(audit_block_fail_dummy_return)()) 143 144#define AUDIT_BLOCK(HEAD_PTR) \ 145 { void *h_ptr = (HEAD_PTR); AUDIT_BLOCK_AS_EXPR(h_ptr); } 146 147#endif 148 149/* Interface to AVL tree generic package instantiation. */ 150 151#define AVL_UNIQUE(BASE) U(avl_ ## BASE) 152 153#define AVL_HANDLE ptr_record * 154 155#define AVL_KEY U(size_bau) 156 157#define AVL_MAX_DEPTH 64 158 159#include "cavl_if.h" 160 161#endif /* Include once. */ 162