Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenblocklist.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
1.7.6.1
|