ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

blocklist.c
Go to the documentation of this file.
00001 /*
00002  *  FreeLoader
00003  *  Copyright (C) 1998-2003  Brian Palmer  <brianp@sginet.com>
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License along
00016  *  with this program; if not, write to the Free Software Foundation, Inc.,
00017  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00018  */
00019 
00020 #include <freeldr.h>
00021 #include <debug.h>
00022 
00023 DBG_DEFAULT_CHANNEL(CACHE);
00024 
00025 // Returns a pointer to a CACHE_BLOCK structure
00026 // Adds the block to the cache manager block list
00027 // in cache memory if it isn't already there
00028 PCACHE_BLOCK CacheInternalGetBlockPointer(PCACHE_DRIVE CacheDrive, ULONG BlockNumber)
00029 {
00030     PCACHE_BLOCK    CacheBlock = NULL;
00031 
00032     TRACE("CacheInternalGetBlockPointer() BlockNumber = %d\n", BlockNumber);
00033 
00034     CacheBlock = CacheInternalFindBlock(CacheDrive, BlockNumber);
00035 
00036     if (CacheBlock != NULL)
00037     {
00038         TRACE("Cache hit! BlockNumber: %d CacheBlock->BlockNumber: %d\n", BlockNumber, CacheBlock->BlockNumber);
00039 
00040         return CacheBlock;
00041     }
00042 
00043     TRACE("Cache miss! BlockNumber: %d\n", BlockNumber);
00044 
00045     CacheBlock = CacheInternalAddBlockToCache(CacheDrive, BlockNumber);
00046 
00047     // Optimize the block list so it has a LRU structure
00048     CacheInternalOptimizeBlockList(CacheDrive, CacheBlock);
00049 
00050     return CacheBlock;
00051 }
00052 
00053 PCACHE_BLOCK CacheInternalFindBlock(PCACHE_DRIVE CacheDrive, ULONG BlockNumber)
00054 {
00055     PCACHE_BLOCK    CacheBlock = NULL;
00056 
00057     TRACE("CacheInternalFindBlock() BlockNumber = %d\n", BlockNumber);
00058 
00059     //
00060     // Make sure the block list has entries before I start searching it.
00061     //
00062     if (!IsListEmpty(&CacheDrive->CacheBlockHead))
00063     {
00064         //
00065         // Search the list and find the BIOS drive number
00066         //
00067         CacheBlock = CONTAINING_RECORD(CacheDrive->CacheBlockHead.Flink, CACHE_BLOCK, ListEntry);
00068 
00069         while (&CacheBlock->ListEntry != &CacheDrive->CacheBlockHead)
00070         {
00071             //
00072             // We found the block, so return it
00073             //
00074             if (CacheBlock->BlockNumber == BlockNumber)
00075             {
00076                 //
00077                 // Increment the blocks access count
00078                 //
00079                 CacheBlock->AccessCount++;
00080 
00081                 return CacheBlock;
00082             }
00083 
00084             CacheBlock = CONTAINING_RECORD(CacheBlock->ListEntry.Flink, CACHE_BLOCK, ListEntry);
00085         }
00086     }
00087 
00088     return NULL;
00089 }
00090 
00091 PCACHE_BLOCK CacheInternalAddBlockToCache(PCACHE_DRIVE CacheDrive, ULONG BlockNumber)
00092 {
00093     PCACHE_BLOCK    CacheBlock = NULL;
00094 
00095     TRACE("CacheInternalAddBlockToCache() BlockNumber = %d\n", BlockNumber);
00096 
00097     // Check the size of the cache so we don't exceed our limits
00098     CacheInternalCheckCacheSizeLimits(CacheDrive);
00099 
00100     // We will need to add the block to the
00101     // drive's list of cached blocks. So allocate
00102     // the block memory.
00103     CacheBlock = MmHeapAlloc(sizeof(CACHE_BLOCK));
00104     if (CacheBlock == NULL)
00105     {
00106         return NULL;
00107     }
00108 
00109     // Now initialize the structure and
00110     // allocate room for the block data
00111     RtlZeroMemory(CacheBlock, sizeof(CACHE_BLOCK));
00112     CacheBlock->BlockNumber = BlockNumber;
00113     CacheBlock->BlockData = MmHeapAlloc(CacheDrive->BlockSize * CacheDrive->BytesPerSector);
00114     if (CacheBlock->BlockData ==NULL)
00115     {
00116         MmHeapFree(CacheBlock);
00117         return NULL;
00118     }
00119 
00120     // Now try to read in the block
00121     if (!MachDiskReadLogicalSectors(CacheDrive->DriveNumber, (BlockNumber * CacheDrive->BlockSize), CacheDrive->BlockSize, (PVOID)DISKREADBUFFER))
00122     {
00123         MmHeapFree(CacheBlock->BlockData);
00124         MmHeapFree(CacheBlock);
00125         return NULL;
00126     }
00127     RtlCopyMemory(CacheBlock->BlockData, (PVOID)DISKREADBUFFER, CacheDrive->BlockSize * CacheDrive->BytesPerSector);
00128 
00129     // Add it to our list of blocks managed by the cache
00130     InsertTailList(&CacheDrive->CacheBlockHead, &CacheBlock->ListEntry);
00131 
00132     // Update the cache data
00133     CacheBlockCount++;
00134     CacheSizeCurrent = CacheBlockCount * (CacheDrive->BlockSize * CacheDrive->BytesPerSector);
00135 
00136     CacheInternalDumpBlockList(CacheDrive);
00137 
00138     return CacheBlock;
00139 }
00140 
00141 BOOLEAN CacheInternalFreeBlock(PCACHE_DRIVE CacheDrive)
00142 {
00143     PCACHE_BLOCK    CacheBlockToFree;
00144 
00145     TRACE("CacheInternalFreeBlock()\n");
00146 
00147     // Get a pointer to the last item in the block list
00148     // that isn't forced to be in the cache and remove
00149     // it from the list
00150     CacheBlockToFree = CONTAINING_RECORD(CacheDrive->CacheBlockHead.Blink, CACHE_BLOCK, ListEntry);
00151     while (&CacheBlockToFree->ListEntry != &CacheDrive->CacheBlockHead && CacheBlockToFree->LockedInCache == TRUE)
00152     {
00153         CacheBlockToFree = CONTAINING_RECORD(CacheBlockToFree->ListEntry.Blink, CACHE_BLOCK, ListEntry);
00154     }
00155 
00156     // No blocks left in cache that can be freed
00157     // so just return
00158     if (IsListEmpty(&CacheDrive->CacheBlockHead))
00159     {
00160         return FALSE;
00161     }
00162 
00163     RemoveEntryList(&CacheBlockToFree->ListEntry);
00164 
00165     // Free the block memory and the block structure
00166     MmHeapFree(CacheBlockToFree->BlockData);
00167     MmHeapFree(CacheBlockToFree);
00168 
00169     // Update the cache data
00170     CacheBlockCount--;
00171     CacheSizeCurrent = CacheBlockCount * (CacheDrive->BlockSize * CacheDrive->BytesPerSector);
00172 
00173     return TRUE;
00174 }
00175 
00176 VOID CacheInternalCheckCacheSizeLimits(PCACHE_DRIVE CacheDrive)
00177 {
00178     SIZE_T      NewCacheSize;
00179 
00180     TRACE("CacheInternalCheckCacheSizeLimits()\n");
00181 
00182     // Calculate the size of the cache if we added a block
00183     NewCacheSize = (CacheBlockCount + 1) * (CacheDrive->BlockSize * CacheDrive->BytesPerSector);
00184 
00185     // Check the new size against the cache size limit
00186     if (NewCacheSize > CacheSizeLimit)
00187     {
00188         CacheInternalFreeBlock(CacheDrive);
00189         CacheInternalDumpBlockList(CacheDrive);
00190     }
00191 }
00192 
00193 VOID CacheInternalDumpBlockList(PCACHE_DRIVE CacheDrive)
00194 {
00195     PCACHE_BLOCK    CacheBlock;
00196 
00197     TRACE("Dumping block list for BIOS drive 0x%x.\n", CacheDrive->DriveNumber);
00198     TRACE("BytesPerSector: %d.\n", CacheDrive->BytesPerSector);
00199     TRACE("BlockSize: %d.\n", CacheDrive->BlockSize);
00200     TRACE("CacheSizeLimit: %d.\n", CacheSizeLimit);
00201     TRACE("CacheSizeCurrent: %d.\n", CacheSizeCurrent);
00202     TRACE("CacheBlockCount: %d.\n", CacheBlockCount);
00203 
00204     CacheBlock = CONTAINING_RECORD(CacheDrive->CacheBlockHead.Flink, CACHE_BLOCK, ListEntry);
00205     while (&CacheBlock->ListEntry != &CacheDrive->CacheBlockHead)
00206     {
00207         TRACE("Cache Block: CacheBlock: 0x%x\n", CacheBlock);
00208         TRACE("Cache Block: Block Number: %d\n", CacheBlock->BlockNumber);
00209         TRACE("Cache Block: Access Count: %d\n", CacheBlock->AccessCount);
00210         TRACE("Cache Block: Block Data: 0x%x\n", CacheBlock->BlockData);
00211         TRACE("Cache Block: Locked In Cache: %d\n", CacheBlock->LockedInCache);
00212 
00213         if (CacheBlock->BlockData == NULL)
00214         {
00215             BugCheck("CacheBlock->BlockData == NULL\n");
00216         }
00217 
00218         CacheBlock = CONTAINING_RECORD(CacheBlock->ListEntry.Flink, CACHE_BLOCK, ListEntry);
00219     }
00220 }
00221 
00222 VOID CacheInternalOptimizeBlockList(PCACHE_DRIVE CacheDrive, PCACHE_BLOCK CacheBlock)
00223 {
00224 
00225     TRACE("CacheInternalOptimizeBlockList()\n");
00226 
00227     // Don't do this if this block is already at the head of the list
00228     if (&CacheBlock->ListEntry != CacheDrive->CacheBlockHead.Flink)
00229     {
00230         // Remove this item from the block list
00231         RemoveEntryList(&CacheBlock->ListEntry);
00232 
00233         // Re-insert it at the head of the list
00234         InsertHeadList(&CacheDrive->CacheBlockHead, &CacheBlock->ListEntry);
00235     }
00236 }

Generated on Sat May 26 2012 04:17:54 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.