1296177Sjhibbits/* Copyright (c) 2008-2011 Freescale Semiconductor, Inc. 2296177Sjhibbits * All rights reserved. 3296177Sjhibbits * 4296177Sjhibbits * Redistribution and use in source and binary forms, with or without 5296177Sjhibbits * modification, are permitted provided that the following conditions are met: 6296177Sjhibbits * * Redistributions of source code must retain the above copyright 7296177Sjhibbits * notice, this list of conditions and the following disclaimer. 8296177Sjhibbits * * Redistributions in binary form must reproduce the above copyright 9296177Sjhibbits * notice, this list of conditions and the following disclaimer in the 10296177Sjhibbits * documentation and/or other materials provided with the distribution. 11296177Sjhibbits * * Neither the name of Freescale Semiconductor nor the 12296177Sjhibbits * names of its contributors may be used to endorse or promote products 13296177Sjhibbits * derived from this software without specific prior written permission. 14296177Sjhibbits * 15296177Sjhibbits * 16296177Sjhibbits * ALTERNATIVELY, this software may be distributed under the terms of the 17296177Sjhibbits * GNU General Public License ("GPL") as published by the Free Software 18296177Sjhibbits * Foundation, either version 2 of that License or (at your option) any 19296177Sjhibbits * later version. 20296177Sjhibbits * 21296177Sjhibbits * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY 22296177Sjhibbits * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23296177Sjhibbits * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24296177Sjhibbits * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY 25296177Sjhibbits * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26296177Sjhibbits * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27296177Sjhibbits * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 28296177Sjhibbits * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29296177Sjhibbits * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30296177Sjhibbits * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31296177Sjhibbits */ 32296177Sjhibbits 33296177Sjhibbits#include "string_ext.h" 34296177Sjhibbits#include "error_ext.h" 35296177Sjhibbits#include "std_ext.h" 36296177Sjhibbits#include "sprint_ext.h" 37296177Sjhibbits#include "part_ext.h" 38296177Sjhibbits#include "xx_ext.h" 39296177Sjhibbits 40296177Sjhibbits#include "mm.h" 41296177Sjhibbits 42296177Sjhibbits 43296177Sjhibbits 44296177Sjhibbits 45296177Sjhibbits/********************************************************************** 46296177Sjhibbits * MM internal routines set * 47296177Sjhibbits **********************************************************************/ 48296177Sjhibbits 49296177Sjhibbits/**************************************************************** 50296177Sjhibbits * Routine: CreateBusyBlock 51296177Sjhibbits * 52296177Sjhibbits * Description: 53296177Sjhibbits * Initializes a new busy block of "size" bytes and started 54296177Sjhibbits * rom "base" address. Each busy block has a name that 55296177Sjhibbits * specified the purpose of the memory allocation. 56296177Sjhibbits * 57296177Sjhibbits * Arguments: 58296177Sjhibbits * base - base address of the busy block 59296177Sjhibbits * size - size of the busy block 60296177Sjhibbits * name - name that specified the busy block 61296177Sjhibbits * 62296177Sjhibbits * Return value: 63296177Sjhibbits * A pointer to new created structure returned on success; 64296177Sjhibbits * Otherwise, NULL. 65296177Sjhibbits ****************************************************************/ 66296177Sjhibbitsstatic t_BusyBlock * CreateBusyBlock(uint64_t base, uint64_t size, char *name) 67296177Sjhibbits{ 68296177Sjhibbits t_BusyBlock *p_BusyBlock; 69296177Sjhibbits uint32_t n; 70296177Sjhibbits 71296177Sjhibbits p_BusyBlock = (t_BusyBlock *)XX_Malloc(sizeof(t_BusyBlock)); 72296177Sjhibbits if ( !p_BusyBlock ) 73296177Sjhibbits { 74296177Sjhibbits REPORT_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); 75296177Sjhibbits return NULL; 76296177Sjhibbits } 77296177Sjhibbits 78296177Sjhibbits p_BusyBlock->base = base; 79296177Sjhibbits p_BusyBlock->end = base + size; 80296177Sjhibbits 81296177Sjhibbits n = strlen(name); 82296177Sjhibbits if (n >= MM_MAX_NAME_LEN) 83296177Sjhibbits n = MM_MAX_NAME_LEN - 1; 84296177Sjhibbits strncpy(p_BusyBlock->name, name, MM_MAX_NAME_LEN-1); 85296177Sjhibbits p_BusyBlock->name[n] = '\0'; 86296177Sjhibbits p_BusyBlock->p_Next = 0; 87296177Sjhibbits 88296177Sjhibbits return p_BusyBlock; 89296177Sjhibbits} 90296177Sjhibbits 91296177Sjhibbits/**************************************************************** 92296177Sjhibbits * Routine: CreateNewBlock 93296177Sjhibbits * 94296177Sjhibbits * Description: 95296177Sjhibbits * Initializes a new memory block of "size" bytes and started 96296177Sjhibbits * from "base" address. 97296177Sjhibbits * 98296177Sjhibbits * Arguments: 99296177Sjhibbits * base - base address of the memory block 100296177Sjhibbits * size - size of the memory block 101296177Sjhibbits * 102296177Sjhibbits * Return value: 103296177Sjhibbits * A pointer to new created structure returned on success; 104296177Sjhibbits * Otherwise, NULL. 105296177Sjhibbits ****************************************************************/ 106296177Sjhibbitsstatic t_MemBlock * CreateNewBlock(uint64_t base, uint64_t size) 107296177Sjhibbits{ 108296177Sjhibbits t_MemBlock *p_MemBlock; 109296177Sjhibbits 110296177Sjhibbits p_MemBlock = (t_MemBlock *)XX_Malloc(sizeof(t_MemBlock)); 111296177Sjhibbits if ( !p_MemBlock ) 112296177Sjhibbits { 113296177Sjhibbits REPORT_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); 114296177Sjhibbits return NULL; 115296177Sjhibbits } 116296177Sjhibbits 117296177Sjhibbits p_MemBlock->base = base; 118296177Sjhibbits p_MemBlock->end = base+size; 119296177Sjhibbits p_MemBlock->p_Next = 0; 120296177Sjhibbits 121296177Sjhibbits return p_MemBlock; 122296177Sjhibbits} 123296177Sjhibbits 124296177Sjhibbits/**************************************************************** 125296177Sjhibbits * Routine: CreateFreeBlock 126296177Sjhibbits * 127296177Sjhibbits * Description: 128296177Sjhibbits * Initializes a new free block of of "size" bytes and 129296177Sjhibbits * started from "base" address. 130296177Sjhibbits * 131296177Sjhibbits * Arguments: 132296177Sjhibbits * base - base address of the free block 133296177Sjhibbits * size - size of the free block 134296177Sjhibbits * 135296177Sjhibbits * Return value: 136296177Sjhibbits * A pointer to new created structure returned on success; 137296177Sjhibbits * Otherwise, NULL. 138296177Sjhibbits ****************************************************************/ 139296177Sjhibbitsstatic t_FreeBlock * CreateFreeBlock(uint64_t base, uint64_t size) 140296177Sjhibbits{ 141296177Sjhibbits t_FreeBlock *p_FreeBlock; 142296177Sjhibbits 143296177Sjhibbits p_FreeBlock = (t_FreeBlock *)XX_Malloc(sizeof(t_FreeBlock)); 144296177Sjhibbits if ( !p_FreeBlock ) 145296177Sjhibbits { 146296177Sjhibbits REPORT_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); 147296177Sjhibbits return NULL; 148296177Sjhibbits } 149296177Sjhibbits 150296177Sjhibbits p_FreeBlock->base = base; 151296177Sjhibbits p_FreeBlock->end = base + size; 152296177Sjhibbits p_FreeBlock->p_Next = 0; 153296177Sjhibbits 154296177Sjhibbits return p_FreeBlock; 155296177Sjhibbits} 156296177Sjhibbits 157296177Sjhibbits/**************************************************************** 158296177Sjhibbits * Routine: AddFree 159296177Sjhibbits * 160296177Sjhibbits * Description: 161296177Sjhibbits * Adds a new free block to the free lists. It updates each 162296177Sjhibbits * free list to include a new free block. 163296177Sjhibbits * Note, that all free block in each free list are ordered 164296177Sjhibbits * by their base address. 165296177Sjhibbits * 166296177Sjhibbits * Arguments: 167296177Sjhibbits * p_MM - pointer to the MM object 168296177Sjhibbits * base - base address of a given free block 169296177Sjhibbits * end - end address of a given free block 170296177Sjhibbits * 171296177Sjhibbits * Return value: 172296177Sjhibbits * 173296177Sjhibbits * 174296177Sjhibbits ****************************************************************/ 175296177Sjhibbitsstatic t_Error AddFree(t_MM *p_MM, uint64_t base, uint64_t end) 176296177Sjhibbits{ 177296177Sjhibbits t_FreeBlock *p_PrevB, *p_CurrB, *p_NewB; 178296177Sjhibbits uint64_t alignment; 179296177Sjhibbits uint64_t alignBase; 180296177Sjhibbits int i; 181296177Sjhibbits 182296177Sjhibbits /* Updates free lists to include a just released block */ 183296177Sjhibbits for (i=0; i <= MM_MAX_ALIGNMENT; i++) 184296177Sjhibbits { 185296177Sjhibbits p_PrevB = p_NewB = 0; 186296177Sjhibbits p_CurrB = p_MM->freeBlocks[i]; 187296177Sjhibbits 188296177Sjhibbits alignment = (uint64_t)(0x1 << i); 189296177Sjhibbits alignBase = MAKE_ALIGNED(base, alignment); 190296177Sjhibbits 191296177Sjhibbits /* Goes to the next free list if there is no block to free */ 192296177Sjhibbits if (alignBase >= end) 193296177Sjhibbits continue; 194296177Sjhibbits 195296177Sjhibbits /* Looks for a free block that should be updated */ 196296177Sjhibbits while ( p_CurrB ) 197296177Sjhibbits { 198296177Sjhibbits if ( alignBase <= p_CurrB->end ) 199296177Sjhibbits { 200296177Sjhibbits if ( end > p_CurrB->end ) 201296177Sjhibbits { 202296177Sjhibbits t_FreeBlock *p_NextB; 203296177Sjhibbits while ( p_CurrB->p_Next && end > p_CurrB->p_Next->end ) 204296177Sjhibbits { 205296177Sjhibbits p_NextB = p_CurrB->p_Next; 206296177Sjhibbits p_CurrB->p_Next = p_CurrB->p_Next->p_Next; 207296177Sjhibbits XX_Free(p_NextB); 208296177Sjhibbits } 209296177Sjhibbits 210296177Sjhibbits p_NextB = p_CurrB->p_Next; 211296177Sjhibbits if ( !p_NextB || (p_NextB && end < p_NextB->base) ) 212296177Sjhibbits { 213296177Sjhibbits p_CurrB->end = end; 214296177Sjhibbits } 215296177Sjhibbits else 216296177Sjhibbits { 217296177Sjhibbits p_CurrB->end = p_NextB->end; 218296177Sjhibbits p_CurrB->p_Next = p_NextB->p_Next; 219296177Sjhibbits XX_Free(p_NextB); 220296177Sjhibbits } 221296177Sjhibbits } 222296177Sjhibbits else if ( (end < p_CurrB->base) && ((end-alignBase) >= alignment) ) 223296177Sjhibbits { 224296177Sjhibbits if ((p_NewB = CreateFreeBlock(alignBase, end-alignBase)) == NULL) 225296177Sjhibbits RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); 226296177Sjhibbits 227296177Sjhibbits p_NewB->p_Next = p_CurrB; 228296177Sjhibbits if (p_PrevB) 229296177Sjhibbits p_PrevB->p_Next = p_NewB; 230296177Sjhibbits else 231296177Sjhibbits p_MM->freeBlocks[i] = p_NewB; 232296177Sjhibbits break; 233296177Sjhibbits } 234296177Sjhibbits 235296177Sjhibbits if ((alignBase < p_CurrB->base) && (end >= p_CurrB->base)) 236296177Sjhibbits { 237296177Sjhibbits p_CurrB->base = alignBase; 238296177Sjhibbits } 239296177Sjhibbits 240296177Sjhibbits /* if size of the free block is less then alignment 241296177Sjhibbits * deletes that free block from the free list. */ 242296177Sjhibbits if ( (p_CurrB->end - p_CurrB->base) < alignment) 243296177Sjhibbits { 244296177Sjhibbits if ( p_PrevB ) 245296177Sjhibbits p_PrevB->p_Next = p_CurrB->p_Next; 246296177Sjhibbits else 247296177Sjhibbits p_MM->freeBlocks[i] = p_CurrB->p_Next; 248296177Sjhibbits XX_Free(p_CurrB); 249296177Sjhibbits } 250296177Sjhibbits break; 251296177Sjhibbits } 252296177Sjhibbits else 253296177Sjhibbits { 254296177Sjhibbits p_PrevB = p_CurrB; 255296177Sjhibbits p_CurrB = p_CurrB->p_Next; 256296177Sjhibbits } 257296177Sjhibbits } 258296177Sjhibbits 259296177Sjhibbits /* If no free block found to be updated, insert a new free block 260296177Sjhibbits * to the end of the free list. 261296177Sjhibbits */ 262296177Sjhibbits if ( !p_CurrB && ((((uint64_t)(end-base)) & ((uint64_t)(alignment-1))) == 0) ) 263296177Sjhibbits { 264296177Sjhibbits if ((p_NewB = CreateFreeBlock(alignBase, end-base)) == NULL) 265296177Sjhibbits RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); 266296177Sjhibbits 267296177Sjhibbits if (p_PrevB) 268296177Sjhibbits p_PrevB->p_Next = p_NewB; 269296177Sjhibbits else 270296177Sjhibbits p_MM->freeBlocks[i] = p_NewB; 271296177Sjhibbits } 272296177Sjhibbits 273296177Sjhibbits /* Update boundaries of the new free block */ 274296177Sjhibbits if ((alignment == 1) && !p_NewB) 275296177Sjhibbits { 276296177Sjhibbits if ( p_CurrB && base > p_CurrB->base ) 277296177Sjhibbits base = p_CurrB->base; 278296177Sjhibbits if ( p_CurrB && end < p_CurrB->end ) 279296177Sjhibbits end = p_CurrB->end; 280296177Sjhibbits } 281296177Sjhibbits } 282296177Sjhibbits 283296177Sjhibbits return (E_OK); 284296177Sjhibbits} 285296177Sjhibbits 286296177Sjhibbits/**************************************************************** 287296177Sjhibbits * Routine: CutFree 288296177Sjhibbits * 289296177Sjhibbits * Description: 290296177Sjhibbits * Cuts a free block from holdBase to holdEnd from the free lists. 291296177Sjhibbits * That is, it updates all free lists of the MM object do 292296177Sjhibbits * not include a block of memory from holdBase to holdEnd. 293296177Sjhibbits * For each free lists it seek for a free block that holds 294296177Sjhibbits * either holdBase or holdEnd. If such block is found it updates it. 295296177Sjhibbits * 296296177Sjhibbits * Arguments: 297296177Sjhibbits * p_MM - pointer to the MM object 298296177Sjhibbits * holdBase - base address of the allocated block 299296177Sjhibbits * holdEnd - end address of the allocated block 300296177Sjhibbits * 301296177Sjhibbits * Return value: 302296177Sjhibbits * E_OK is returned on success, 303296177Sjhibbits * otherwise returns an error code. 304296177Sjhibbits * 305296177Sjhibbits ****************************************************************/ 306296177Sjhibbitsstatic t_Error CutFree(t_MM *p_MM, uint64_t holdBase, uint64_t holdEnd) 307296177Sjhibbits{ 308296177Sjhibbits t_FreeBlock *p_PrevB, *p_CurrB, *p_NewB; 309296177Sjhibbits uint64_t alignBase, base, end; 310296177Sjhibbits uint64_t alignment; 311296177Sjhibbits int i; 312296177Sjhibbits 313296177Sjhibbits for (i=0; i <= MM_MAX_ALIGNMENT; i++) 314296177Sjhibbits { 315296177Sjhibbits p_PrevB = p_NewB = 0; 316296177Sjhibbits p_CurrB = p_MM->freeBlocks[i]; 317296177Sjhibbits 318296177Sjhibbits alignment = (uint64_t)(0x1 << i); 319296177Sjhibbits alignBase = MAKE_ALIGNED(holdEnd, alignment); 320296177Sjhibbits 321296177Sjhibbits while ( p_CurrB ) 322296177Sjhibbits { 323296177Sjhibbits base = p_CurrB->base; 324296177Sjhibbits end = p_CurrB->end; 325296177Sjhibbits 326296177Sjhibbits if ( (holdBase <= base) && (holdEnd <= end) && (holdEnd > base) ) 327296177Sjhibbits { 328296177Sjhibbits if ( alignBase >= end || 329296177Sjhibbits (alignBase < end && ((end-alignBase) < alignment)) ) 330296177Sjhibbits { 331296177Sjhibbits if (p_PrevB) 332296177Sjhibbits p_PrevB->p_Next = p_CurrB->p_Next; 333296177Sjhibbits else 334296177Sjhibbits p_MM->freeBlocks[i] = p_CurrB->p_Next; 335296177Sjhibbits XX_Free(p_CurrB); 336296177Sjhibbits } 337296177Sjhibbits else 338296177Sjhibbits { 339296177Sjhibbits p_CurrB->base = alignBase; 340296177Sjhibbits } 341296177Sjhibbits break; 342296177Sjhibbits } 343296177Sjhibbits else if ( (holdBase > base) && (holdEnd <= end) ) 344296177Sjhibbits { 345296177Sjhibbits if ( (holdBase-base) >= alignment ) 346296177Sjhibbits { 347296177Sjhibbits if ( (alignBase < end) && ((end-alignBase) >= alignment) ) 348296177Sjhibbits { 349296177Sjhibbits if ((p_NewB = CreateFreeBlock(alignBase, end-alignBase)) == NULL) 350296177Sjhibbits RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); 351296177Sjhibbits p_NewB->p_Next = p_CurrB->p_Next; 352296177Sjhibbits p_CurrB->p_Next = p_NewB; 353296177Sjhibbits } 354296177Sjhibbits p_CurrB->end = holdBase; 355296177Sjhibbits } 356296177Sjhibbits else if ( (alignBase < end) && ((end-alignBase) >= alignment) ) 357296177Sjhibbits { 358296177Sjhibbits p_CurrB->base = alignBase; 359296177Sjhibbits } 360296177Sjhibbits else 361296177Sjhibbits { 362296177Sjhibbits if (p_PrevB) 363296177Sjhibbits p_PrevB->p_Next = p_CurrB->p_Next; 364296177Sjhibbits else 365296177Sjhibbits p_MM->freeBlocks[i] = p_CurrB->p_Next; 366296177Sjhibbits XX_Free(p_CurrB); 367296177Sjhibbits } 368296177Sjhibbits break; 369296177Sjhibbits } 370296177Sjhibbits else 371296177Sjhibbits { 372296177Sjhibbits p_PrevB = p_CurrB; 373296177Sjhibbits p_CurrB = p_CurrB->p_Next; 374296177Sjhibbits } 375296177Sjhibbits } 376296177Sjhibbits } 377296177Sjhibbits 378296177Sjhibbits return (E_OK); 379296177Sjhibbits} 380296177Sjhibbits 381296177Sjhibbits/**************************************************************** 382296177Sjhibbits * Routine: AddBusy 383296177Sjhibbits * 384296177Sjhibbits * Description: 385296177Sjhibbits * Adds a new busy block to the list of busy blocks. Note, 386296177Sjhibbits * that all busy blocks are ordered by their base address in 387296177Sjhibbits * the busy list. 388296177Sjhibbits * 389296177Sjhibbits * Arguments: 390296177Sjhibbits * MM - handler to the MM object 391296177Sjhibbits * p_NewBusyB - pointer to the a busy block 392296177Sjhibbits * 393296177Sjhibbits * Return value: 394296177Sjhibbits * None. 395296177Sjhibbits * 396296177Sjhibbits ****************************************************************/ 397296177Sjhibbitsstatic void AddBusy(t_MM *p_MM, t_BusyBlock *p_NewBusyB) 398296177Sjhibbits{ 399296177Sjhibbits t_BusyBlock *p_CurrBusyB, *p_PrevBusyB; 400296177Sjhibbits 401296177Sjhibbits /* finds a place of a new busy block in the list of busy blocks */ 402296177Sjhibbits p_PrevBusyB = 0; 403296177Sjhibbits p_CurrBusyB = p_MM->busyBlocks; 404296177Sjhibbits 405296177Sjhibbits while ( p_CurrBusyB && p_NewBusyB->base > p_CurrBusyB->base ) 406296177Sjhibbits { 407296177Sjhibbits p_PrevBusyB = p_CurrBusyB; 408296177Sjhibbits p_CurrBusyB = p_CurrBusyB->p_Next; 409296177Sjhibbits } 410296177Sjhibbits 411296177Sjhibbits /* insert the new busy block into the list of busy blocks */ 412296177Sjhibbits if ( p_CurrBusyB ) 413296177Sjhibbits p_NewBusyB->p_Next = p_CurrBusyB; 414296177Sjhibbits if ( p_PrevBusyB ) 415296177Sjhibbits p_PrevBusyB->p_Next = p_NewBusyB; 416296177Sjhibbits else 417296177Sjhibbits p_MM->busyBlocks = p_NewBusyB; 418296177Sjhibbits} 419296177Sjhibbits 420296177Sjhibbits/**************************************************************** 421296177Sjhibbits * Routine: CutBusy 422296177Sjhibbits * 423296177Sjhibbits * Description: 424296177Sjhibbits * Cuts a block from base to end from the list of busy blocks. 425296177Sjhibbits * This is done by updating the list of busy blocks do not 426296177Sjhibbits * include a given block, that block is going to be free. If a 427296177Sjhibbits * given block is a part of some other busy block, so that 428296177Sjhibbits * busy block is updated. If there are number of busy blocks 429296177Sjhibbits * included in the given block, so all that blocks are removed 430296177Sjhibbits * from the busy list and the end blocks are updated. 431296177Sjhibbits * If the given block devides some block into two parts, a new 432296177Sjhibbits * busy block is added to the busy list. 433296177Sjhibbits * 434296177Sjhibbits * Arguments: 435296177Sjhibbits * p_MM - pointer to the MM object 436296177Sjhibbits * base - base address of a given busy block 437296177Sjhibbits * end - end address of a given busy block 438296177Sjhibbits * 439296177Sjhibbits * Return value: 440296177Sjhibbits * E_OK on success, E_NOMEMORY otherwise. 441296177Sjhibbits * 442296177Sjhibbits ****************************************************************/ 443296177Sjhibbitsstatic t_Error CutBusy(t_MM *p_MM, uint64_t base, uint64_t end) 444296177Sjhibbits{ 445296177Sjhibbits t_BusyBlock *p_CurrB, *p_PrevB, *p_NewB; 446296177Sjhibbits 447296177Sjhibbits p_CurrB = p_MM->busyBlocks; 448296177Sjhibbits p_PrevB = p_NewB = 0; 449296177Sjhibbits 450296177Sjhibbits while ( p_CurrB ) 451296177Sjhibbits { 452296177Sjhibbits if ( base < p_CurrB->end ) 453296177Sjhibbits { 454296177Sjhibbits if ( end > p_CurrB->end ) 455296177Sjhibbits { 456296177Sjhibbits t_BusyBlock *p_NextB; 457296177Sjhibbits while ( p_CurrB->p_Next && end >= p_CurrB->p_Next->end ) 458296177Sjhibbits { 459296177Sjhibbits p_NextB = p_CurrB->p_Next; 460296177Sjhibbits p_CurrB->p_Next = p_CurrB->p_Next->p_Next; 461296177Sjhibbits XX_Free(p_NextB); 462296177Sjhibbits } 463296177Sjhibbits 464296177Sjhibbits p_NextB = p_CurrB->p_Next; 465296177Sjhibbits if ( p_NextB && end > p_NextB->base ) 466296177Sjhibbits { 467296177Sjhibbits p_NextB->base = end; 468296177Sjhibbits } 469296177Sjhibbits } 470296177Sjhibbits 471296177Sjhibbits if ( base <= p_CurrB->base ) 472296177Sjhibbits { 473296177Sjhibbits if ( end < p_CurrB->end && end > p_CurrB->base ) 474296177Sjhibbits { 475296177Sjhibbits p_CurrB->base = end; 476296177Sjhibbits } 477296177Sjhibbits else if ( end >= p_CurrB->end ) 478296177Sjhibbits { 479296177Sjhibbits if ( p_PrevB ) 480296177Sjhibbits p_PrevB->p_Next = p_CurrB->p_Next; 481296177Sjhibbits else 482296177Sjhibbits p_MM->busyBlocks = p_CurrB->p_Next; 483296177Sjhibbits XX_Free(p_CurrB); 484296177Sjhibbits } 485296177Sjhibbits } 486296177Sjhibbits else 487296177Sjhibbits { 488296177Sjhibbits if ( end < p_CurrB->end && end > p_CurrB->base ) 489296177Sjhibbits { 490296177Sjhibbits if ((p_NewB = CreateBusyBlock(end, 491296177Sjhibbits p_CurrB->end-end, 492296177Sjhibbits p_CurrB->name)) == NULL) 493296177Sjhibbits RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); 494296177Sjhibbits p_NewB->p_Next = p_CurrB->p_Next; 495296177Sjhibbits p_CurrB->p_Next = p_NewB; 496296177Sjhibbits } 497296177Sjhibbits p_CurrB->end = base; 498296177Sjhibbits } 499296177Sjhibbits break; 500296177Sjhibbits } 501296177Sjhibbits else 502296177Sjhibbits { 503296177Sjhibbits p_PrevB = p_CurrB; 504296177Sjhibbits p_CurrB = p_CurrB->p_Next; 505296177Sjhibbits } 506296177Sjhibbits } 507296177Sjhibbits 508296177Sjhibbits return (E_OK); 509296177Sjhibbits} 510296177Sjhibbits 511296177Sjhibbits/**************************************************************** 512296177Sjhibbits * Routine: MmGetGreaterAlignment 513296177Sjhibbits * 514296177Sjhibbits * Description: 515296177Sjhibbits * Allocates a block of memory according to the given size 516296177Sjhibbits * and the alignment. That routine is called from the MM_Get 517296177Sjhibbits * routine if the required alignment is greater then MM_MAX_ALIGNMENT. 518296177Sjhibbits * In that case, it goes over free blocks of 64 byte align list 519296177Sjhibbits * and checks if it has the required size of bytes of the required 520296177Sjhibbits * alignment. If no blocks found returns ILLEGAL_BASE. 521296177Sjhibbits * After the block is found and data is allocated, it calls 522296177Sjhibbits * the internal CutFree routine to update all free lists 523296177Sjhibbits * do not include a just allocated block. Of course, each 524296177Sjhibbits * free list contains a free blocks with the same alignment. 525296177Sjhibbits * It is also creates a busy block that holds 526296177Sjhibbits * information about an allocated block. 527296177Sjhibbits * 528296177Sjhibbits * Arguments: 529296177Sjhibbits * MM - handle to the MM object 530296177Sjhibbits * size - size of the MM 531296177Sjhibbits * alignment - index as a power of two defines 532296177Sjhibbits * a required alignment that is greater then 64. 533296177Sjhibbits * name - the name that specifies an allocated block. 534296177Sjhibbits * 535296177Sjhibbits * Return value: 536296177Sjhibbits * base address of an allocated block. 537296177Sjhibbits * ILLEGAL_BASE if can't allocate a block 538296177Sjhibbits * 539296177Sjhibbits ****************************************************************/ 540296177Sjhibbitsstatic uint64_t MmGetGreaterAlignment(t_MM *p_MM, uint64_t size, uint64_t alignment, char* name) 541296177Sjhibbits{ 542296177Sjhibbits t_FreeBlock *p_FreeB; 543296177Sjhibbits t_BusyBlock *p_NewBusyB; 544296177Sjhibbits uint64_t holdBase, holdEnd, alignBase = 0; 545296177Sjhibbits 546296177Sjhibbits /* goes over free blocks of the 64 byte alignment list 547296177Sjhibbits and look for a block of the suitable size and 548296177Sjhibbits base address according to the alignment. */ 549296177Sjhibbits p_FreeB = p_MM->freeBlocks[MM_MAX_ALIGNMENT]; 550296177Sjhibbits 551296177Sjhibbits while ( p_FreeB ) 552296177Sjhibbits { 553296177Sjhibbits alignBase = MAKE_ALIGNED(p_FreeB->base, alignment); 554296177Sjhibbits 555296177Sjhibbits /* the block is found if the aligned base inside the block 556296177Sjhibbits * and has the anough size. */ 557296177Sjhibbits if ( alignBase >= p_FreeB->base && 558296177Sjhibbits alignBase < p_FreeB->end && 559296177Sjhibbits size <= (p_FreeB->end - alignBase) ) 560296177Sjhibbits break; 561296177Sjhibbits else 562296177Sjhibbits p_FreeB = p_FreeB->p_Next; 563296177Sjhibbits } 564296177Sjhibbits 565296177Sjhibbits /* If such block isn't found */ 566296177Sjhibbits if ( !p_FreeB ) 567296177Sjhibbits return (uint64_t)(ILLEGAL_BASE); 568296177Sjhibbits 569296177Sjhibbits holdBase = alignBase; 570296177Sjhibbits holdEnd = alignBase + size; 571296177Sjhibbits 572296177Sjhibbits /* init a new busy block */ 573296177Sjhibbits if ((p_NewBusyB = CreateBusyBlock(holdBase, size, name)) == NULL) 574296177Sjhibbits return (uint64_t)(ILLEGAL_BASE); 575296177Sjhibbits 576296177Sjhibbits /* calls Update routine to update a lists of free blocks */ 577296177Sjhibbits if ( CutFree ( p_MM, holdBase, holdEnd ) != E_OK ) 578296177Sjhibbits return (uint64_t)(ILLEGAL_BASE); 579296177Sjhibbits 580296177Sjhibbits /* insert the new busy block into the list of busy blocks */ 581296177Sjhibbits AddBusy ( p_MM, p_NewBusyB ); 582296177Sjhibbits 583296177Sjhibbits return (holdBase); 584296177Sjhibbits} 585296177Sjhibbits 586296177Sjhibbits 587296177Sjhibbits/********************************************************************** 588296177Sjhibbits * MM API routines set * 589296177Sjhibbits **********************************************************************/ 590296177Sjhibbits 591296177Sjhibbits/*****************************************************************************/ 592296177Sjhibbitst_Error MM_Init(t_Handle *h_MM, uint64_t base, uint64_t size) 593296177Sjhibbits{ 594296177Sjhibbits t_MM *p_MM; 595296177Sjhibbits uint64_t newBase, newSize; 596296177Sjhibbits int i; 597296177Sjhibbits 598296177Sjhibbits if (!size) 599296177Sjhibbits { 600296177Sjhibbits RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Size (should be positive)")); 601296177Sjhibbits } 602296177Sjhibbits 603296177Sjhibbits /* Initializes a new MM object */ 604296177Sjhibbits p_MM = (t_MM *)XX_Malloc(sizeof(t_MM)); 605296177Sjhibbits if (!p_MM) 606296177Sjhibbits { 607296177Sjhibbits RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); 608296177Sjhibbits } 609296177Sjhibbits 610296177Sjhibbits p_MM->h_Spinlock = XX_InitSpinlock(); 611296177Sjhibbits if (!p_MM->h_Spinlock) 612296177Sjhibbits { 613296177Sjhibbits XX_Free(p_MM); 614296177Sjhibbits RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MM spinlock!")); 615296177Sjhibbits } 616296177Sjhibbits 617296177Sjhibbits /* initializes a new memory block */ 618296177Sjhibbits if ((p_MM->memBlocks = CreateNewBlock(base, size)) == NULL) 619296177Sjhibbits RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); 620296177Sjhibbits 621296177Sjhibbits /* A busy list is empty */ 622296177Sjhibbits p_MM->busyBlocks = 0; 623296177Sjhibbits 624296177Sjhibbits /*Initializes a new free block for each free list*/ 625296177Sjhibbits for (i=0; i <= MM_MAX_ALIGNMENT; i++) 626296177Sjhibbits { 627296177Sjhibbits newBase = MAKE_ALIGNED( base, (0x1 << i) ); 628296177Sjhibbits newSize = size - (newBase - base); 629296177Sjhibbits 630296177Sjhibbits if ((p_MM->freeBlocks[i] = CreateFreeBlock(newBase, newSize)) == NULL) 631296177Sjhibbits RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); 632296177Sjhibbits } 633296177Sjhibbits 634296177Sjhibbits *h_MM = p_MM; 635296177Sjhibbits 636296177Sjhibbits return (E_OK); 637296177Sjhibbits} 638296177Sjhibbits 639296177Sjhibbits/*****************************************************************************/ 640296177Sjhibbitsvoid MM_Free(t_Handle h_MM) 641296177Sjhibbits{ 642296177Sjhibbits t_MM *p_MM = (t_MM *)h_MM; 643296177Sjhibbits t_MemBlock *p_MemBlock; 644296177Sjhibbits t_BusyBlock *p_BusyBlock; 645296177Sjhibbits t_FreeBlock *p_FreeBlock; 646296177Sjhibbits void *p_Block; 647296177Sjhibbits int i; 648296177Sjhibbits 649296177Sjhibbits ASSERT_COND(p_MM); 650296177Sjhibbits 651296177Sjhibbits /* release memory allocated for busy blocks */ 652296177Sjhibbits p_BusyBlock = p_MM->busyBlocks; 653296177Sjhibbits while ( p_BusyBlock ) 654296177Sjhibbits { 655296177Sjhibbits p_Block = p_BusyBlock; 656296177Sjhibbits p_BusyBlock = p_BusyBlock->p_Next; 657296177Sjhibbits XX_Free(p_Block); 658296177Sjhibbits } 659296177Sjhibbits 660296177Sjhibbits /* release memory allocated for free blocks */ 661296177Sjhibbits for (i=0; i <= MM_MAX_ALIGNMENT; i++) 662296177Sjhibbits { 663296177Sjhibbits p_FreeBlock = p_MM->freeBlocks[i]; 664296177Sjhibbits while ( p_FreeBlock ) 665296177Sjhibbits { 666296177Sjhibbits p_Block = p_FreeBlock; 667296177Sjhibbits p_FreeBlock = p_FreeBlock->p_Next; 668296177Sjhibbits XX_Free(p_Block); 669296177Sjhibbits } 670296177Sjhibbits } 671296177Sjhibbits 672296177Sjhibbits /* release memory allocated for memory blocks */ 673296177Sjhibbits p_MemBlock = p_MM->memBlocks; 674296177Sjhibbits while ( p_MemBlock ) 675296177Sjhibbits { 676296177Sjhibbits p_Block = p_MemBlock; 677296177Sjhibbits p_MemBlock = p_MemBlock->p_Next; 678296177Sjhibbits XX_Free(p_Block); 679296177Sjhibbits } 680296177Sjhibbits 681296177Sjhibbits if (p_MM->h_Spinlock) 682296177Sjhibbits XX_FreeSpinlock(p_MM->h_Spinlock); 683296177Sjhibbits 684296177Sjhibbits /* release memory allocated for MM object itself */ 685296177Sjhibbits XX_Free(p_MM); 686296177Sjhibbits} 687296177Sjhibbits 688296177Sjhibbits/*****************************************************************************/ 689296177Sjhibbitsuint64_t MM_Get(t_Handle h_MM, uint64_t size, uint64_t alignment, char* name) 690296177Sjhibbits{ 691296177Sjhibbits t_MM *p_MM = (t_MM *)h_MM; 692296177Sjhibbits t_FreeBlock *p_FreeB; 693296177Sjhibbits t_BusyBlock *p_NewBusyB; 694296177Sjhibbits uint64_t holdBase, holdEnd, j, i = 0; 695296177Sjhibbits uint32_t intFlags; 696296177Sjhibbits 697296177Sjhibbits SANITY_CHECK_RETURN_VALUE(p_MM, E_INVALID_HANDLE, (uint64_t)ILLEGAL_BASE); 698296177Sjhibbits 699296177Sjhibbits /* checks that alignment value is greater then zero */ 700296177Sjhibbits if (alignment == 0) 701296177Sjhibbits { 702296177Sjhibbits alignment = 1; 703296177Sjhibbits } 704296177Sjhibbits 705296177Sjhibbits j = alignment; 706296177Sjhibbits 707296177Sjhibbits /* checks if alignment is a power of two, if it correct and if the 708296177Sjhibbits required size is multiple of the given alignment. */ 709296177Sjhibbits while ((j & 0x1) == 0) 710296177Sjhibbits { 711296177Sjhibbits i++; 712296177Sjhibbits j = j >> 1; 713296177Sjhibbits } 714296177Sjhibbits 715296177Sjhibbits /* if the given alignment isn't power of two, returns an error */ 716296177Sjhibbits if (j != 1) 717296177Sjhibbits { 718296177Sjhibbits REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("alignment (should be power of 2)")); 719296177Sjhibbits return (uint64_t)ILLEGAL_BASE; 720296177Sjhibbits } 721296177Sjhibbits 722296177Sjhibbits if (i > MM_MAX_ALIGNMENT) 723296177Sjhibbits { 724296177Sjhibbits return (MmGetGreaterAlignment(p_MM, size, alignment, name)); 725296177Sjhibbits } 726296177Sjhibbits 727296177Sjhibbits intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock); 728296177Sjhibbits /* look for a block of the size greater or equal to the required size. */ 729296177Sjhibbits p_FreeB = p_MM->freeBlocks[i]; 730296177Sjhibbits while ( p_FreeB && (p_FreeB->end - p_FreeB->base) < size ) 731296177Sjhibbits p_FreeB = p_FreeB->p_Next; 732296177Sjhibbits 733296177Sjhibbits /* If such block is found */ 734296177Sjhibbits if ( !p_FreeB ) 735296177Sjhibbits { 736296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 737296177Sjhibbits return (uint64_t)(ILLEGAL_BASE); 738296177Sjhibbits } 739296177Sjhibbits 740296177Sjhibbits holdBase = p_FreeB->base; 741296177Sjhibbits holdEnd = holdBase + size; 742296177Sjhibbits 743296177Sjhibbits /* init a new busy block */ 744296177Sjhibbits if ((p_NewBusyB = CreateBusyBlock(holdBase, size, name)) == NULL) 745296177Sjhibbits { 746296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 747296177Sjhibbits return (uint64_t)(ILLEGAL_BASE); 748296177Sjhibbits } 749296177Sjhibbits 750296177Sjhibbits /* calls Update routine to update a lists of free blocks */ 751296177Sjhibbits if ( CutFree ( p_MM, holdBase, holdEnd ) != E_OK ) 752296177Sjhibbits { 753296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 754296177Sjhibbits return (uint64_t)(ILLEGAL_BASE); 755296177Sjhibbits } 756296177Sjhibbits 757296177Sjhibbits /* insert the new busy block into the list of busy blocks */ 758296177Sjhibbits AddBusy ( p_MM, p_NewBusyB ); 759296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 760296177Sjhibbits 761296177Sjhibbits return (holdBase); 762296177Sjhibbits} 763296177Sjhibbits 764296177Sjhibbits/*****************************************************************************/ 765296177Sjhibbitsuint64_t MM_GetForce(t_Handle h_MM, uint64_t base, uint64_t size, char* name) 766296177Sjhibbits{ 767296177Sjhibbits t_MM *p_MM = (t_MM *)h_MM; 768296177Sjhibbits t_FreeBlock *p_FreeB; 769296177Sjhibbits t_BusyBlock *p_NewBusyB; 770296177Sjhibbits uint32_t intFlags; 771296177Sjhibbits bool blockIsFree = FALSE; 772296177Sjhibbits 773296177Sjhibbits ASSERT_COND(p_MM); 774296177Sjhibbits 775296177Sjhibbits intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock); 776296177Sjhibbits p_FreeB = p_MM->freeBlocks[0]; /* The biggest free blocks are in the 777296177Sjhibbits free list with alignment 1 */ 778296177Sjhibbits 779296177Sjhibbits while ( p_FreeB ) 780296177Sjhibbits { 781296177Sjhibbits if ( base >= p_FreeB->base && (base+size) <= p_FreeB->end ) 782296177Sjhibbits { 783296177Sjhibbits blockIsFree = TRUE; 784296177Sjhibbits break; 785296177Sjhibbits } 786296177Sjhibbits else 787296177Sjhibbits p_FreeB = p_FreeB->p_Next; 788296177Sjhibbits } 789296177Sjhibbits 790296177Sjhibbits if ( !blockIsFree ) 791296177Sjhibbits { 792296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 793296177Sjhibbits return (uint64_t)(ILLEGAL_BASE); 794296177Sjhibbits } 795296177Sjhibbits 796296177Sjhibbits /* init a new busy block */ 797296177Sjhibbits if ((p_NewBusyB = CreateBusyBlock(base, size, name)) == NULL) 798296177Sjhibbits { 799296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 800296177Sjhibbits return (uint64_t)(ILLEGAL_BASE); 801296177Sjhibbits } 802296177Sjhibbits 803296177Sjhibbits /* calls Update routine to update a lists of free blocks */ 804296177Sjhibbits if ( CutFree ( p_MM, base, base+size ) != E_OK ) 805296177Sjhibbits { 806296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 807296177Sjhibbits return (uint64_t)(ILLEGAL_BASE); 808296177Sjhibbits } 809296177Sjhibbits 810296177Sjhibbits /* insert the new busy block into the list of busy blocks */ 811296177Sjhibbits AddBusy ( p_MM, p_NewBusyB ); 812296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 813296177Sjhibbits 814296177Sjhibbits return (base); 815296177Sjhibbits} 816296177Sjhibbits 817296177Sjhibbits/*****************************************************************************/ 818296177Sjhibbitsuint64_t MM_GetForceMin(t_Handle h_MM, uint64_t size, uint64_t alignment, uint64_t min, char* name) 819296177Sjhibbits{ 820296177Sjhibbits t_MM *p_MM = (t_MM *)h_MM; 821296177Sjhibbits t_FreeBlock *p_FreeB; 822296177Sjhibbits t_BusyBlock *p_NewBusyB; 823296177Sjhibbits uint64_t holdBase, holdEnd, j = alignment, i=0; 824296177Sjhibbits uint32_t intFlags; 825296177Sjhibbits 826296177Sjhibbits ASSERT_COND(p_MM); 827296177Sjhibbits 828296177Sjhibbits /* checks if alignment is a power of two, if it correct and if the 829296177Sjhibbits required size is multiple of the given alignment. */ 830296177Sjhibbits while ((j & 0x1) == 0) 831296177Sjhibbits { 832296177Sjhibbits i++; 833296177Sjhibbits j = j >> 1; 834296177Sjhibbits } 835296177Sjhibbits 836296177Sjhibbits if ( (j != 1) || (i > MM_MAX_ALIGNMENT) ) 837296177Sjhibbits { 838296177Sjhibbits return (uint64_t)(ILLEGAL_BASE); 839296177Sjhibbits } 840296177Sjhibbits 841296177Sjhibbits intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock); 842296177Sjhibbits p_FreeB = p_MM->freeBlocks[i]; 843296177Sjhibbits 844296177Sjhibbits /* look for the first block that contains the minimum 845296177Sjhibbits base address. If the whole required size may be fit 846296177Sjhibbits into it, use that block, otherwise look for the next 847296177Sjhibbits block of size greater or equal to the required size. */ 848296177Sjhibbits while ( p_FreeB && (min >= p_FreeB->end)) 849296177Sjhibbits p_FreeB = p_FreeB->p_Next; 850296177Sjhibbits 851296177Sjhibbits /* If such block is found */ 852296177Sjhibbits if ( !p_FreeB ) 853296177Sjhibbits { 854296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 855296177Sjhibbits return (uint64_t)(ILLEGAL_BASE); 856296177Sjhibbits } 857296177Sjhibbits 858296177Sjhibbits /* if this block is large enough, use this block */ 859296177Sjhibbits holdBase = ( min <= p_FreeB->base ) ? p_FreeB->base : min; 860296177Sjhibbits if ((holdBase + size) <= p_FreeB->end ) 861296177Sjhibbits { 862296177Sjhibbits holdEnd = holdBase + size; 863296177Sjhibbits } 864296177Sjhibbits else 865296177Sjhibbits { 866296177Sjhibbits p_FreeB = p_FreeB->p_Next; 867296177Sjhibbits while ( p_FreeB && ((p_FreeB->end - p_FreeB->base) < size) ) 868296177Sjhibbits p_FreeB = p_FreeB->p_Next; 869296177Sjhibbits 870296177Sjhibbits /* If such block is found */ 871296177Sjhibbits if ( !p_FreeB ) 872296177Sjhibbits { 873296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 874296177Sjhibbits return (uint64_t)(ILLEGAL_BASE); 875296177Sjhibbits } 876296177Sjhibbits 877296177Sjhibbits holdBase = p_FreeB->base; 878296177Sjhibbits holdEnd = holdBase + size; 879296177Sjhibbits } 880296177Sjhibbits 881296177Sjhibbits /* init a new busy block */ 882296177Sjhibbits if ((p_NewBusyB = CreateBusyBlock(holdBase, size, name)) == NULL) 883296177Sjhibbits { 884296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 885296177Sjhibbits return (uint64_t)(ILLEGAL_BASE); 886296177Sjhibbits } 887296177Sjhibbits 888296177Sjhibbits /* calls Update routine to update a lists of free blocks */ 889296177Sjhibbits if ( CutFree( p_MM, holdBase, holdEnd ) != E_OK ) 890296177Sjhibbits { 891296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 892296177Sjhibbits return (uint64_t)(ILLEGAL_BASE); 893296177Sjhibbits } 894296177Sjhibbits 895296177Sjhibbits /* insert the new busy block into the list of busy blocks */ 896296177Sjhibbits AddBusy( p_MM, p_NewBusyB ); 897296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 898296177Sjhibbits 899296177Sjhibbits return (holdBase); 900296177Sjhibbits} 901296177Sjhibbits 902296177Sjhibbits/*****************************************************************************/ 903296177Sjhibbitsuint64_t MM_Put(t_Handle h_MM, uint64_t base) 904296177Sjhibbits{ 905296177Sjhibbits t_MM *p_MM = (t_MM *)h_MM; 906296177Sjhibbits t_BusyBlock *p_BusyB, *p_PrevBusyB; 907296177Sjhibbits uint64_t size; 908296177Sjhibbits uint32_t intFlags; 909296177Sjhibbits 910296177Sjhibbits ASSERT_COND(p_MM); 911296177Sjhibbits 912296177Sjhibbits /* Look for a busy block that have the given base value. 913296177Sjhibbits * That block will be returned back to the memory. 914296177Sjhibbits */ 915296177Sjhibbits p_PrevBusyB = 0; 916296177Sjhibbits 917296177Sjhibbits intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock); 918296177Sjhibbits p_BusyB = p_MM->busyBlocks; 919296177Sjhibbits while ( p_BusyB && base != p_BusyB->base ) 920296177Sjhibbits { 921296177Sjhibbits p_PrevBusyB = p_BusyB; 922296177Sjhibbits p_BusyB = p_BusyB->p_Next; 923296177Sjhibbits } 924296177Sjhibbits 925296177Sjhibbits if ( !p_BusyB ) 926296177Sjhibbits { 927296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 928296177Sjhibbits return (uint64_t)(0); 929296177Sjhibbits } 930296177Sjhibbits 931296177Sjhibbits if ( AddFree( p_MM, p_BusyB->base, p_BusyB->end ) != E_OK ) 932296177Sjhibbits { 933296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 934296177Sjhibbits return (uint64_t)(0); 935296177Sjhibbits } 936296177Sjhibbits 937296177Sjhibbits /* removes a busy block form the list of busy blocks */ 938296177Sjhibbits if ( p_PrevBusyB ) 939296177Sjhibbits p_PrevBusyB->p_Next = p_BusyB->p_Next; 940296177Sjhibbits else 941296177Sjhibbits p_MM->busyBlocks = p_BusyB->p_Next; 942296177Sjhibbits 943296177Sjhibbits size = p_BusyB->end - p_BusyB->base; 944296177Sjhibbits 945296177Sjhibbits XX_Free(p_BusyB); 946296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 947296177Sjhibbits 948296177Sjhibbits return (size); 949296177Sjhibbits} 950296177Sjhibbits 951296177Sjhibbits/*****************************************************************************/ 952296177Sjhibbitsuint64_t MM_PutForce(t_Handle h_MM, uint64_t base, uint64_t size) 953296177Sjhibbits{ 954296177Sjhibbits t_MM *p_MM = (t_MM *)h_MM; 955296177Sjhibbits uint64_t end = base + size; 956296177Sjhibbits uint32_t intFlags; 957296177Sjhibbits 958296177Sjhibbits ASSERT_COND(p_MM); 959296177Sjhibbits 960296177Sjhibbits intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock); 961296177Sjhibbits if ( CutBusy( p_MM, base, end ) != E_OK ) 962296177Sjhibbits { 963296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 964296177Sjhibbits return (uint64_t)(0); 965296177Sjhibbits } 966296177Sjhibbits 967296177Sjhibbits if ( AddFree ( p_MM, base, end ) != E_OK ) 968296177Sjhibbits { 969296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 970296177Sjhibbits return (uint64_t)(0); 971296177Sjhibbits } 972296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 973296177Sjhibbits 974296177Sjhibbits return (size); 975296177Sjhibbits} 976296177Sjhibbits 977296177Sjhibbits/*****************************************************************************/ 978296177Sjhibbitst_Error MM_Add(t_Handle h_MM, uint64_t base, uint64_t size) 979296177Sjhibbits{ 980296177Sjhibbits t_MM *p_MM = (t_MM *)h_MM; 981296177Sjhibbits t_MemBlock *p_MemB, *p_NewMemB; 982296177Sjhibbits t_Error errCode; 983296177Sjhibbits uint32_t intFlags; 984296177Sjhibbits 985296177Sjhibbits ASSERT_COND(p_MM); 986296177Sjhibbits 987296177Sjhibbits /* find a last block in the list of memory blocks to insert a new 988296177Sjhibbits * memory block 989296177Sjhibbits */ 990296177Sjhibbits intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock); 991296177Sjhibbits p_MemB = p_MM->memBlocks; 992296177Sjhibbits while ( p_MemB->p_Next ) 993296177Sjhibbits { 994296177Sjhibbits if ( base >= p_MemB->base && base < p_MemB->end ) 995296177Sjhibbits { 996296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 997296177Sjhibbits RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG); 998296177Sjhibbits } 999296177Sjhibbits p_MemB = p_MemB->p_Next; 1000296177Sjhibbits } 1001296177Sjhibbits /* check for a last memory block */ 1002296177Sjhibbits if ( base >= p_MemB->base && base < p_MemB->end ) 1003296177Sjhibbits { 1004296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 1005296177Sjhibbits RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG); 1006296177Sjhibbits } 1007296177Sjhibbits 1008296177Sjhibbits /* create a new memory block */ 1009296177Sjhibbits if ((p_NewMemB = CreateNewBlock(base, size)) == NULL) 1010296177Sjhibbits { 1011296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 1012296177Sjhibbits RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); 1013296177Sjhibbits } 1014296177Sjhibbits 1015296177Sjhibbits /* append a new memory block to the end of the list of memory blocks */ 1016296177Sjhibbits p_MemB->p_Next = p_NewMemB; 1017296177Sjhibbits 1018296177Sjhibbits /* add a new free block to the free lists */ 1019296177Sjhibbits errCode = AddFree(p_MM, base, base+size); 1020296177Sjhibbits if (errCode) 1021296177Sjhibbits { 1022296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 1023296177Sjhibbits p_MemB->p_Next = 0; 1024296177Sjhibbits XX_Free(p_NewMemB); 1025296177Sjhibbits return ((t_Error)errCode); 1026296177Sjhibbits } 1027296177Sjhibbits XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); 1028296177Sjhibbits 1029296177Sjhibbits return (E_OK); 1030296177Sjhibbits} 1031296177Sjhibbits 1032296177Sjhibbits/*****************************************************************************/ 1033296177Sjhibbitsuint64_t MM_GetMemBlock(t_Handle h_MM, int index) 1034296177Sjhibbits{ 1035296177Sjhibbits t_MM *p_MM = (t_MM*)h_MM; 1036296177Sjhibbits t_MemBlock *p_MemBlock; 1037296177Sjhibbits int i; 1038296177Sjhibbits 1039296177Sjhibbits ASSERT_COND(p_MM); 1040296177Sjhibbits 1041296177Sjhibbits p_MemBlock = p_MM->memBlocks; 1042296177Sjhibbits for (i=0; i < index; i++) 1043296177Sjhibbits p_MemBlock = p_MemBlock->p_Next; 1044296177Sjhibbits 1045296177Sjhibbits if ( p_MemBlock ) 1046296177Sjhibbits return (p_MemBlock->base); 1047296177Sjhibbits else 1048296177Sjhibbits return (uint64_t)ILLEGAL_BASE; 1049296177Sjhibbits} 1050296177Sjhibbits 1051296177Sjhibbits/*****************************************************************************/ 1052296177Sjhibbitsuint64_t MM_GetBase(t_Handle h_MM) 1053296177Sjhibbits{ 1054296177Sjhibbits t_MM *p_MM = (t_MM*)h_MM; 1055296177Sjhibbits t_MemBlock *p_MemBlock; 1056296177Sjhibbits 1057296177Sjhibbits ASSERT_COND(p_MM); 1058296177Sjhibbits 1059296177Sjhibbits p_MemBlock = p_MM->memBlocks; 1060296177Sjhibbits return p_MemBlock->base; 1061296177Sjhibbits} 1062296177Sjhibbits 1063296177Sjhibbits/*****************************************************************************/ 1064296177Sjhibbitsbool MM_InRange(t_Handle h_MM, uint64_t addr) 1065296177Sjhibbits{ 1066296177Sjhibbits t_MM *p_MM = (t_MM*)h_MM; 1067296177Sjhibbits t_MemBlock *p_MemBlock; 1068296177Sjhibbits 1069296177Sjhibbits ASSERT_COND(p_MM); 1070296177Sjhibbits 1071296177Sjhibbits p_MemBlock = p_MM->memBlocks; 1072296177Sjhibbits 1073296177Sjhibbits if ((addr >= p_MemBlock->base) && (addr < p_MemBlock->end)) 1074296177Sjhibbits return TRUE; 1075296177Sjhibbits else 1076296177Sjhibbits return FALSE; 1077296177Sjhibbits} 1078296177Sjhibbits 1079296177Sjhibbits/*****************************************************************************/ 1080296177Sjhibbitsvoid MM_Dump(t_Handle h_MM, void *buff) 1081296177Sjhibbits{ 1082296177Sjhibbits t_MM *p_MM = (t_MM *)h_MM; 1083296177Sjhibbits t_FreeBlock *p_FreeB; 1084296177Sjhibbits t_BusyBlock *p_BusyB; 1085296177Sjhibbits int i; 1086296177Sjhibbits 1087296177Sjhibbits p_BusyB = p_MM->busyBlocks; 1088296177Sjhibbits Sprint(buff, "List of busy blocks:\n"); 1089296177Sjhibbits while (p_BusyB) 1090296177Sjhibbits { 1091296177Sjhibbits Sprint(buff, "\t0x%p: (%s: b=0x%lx, e=0x%lx)\n", 1092296177Sjhibbits p_BusyB, p_BusyB->name, p_BusyB->base, p_BusyB->end ); 1093296177Sjhibbits p_BusyB = p_BusyB->p_Next; 1094296177Sjhibbits } 1095296177Sjhibbits 1096296177Sjhibbits Sprint(buff, "\nLists of free blocks according to alignment:\n"); 1097296177Sjhibbits for (i=0; i <= MM_MAX_ALIGNMENT; i++) 1098296177Sjhibbits { 1099296177Sjhibbits Sprint(buff, "%d alignment:\n", (0x1 << i)); 1100296177Sjhibbits p_FreeB = p_MM->freeBlocks[i]; 1101296177Sjhibbits while (p_FreeB) 1102296177Sjhibbits { 1103296177Sjhibbits Sprint(buff, "\t0x%p: (b=0x%lx, e=0x%lx)\n", 1104296177Sjhibbits p_FreeB, p_FreeB->base, p_FreeB->end); 1105296177Sjhibbits p_FreeB = p_FreeB->p_Next; 1106296177Sjhibbits } 1107296177Sjhibbits Sprint(buff, "\n"); 1108296177Sjhibbits } 1109296177Sjhibbits} 1110