1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /* ---- includes ----------------------------------------------------------- */ 18 19 #include "b_BasicEm/MemSeg.h" 20 #include "b_BasicEm/Functions.h" 21 #include "b_BasicEm/Context.h" 22 23 /* ------------------------------------------------------------------------- */ 24 25 /* ========================================================================= */ 26 /* */ 27 /* ---- \ghd{ auxiliary functions } ---------------------------------------- */ 28 /* */ 29 /* ========================================================================= */ 30 31 /* ------------------------------------------------------------------------- */ 32 33 /* ========================================================================= */ 34 /* */ 35 /* ---- \ghd{ constructor / destructor } ----------------------------------- */ 36 /* */ 37 /* ========================================================================= */ 38 39 /* ------------------------------------------------------------------------- */ 40 41 void bbs_MemSeg_init( struct bbs_Context* cpA, 42 struct bbs_MemSeg* ptrA ) 43 { 44 ptrA->memPtrE = NULL; 45 ptrA->sizeE = 0; 46 ptrA->allocIndexE = 0; 47 ptrA->sharedE = FALSE; 48 ptrA->idE = 0; 49 ptrA->dynMemManagerPtrE = NULL; 50 } 51 52 /* ------------------------------------------------------------------------- */ 53 54 void bbs_MemSeg_exit( struct bbs_Context* cpA, 55 struct bbs_MemSeg* ptrA ) 56 { 57 ptrA->memPtrE = NULL; 58 ptrA->sizeE = 0; 59 ptrA->allocIndexE = 0; 60 ptrA->sharedE = FALSE; 61 ptrA->idE = 0; 62 ptrA->dynMemManagerPtrE = NULL; 63 } 64 65 /* ------------------------------------------------------------------------- */ 66 67 /* ========================================================================= */ 68 /* */ 69 /* ---- \ghd{ operators } -------------------------------------------------- */ 70 /* */ 71 /* ========================================================================= */ 72 73 /* ------------------------------------------------------------------------- */ 74 75 /* ========================================================================= */ 76 /* */ 77 /* ---- \ghd{ query functions } -------------------------------------------- */ 78 /* */ 79 /* ========================================================================= */ 80 81 /* ------------------------------------------------------------------------- */ 82 83 uint32 bbs_MemSeg_availableSize( struct bbs_Context* cpA, 84 const struct bbs_MemSeg* ptrA ) 85 { 86 if( ptrA->dynMemManagerPtrE == NULL ) 87 { 88 return ( ptrA->sizeE == ptrA->allocIndexE ) ? 0 : ptrA->sizeE - ptrA->allocIndexE - 2 * ptrA->sharedE; 89 } 90 else 91 { 92 return 0xFFFFFFFF; 93 } 94 } 95 96 /* ------------------------------------------------------------------------- */ 97 98 uint32 bbs_MemSeg_allocatedSize( struct bbs_Context* cpA, 99 const struct bbs_MemSeg* ptrA ) 100 { 101 if( ptrA->dynMemManagerPtrE == NULL ) 102 { 103 return ptrA->allocIndexE; 104 } 105 else 106 { 107 return bbs_DynMemManager_allocatedSize( cpA, ptrA->dynMemManagerPtrE ); 108 } 109 } 110 111 /* ------------------------------------------------------------------------- */ 112 113 uint32 bbs_MemSeg_usedSize( struct bbs_Context* cpA, 114 const struct bbs_MemSeg* ptrA ) 115 { 116 if( ptrA->dynMemManagerPtrE == NULL ) 117 { 118 if( ptrA->sharedE ) 119 { 120 return ptrA->allocIndexE; 121 } 122 else 123 { 124 uint32 indexL = 0; 125 uint32 countL = 0; 126 while( indexL < ptrA->allocIndexE ) 127 { 128 uint32 sizeL = *( uint32* )( ptrA->memPtrE + indexL ); 129 indexL += ( sizeL & 0xFFFFFFFE ); 130 if( ( sizeL & 1 ) == 0 ) 131 { 132 countL += sizeL - 2; 133 } 134 } 135 return countL; 136 } 137 } 138 else 139 { 140 return bbs_MemSeg_allocatedSize( cpA, ptrA ); 141 } 142 } 143 144 /* ------------------------------------------------------------------------- */ 145 146 uint32 bbs_MemSeg_blocks( struct bbs_Context* cpA, 147 const struct bbs_MemSeg* ptrA ) 148 { 149 uint32 indexL = 0; 150 uint32 countL = 0; 151 152 if( ptrA->sharedE ) return 0; 153 154 while( indexL < ptrA->allocIndexE ) 155 { 156 uint32 sizeL = *( uint32* )( ptrA->memPtrE + indexL ); 157 indexL += ( sizeL & 0xFFFFFFFE ); 158 countL++; 159 } 160 return countL; 161 } 162 163 /* ------------------------------------------------------------------------- */ 164 165 uint32 bbs_MemSeg_usedBlocks( struct bbs_Context* cpA, 166 const struct bbs_MemSeg* ptrA ) 167 { 168 uint32 indexL = 0; 169 uint32 countL = 0; 170 171 if( ptrA->sharedE ) return 0; 172 173 while( indexL < ptrA->allocIndexE ) 174 { 175 uint32 sizeL = *( uint32* )( ptrA->memPtrE + indexL ); 176 indexL += ( sizeL & 0xFFFFFFFE ); 177 countL += ( ( sizeL & 1 ) == 0 ); 178 } 179 return countL; 180 } 181 182 /* ------------------------------------------------------------------------- */ 183 184 /* ========================================================================= */ 185 /* */ 186 /* ---- \ghd{ modify functions } ------------------------------------------- */ 187 /* */ 188 /* ========================================================================= */ 189 190 /* ------------------------------------------------------------------------- */ 191 192 /* ========================================================================= */ 193 /* */ 194 /* ---- \ghd{ I/O } -------------------------------------------------------- */ 195 /* */ 196 /* ========================================================================= */ 197 198 /* ------------------------------------------------------------------------- */ 199 200 /* ========================================================================= */ 201 /* */ 202 /* ---- \ghd{ exec functions } --------------------------------------------- */ 203 /* */ 204 /* ========================================================================= */ 205 206 /* ------------------------------------------------------------------------- */ 207 208 struct bbs_MemSeg bbs_MemSeg_create( struct bbs_Context* cpA, 209 void* memPtrA, uint32 sizeA ) 210 { 211 struct bbs_MemSeg memSegL; 212 memSegL.memPtrE = ( uint16* )memPtrA; 213 memSegL.sizeE = sizeA & 0xFFFFFFFE; /* enforce even size to avoid overflow problems */ 214 memSegL.allocIndexE = 0; 215 memSegL.sharedE = FALSE; 216 memSegL.idE = 0; 217 memSegL.dynMemManagerPtrE = NULL; 218 return memSegL; 219 } 220 221 /* ------------------------------------------------------------------------- */ 222 223 struct bbs_MemSeg bbs_MemSeg_createShared( struct bbs_Context* cpA, 224 void* memPtrA, uint32 sizeA ) 225 { 226 struct bbs_MemSeg memSegL; 227 memSegL.memPtrE = ( uint16* )memPtrA; 228 memSegL.sizeE = sizeA; 229 memSegL.allocIndexE = 0; 230 memSegL.sharedE = TRUE; 231 memSegL.idE = 0; 232 memSegL.dynMemManagerPtrE = NULL; 233 return memSegL; 234 } 235 236 /* ------------------------------------------------------------------------- */ 237 238 void* bbs_MemSeg_alloc( struct bbs_Context* cpA, 239 struct bbs_MemSeg* ptrA, 240 uint32 sizeA ) 241 { 242 uint16* memPtrL = NULL; 243 244 if( bbs_Context_error( cpA ) ) return NULL; 245 246 if( !ptrA->sharedE ) 247 { 248 if( ptrA->dynMemManagerPtrE == NULL ) 249 { 250 uint32 effSizeL = sizeA + ( sizeA & 1 ) + 2; /* effective block size */ 251 memPtrL = ptrA->memPtrE + ptrA->allocIndexE; 252 *( ( uint32* )memPtrL ) = effSizeL; 253 memPtrL += 2; 254 if( ptrA->allocIndexE + effSizeL > ptrA->sizeE ) 255 { 256 bbs_ERR2( bbs_ERR_MEMORY_OVERFLOW, 257 "uint16* bbs_MemSeg_alloc( struct bbs_MemSeg* ptrA, uint32 sizeA ):\n" 258 "Exclusive Memory overflow. Segment size: %i. Requested size: %i", ptrA->sizeE, sizeA ); 259 return NULL; 260 } 261 ptrA->allocIndexE += effSizeL; 262 } 263 else 264 { 265 memPtrL = bbs_DynMemManager_alloc( cpA, ptrA->dynMemManagerPtrE, ptrA, sizeA ); 266 } 267 } 268 else 269 { 270 uint32 effSizeL = sizeA + ( sizeA & 1 ); /* effective block size */ 271 272 if( ptrA->allocIndexE + effSizeL > ptrA->sizeE + ( ptrA->sizeE & 1 ) ) 273 { 274 if( ptrA->dynMemManagerPtrE == NULL ) 275 { 276 bbs_ERR2( bbs_ERR_MEMORY_OVERFLOW, 277 "uint16* bbs_MemSeg_alloc( struct bbs_MemSeg* ptrA, uint32 sizeA ):\n" 278 "Shared Memory overflow. Segment size: %i. Requested size: %i", ptrA->sizeE, sizeA ); 279 return NULL; 280 } 281 else 282 { 283 uint32 actualBlockSizeL = 0; 284 ptrA->memPtrE = bbs_DynMemManager_nextBlock( cpA, ptrA->dynMemManagerPtrE, ptrA, ptrA->memPtrE, effSizeL, &actualBlockSizeL ); 285 ptrA->sizeE = actualBlockSizeL; 286 ptrA->allocIndexE = 0; 287 } 288 } 289 290 memPtrL = ptrA->memPtrE + ptrA->allocIndexE; 291 ptrA->allocIndexE += effSizeL; 292 } 293 294 #if defined( HW_TMS320C5x ) 295 #ifdef DEBUG2 296 { 297 /* check if segment crosses page boundary */ 298 if( ( ( ( uint32 ) ptrA->memPtrE ) >> 16 ) != 299 ( ( ( uint32 ) ptrA->memPtrE + ( ptrA->sizeE - 1 ) ) >> 16 ) ) 300 { 301 bbs_ERROR0( "uint16* bbs_MemSeg_alloc( struct bbs_MemSeg* ptrA, uint32 sizeA ):\nSegment crosses page boundary\n" ); 302 return NULL; 303 } 304 } 305 #endif 306 #endif 307 308 return memPtrL; 309 } 310 311 /* ------------------------------------------------------------------------- */ 312 313 void bbs_MemSeg_free( struct bbs_Context* cpA, 314 struct bbs_MemSeg* ptrA, 315 void* memPtrA ) 316 { 317 bbs_DEF_fNameL( "void bbs_MemSeg_free( struct bbs_MemSeg* ptrA, void* memPtrA )" ) 318 319 if( bbs_Context_error( cpA ) ) return; 320 321 /** only valid exclusive segments can be freed */ 322 if( ptrA == NULL || memPtrA == NULL || ptrA->sharedE ) return; 323 324 if( ptrA->dynMemManagerPtrE != NULL ) 325 { 326 bbs_DynMemManager_free( cpA, ptrA->dynMemManagerPtrE, memPtrA ); 327 } 328 else 329 { 330 uint32 indexL, sizeL; 331 uint16* memPtrL; 332 333 if( ptrA == NULL || memPtrA == NULL ) return; 334 if( ptrA->sharedE ) return; 335 336 #ifdef HW_TMS320C5x 337 indexL = ( uint32 ) memPtrA - ( uint32 ) ptrA->memPtrE - 2; 338 #else 339 indexL = ( uint16* )memPtrA - ptrA->memPtrE - 2; 340 #endif 341 342 memPtrL = ptrA->memPtrE + indexL; 343 sizeL = *( ( int32* )memPtrL ); 344 345 /* checks */ 346 if( indexL > ptrA->allocIndexE || ( indexL & 1 ) != 0 ) 347 { 348 bbs_ERROR4( "%s\n: Invalid memory.\n" 349 "sizeE = %i\n" 350 "allocIndexE = %i\n" 351 "indexL = %i\n", 352 fNameL, 353 ptrA->sizeE, 354 ptrA->allocIndexE, 355 indexL ); 356 return; 357 } 358 359 if( ( sizeL & 1 ) != 0 ) 360 { 361 bbs_ERROR1( "%s\n: Memory block was already freed once", fNameL ); 362 return; 363 } 364 365 *( ( uint32* )memPtrL ) += 1; /* odd size value indicates unused memory block */ 366 367 /* free last unused blocks if any */ 368 if( indexL + sizeL == ptrA->allocIndexE ) 369 { 370 uint32 newAllocIndexL = 0; 371 indexL = 0; 372 while( indexL < ptrA->allocIndexE ) 373 { 374 uint32 sizeL = *( uint32* )( ptrA->memPtrE + indexL ); 375 indexL += ( sizeL & 0xFFFFFFFE ); 376 if( ( sizeL & 1 ) == 0 ) 377 { 378 newAllocIndexL = indexL; 379 } 380 } 381 382 ptrA->allocIndexE = newAllocIndexL; 383 } 384 385 #ifdef DEBUG2 386 bbs_MemSeg_checkConsistency( cpA, ptrA ); 387 #endif 388 389 } 390 } 391 392 /* ------------------------------------------------------------------------- */ 393 394 void bbs_MemSeg_checkConsistency( struct bbs_Context* cpA, 395 const struct bbs_MemSeg* ptrA ) 396 { 397 uint32 indexL = 0; 398 399 if( ptrA->sharedE ) return; 400 401 while( indexL < ptrA->allocIndexE ) 402 { 403 uint32 sizeL = *( uint32* )( ptrA->memPtrE + indexL ); 404 indexL += ( sizeL & 0xFFFFFFFE ); 405 } 406 407 if( indexL != ptrA->allocIndexE ) 408 { 409 bbs_ERROR0( "Memory consistency check failed" ); 410 } 411 } 412 413 /* ------------------------------------------------------------------------- */ 414 415 /* ========================================================================= */ 416