diff --git a/src/system/kernel/cache/Jamfile b/src/system/kernel/cache/Jamfile index 1adf0cce9a..553704f072 100644 --- a/src/system/kernel/cache/Jamfile +++ b/src/system/kernel/cache/Jamfile @@ -1,7 +1,6 @@ SubDir HAIKU_TOP src system kernel cache ; KernelMergeObject kernel_cache.o : - block_allocator.cpp block_cache.cpp file_cache.cpp file_map.cpp diff --git a/src/system/kernel/cache/block_allocator.cpp b/src/system/kernel/cache/block_allocator.cpp deleted file mode 100644 index c25a7f080a..0000000000 --- a/src/system/kernel/cache/block_allocator.cpp +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Copyright 2005-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved. - * Distributed under the terms of the MIT License. - */ - - -#include "block_cache_private.h" - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - - -//#define TRACE_BLOCK_ALLOCATOR -#ifdef TRACE_BLOCK_ALLOCATOR -# define TRACE(x) dprintf x -#else -# define TRACE(x) ; -#endif - - -/** The BlockAddressPool class manages a block of virtual memory address - * ranges. - * The actual block of kBlockAddressSize bytes, currently 128 MB (as defined - * in block_cache_private.h) is divided into kBlockRangeSize or 64 kB - * ranges. - * You can ask for a free range, and when you're done, you return it into - * the pool. You usually only do that when the block cache owning the - * ranges is deleted, or if memory becomes tight, a new volume is mounted - * or whatever. - * - * The block_range class on the other side manages each range. Only allocated - * ranges have a block_range object. - * In the block cache, the ranges are put into a hash table - they are - * accessed within that hash by address. That way, a cached_block allocated - * in one range doesn't need to know its range. - * - * If you actually need physical memory, you must allocate it using the - * block_range Allocate() methods. - * - * The block_range is further divided into block_chunks. A block_chunk is - * a multiple of the page size - for block sizes below the page size, it's - * just one page. Pages for the block range are actually allocated and - * mapped per chunk, and not for the whole range. - * - * The block_range only exists to avoid fragmentation of the virtual memory - * region reserved for the block cache, since all allocations have the same - * size there can't be any fragmentation at all. - * - * NOTE: This code is a bit complicated, and maybe a slab allocator would have been - * the better choice. What this allows for (and what would not be easily possible - * with a slab allocator) is to keep blocks in physical memory, but don't - * have them mapped. This, of course, would only be important if you have - * more memory than address space available - which sounds like a good idea - * now, but with 64-bit address spaces it looks a bit different :-) - */ - -class BlockAddressPool { - public: - BlockAddressPool(); - ~BlockAddressPool(); - - status_t InitCheck() const { return fArea >= B_OK ? B_OK : fArea; } - - size_t RangeSize() const { return kBlockRangeSize; } - size_t RangeShift() const { return kBlockRangeShift; } - addr_t BaseAddress() const { return fBase; } - - addr_t Get(); - void Put(addr_t address); - - private: - benaphore fLock; - area_id fArea; - addr_t fBase; - addr_t fFirstFree; - int32 fNextFree; - int32 fFreeList[kBlockAddressSize / kBlockRangeSize]; -}; - - -static class BlockAddressPool sBlockAddressPool; - - -BlockAddressPool::BlockAddressPool() -{ - benaphore_init(&fLock, "block address pool"); - - fBase = 0xa0000000; - // directly after the I/O space area - fArea = vm_create_null_area(vm_kernel_address_space_id(), "block cache", - (void **)&fBase, B_BASE_ADDRESS, kBlockAddressSize); - - fFirstFree = fBase; - fNextFree = -1; -} - - -BlockAddressPool::~BlockAddressPool() -{ - delete_area(fArea); -} - - -addr_t -BlockAddressPool::Get() -{ - BenaphoreLocker locker(&fLock); - - // ToDo: we must make sure that a single volume will never eat - // all available ranges! Every mounted volume should have a - // guaranteed minimum available for its own use. - - addr_t address = fFirstFree; - if (address != NULL) { - // Blocks are first taken from the initial free chunk, and - // when that is empty, from the free list. - // This saves us the initialization of the free list array, - // dunno if it's such a good idea, though. - if ((fFirstFree += RangeSize()) >= fBase + kBlockAddressSize) - fFirstFree = NULL; - - return address; - } - - if (fNextFree == -1) - return NULL; - - address = (fNextFree << RangeShift()) + fBase; - fNextFree = fFreeList[fNextFree]; - - return address; -} - - -void -BlockAddressPool::Put(addr_t address) -{ - BenaphoreLocker locker(&fLock); - - int32 index = (address - fBase) >> RangeShift(); - fFreeList[index] = fNextFree; - fNextFree = index; -} - - -// #pragma mark - - - -/* static */ -int -block_range::Compare(void *_blockRange, const void *_address) -{ - block_range *range = (block_range *)_blockRange; - addr_t address = (addr_t)_address; - - return ((range->base - sBlockAddressPool.BaseAddress()) >> sBlockAddressPool.RangeShift()) - - ((address - sBlockAddressPool.BaseAddress()) >> sBlockAddressPool.RangeShift()); -} - - -/* static */ -uint32 -block_range::Hash(void *_blockRange, const void *_address, uint32 range) -{ - block_range *blockRange = (block_range *)_blockRange; - addr_t address = (addr_t)_address; - - if (blockRange != NULL) { - return ((blockRange->base - sBlockAddressPool.BaseAddress()) - >> sBlockAddressPool.RangeShift()) % range; - } - - return ((address - sBlockAddressPool.BaseAddress()) - >> sBlockAddressPool.RangeShift()) % range; -} - - -/* static */ -status_t -block_range::New(block_cache *cache, block_range **_range) -{ - addr_t address = sBlockAddressPool.Get(); - if (address == NULL) - return B_ENTRY_NOT_FOUND; - - block_range *range = (block_range *)malloc(sizeof(block_range) - + cache->chunks_per_range * sizeof(block_chunk)); - if (range == NULL) { - sBlockAddressPool.Put(address); - return B_NO_MEMORY; - } - - TRACE(("new block range %p, base = %p!\n", range, (void *)address)); - memset(range, 0, sizeof(block_range) + cache->chunks_per_range * sizeof(block_chunk)); - range->base = address; - - // insert into free ranges list and hash in cache - cache->free_ranges.Add(range); - hash_insert(cache->ranges_hash, range); - - *_range = range; - return B_OK; -} - - -/*static*/ -void -block_range::Delete(block_cache *cache, block_range *range) -{ - TRACE(("delete block range %p, base = %p!\n", range, (void *)range->base)); - - // unmap the memory - - vm_address_space *addressSpace = vm_kernel_address_space(); - vm_translation_map *map = &addressSpace->translation_map; - - map->ops->lock(map); - map->ops->unmap(map, range->base, range->base + kBlockRangeSize - 1); - map->ops->unlock(map); - - sBlockAddressPool.Put(range->base); - - // free pages - - uint32 numPages = kBlockRangeSize / B_PAGE_SIZE; - for (uint32 i = 0; i < numPages; i++) { - if (range->pages[i] == NULL) - continue; - - vm_page_set_state(range->pages[i], PAGE_STATE_FREE); - } - - // remove from cache free list and hash - cache->free_ranges.Remove(range); - hash_remove(cache->ranges_hash, range); - - free(range); -} - - -uint32 -block_range::BlockIndex(block_cache *cache, void *address) -{ - return (((addr_t)address - base) % cache->chunk_size) / cache->block_size; -} - - -uint32 -block_range::ChunkIndex(block_cache *cache, void *address) -{ - return ((addr_t)address - base) / cache->chunk_size; -} - - -block_chunk * -block_range::Chunk(block_cache *cache, void *address) -{ - return &chunks[ChunkIndex(cache, address)]; -} - - -status_t -block_range::Allocate(block_cache *cache, cached_block *block) -{ - block_chunk *chunk; - - void *address = Allocate(cache, &chunk); - if (address == NULL) - return B_NO_MEMORY; - - block->current_data = address; - - // add the block to the chunk - block->chunk_next = chunk->blocks; - chunk->blocks = block; - - return B_OK; -} - - -void -block_range::Free(block_cache *cache, cached_block *block) -{ - Free(cache, block->current_data); - block_chunk *chunk = Chunk(cache, block->current_data); - - // remove block from list - - cached_block *last = NULL, *next = chunk->blocks; - while (next != NULL && next != block) { - last = next; - next = next->chunk_next; - } - if (next == NULL) { - panic("cached_block %p was not in chunk %p\n", block, chunk); - } else { - if (last) - last->chunk_next = block->chunk_next; - else - chunk->blocks = block->chunk_next; - } - - block->current_data = NULL; -} - - -void * -block_range::Allocate(block_cache *cache, block_chunk **_chunk) -{ - // get free chunk in range - - uint32 chunk; - for (chunk = 0; chunk < cache->chunks_per_range; chunk++) { - if ((used_mask & (1UL << chunk)) == 0) - break; - } - if (chunk == cache->chunks_per_range) { - panic("block_range %p pretended to be free but isn't\n", this); - return NULL; - } - - // get free block in chunk - - uint32 numBlocks = cache->chunk_size / cache->block_size; - uint32 block; - for (block = 0; block < numBlocks; block++) { - if ((chunks[chunk].used_mask & (1UL << block)) == 0) - break; - } - if (block == numBlocks) { - panic("block_chunk %lu in range %p pretended to be free but isn't\n", block, this); - return NULL; - } - - if (!chunks[chunk].mapped) { - // allocate pages if needed - uint32 numPages = cache->chunk_size / B_PAGE_SIZE; - uint32 pageBaseIndex = numPages * chunk; - if (pages[pageBaseIndex] == NULL) { - // there are no pages for us yet - for (uint32 i = 0; i < numPages; i++) { - vm_page *page = vm_page_allocate_page(PAGE_STATE_FREE, false); - if (page == NULL) { - // ToDo: handle this gracefully - panic("no memory for block!!\n"); - return NULL; - } - - pages[pageBaseIndex + i] = page; - } - } - - // map the memory - - vm_address_space *addressSpace = vm_kernel_address_space(); - vm_translation_map *map = &addressSpace->translation_map; - size_t reservePages = map->ops->map_max_pages_need(map, - 0, numPages * B_PAGE_SIZE); - - vm_page_reserve_pages(reservePages); - map->ops->lock(map); - - for (uint32 i = 0; i < numPages; i++) { - map->ops->map(map, base + chunk * cache->chunk_size + i * B_PAGE_SIZE, - pages[pageBaseIndex + i]->physical_page_number * B_PAGE_SIZE, - B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); - } - - map->ops->unlock(map); - vm_page_unreserve_pages(reservePages); - - chunks[chunk].mapped = true; - } - - chunks[chunk].used_mask |= 1UL << block; - if (chunks[chunk].used_mask == cache->chunk_mask) { - // all blocks are used in this chunk, propagate usage bit - used_mask |= 1UL << chunk; - - if (used_mask == cache->range_mask) { - // range is full, remove it from the free list - cache->free_ranges.Remove(this); - } - } - TRACE(("Allocate: used masks: chunk = %x, range = %lx\n", chunks[chunk].used_mask, used_mask)); - - if (_chunk) - *_chunk = &chunks[chunk]; - return (void *)(base + cache->chunk_size * chunk + cache->block_size * block); -} - - -void -block_range::Free(block_cache *cache, void *address) -{ - uint32 chunk = ChunkIndex(cache, address); - - if (chunks[chunk].used_mask == cache->chunk_mask) { - if (used_mask == cache->range_mask) { - // range was full before, add it to the free list - cache->free_ranges.Add(this); - } - // chunk was full before, propagate usage bit to range - used_mask &= ~(1UL << chunk); - } - chunks[chunk].used_mask &= ~(1UL << BlockIndex(cache, address)); - - TRACE(("Free: used masks: chunk = %x, range = %lx\n", chunks[chunk].used_mask, used_mask)); -} - - -bool -block_range::Unused(const block_cache *cache) const -{ - if (used_mask != 0) - return false; - - for (int32 chunk = cache->chunks_per_range; chunk-- > 0;) { - if (chunks[chunk].used_mask != 0) - return false; - } - - return true; -} - - -// #pragma mark - - - -extern "C" status_t -init_block_allocator(void) -{ - new(&sBlockAddressPool) BlockAddressPool; - // static initializers do not work in the kernel, - // so we have to do it here, manually - - return sBlockAddressPool.InitCheck(); -} diff --git a/src/system/kernel/cache/block_cache.cpp b/src/system/kernel/cache/block_cache.cpp index 2b8b6177b3..77e3ea8639 100644 --- a/src/system/kernel/cache/block_cache.cpp +++ b/src/system/kernel/cache/block_cache.cpp @@ -195,6 +195,7 @@ static status_t write_cached_block(block_cache *cache, cached_block *block, static DoublyLinkedList sCaches; static mutex sCachesLock; #endif +static object_cache *sBlockCache; // #pragma mark - private transaction @@ -311,7 +312,6 @@ block_cache::block_cache(int _fd, off_t numBlocks, size_t blockSize, next_transaction_id(1), last_transaction(NULL), transaction_hash(NULL), - ranges_hash(NULL), read_only(readOnly) { #ifdef DEBUG_BLOCK_CACHE @@ -320,6 +320,11 @@ block_cache::block_cache(int _fd, off_t numBlocks, size_t blockSize, mutex_unlock(&sCachesLock); #endif + buffer_cache = create_object_cache_etc("block cache buffers", blockSize, + 8, 0, CACHE_LARGE_SLAB, NULL, NULL, NULL, NULL); + if (buffer_cache == NULL) + return; + hash = hash_init(32, 0, &cached_block::Compare, &cached_block::Hash); if (hash == NULL) return; @@ -329,18 +334,9 @@ block_cache::block_cache(int _fd, off_t numBlocks, size_t blockSize, if (transaction_hash == NULL) return; - ranges_hash = hash_init(16, 0, &block_range::Compare, &block_range::Hash); - if (ranges_hash == NULL) - return; - if (benaphore_init(&lock, "block cache") < B_OK) return; - chunk_size = max_c(blockSize, B_PAGE_SIZE); - chunks_per_range = kBlockRangeSize / chunk_size; - range_mask = (1UL << chunks_per_range) - 1; - chunk_mask = (1UL << (chunk_size / blockSize)) - 1; - register_low_memory_handler(&block_cache::LowMemoryHandler, this, 0); } @@ -357,9 +353,10 @@ block_cache::~block_cache() benaphore_destroy(&lock); - hash_uninit(ranges_hash); hash_uninit(transaction_hash); hash_uninit(hash); + + delete_object_cache(buffer_cache); } @@ -369,83 +366,31 @@ block_cache::InitCheck() if (lock.sem < B_OK) return lock.sem; - if (hash == NULL || transaction_hash == NULL || ranges_hash == NULL) + if (buffer_cache == NULL || hash == NULL || transaction_hash == NULL) return B_NO_MEMORY; return B_OK; } -block_range * -block_cache::GetFreeRange() -{ - if (!free_ranges.IsEmpty()) - return free_ranges.First(); - - // we need to allocate a new range - block_range *range; - if (block_range::New(this, &range) != B_OK) { - RemoveUnusedBlocks(2, 50); - - if (!free_ranges.IsEmpty()) - return free_ranges.First(); - - RemoveUnusedBlocks(LONG_MAX, 50); - - if (!free_ranges.IsEmpty()) - return free_ranges.First(); - - // TODO: We also need to free ranges from other caches to get a free one - // (if not, an active volume might have stolen all free ranges already) - return NULL; - } - - return range; -} - - -block_range * -block_cache::GetRange(void *address) -{ - return (block_range *)hash_lookup(ranges_hash, address); -} - - void -block_cache::Free(void *address) +block_cache::Free(void *buffer) { - if (address == NULL) - return; - - block_range *range = GetRange(address); - if (range == NULL) - panic("no range for address %p\n", address); - - ASSERT(range != NULL); - range->Free(this, address); - - if (range->Unused(this)) - block_range::Delete(this, range); + object_cache_free(buffer_cache, buffer); } void * block_cache::Allocate() { - block_range *range = GetFreeRange(); - if (range == NULL) - return NULL; - - return range->Allocate(this); + return object_cache_alloc(buffer_cache, 0); } void block_cache::FreeBlock(cached_block *block) { - block_range *range = GetRange(block->current_data); - ASSERT(range != NULL); - range->Free(this, block); + Free(block->current_data); if (block->original_data != NULL || block->parent_data != NULL) { panic("block_cache::FreeBlock(): %p, %p\n", block->original_data, @@ -456,10 +401,7 @@ block_cache::FreeBlock(cached_block *block) Free(block->compare); #endif - if (range->Unused(this)) - block_range::Delete(this, range); - - delete block; + object_cache_free(sBlockCache, block); } @@ -477,6 +419,14 @@ block_cache::_GetUnusedBlock() // remove block from lists iterator.Remove(); hash_remove(hash, block); + + // TODO: see if parent/compare data is handled correctly here! + if (block->parent_data != NULL + && block->parent_data != block->original_data) + Free(block->parent_data); + if (block->original_data != NULL) + Free(block->original_data); + return block; } @@ -488,15 +438,7 @@ block_cache::_GetUnusedBlock() cached_block * block_cache::NewBlock(off_t blockNumber) { - cached_block *block = new(nothrow) cached_block; - if (block != NULL) { - block_range *range = GetFreeRange(); - if (range == NULL) { - delete block; - block = NULL; - } else - range->Allocate(this, block); - } + cached_block *block = (cached_block *)object_cache_alloc(sBlockCache, 0); if (block == NULL) { dprintf("block allocation failed, unused list is %sempty.\n", unused_blocks.IsEmpty() ? "" : "not "); @@ -509,6 +451,12 @@ block_cache::NewBlock(off_t blockNumber) } } + block->current_data = Allocate(); + if (block->current_data == NULL) { + object_cache_free(sBlockCache, block); + return NULL; + } + block->block_number = blockNumber; block->ref_count = 0; block->accessed = 0; @@ -701,23 +649,6 @@ get_cached_block(block_cache *cache, off_t blockNumber, bool *_allocated, hash_insert(cache->hash, block); *_allocated = true; - } else { - // TODO: currently, the data is always mapped in -/* - if (block->ref_count == 0 && block->current_data != NULL) { - // see if the old block can be resurrected - block->current_data = cache->allocator->Acquire(block->current_data); - } - - if (block->current_data == NULL) { - // there is no block yet, but we need one - block->current_data = cache->allocator->Get(); - if (block->current_data == NULL) - return NULL; - - *_allocated = true; - } -*/ } if (*_allocated && readBlock) { @@ -938,8 +869,6 @@ dump_cache(int argc, char **argv) kprintf(" is-dirty"); if (block->unused) kprintf(" unused"); - if (block->unmapped) - kprintf(" unmapped"); kprintf("\n"); if (block->transaction != NULL) { kprintf(" transaction: %p (%ld)\n", block->transaction, @@ -965,10 +894,6 @@ dump_cache(int argc, char **argv) kprintf(" max_blocks: %Ld\n", cache->max_blocks); kprintf(" block_size: %lu\n", cache->block_size); kprintf(" next_transaction_id: %ld\n", cache->next_transaction_id); - kprintf(" chunks_per_range: %lu\n", cache->chunks_per_range); - kprintf(" chunks_size: %lu\n", cache->chunk_size); - kprintf(" range_mask: %lu\n", cache->range_mask); - kprintf(" chunks_mask: %lu\n", cache->chunk_mask); if (showBlocks) { kprintf(" blocks:\n"); @@ -984,13 +909,13 @@ dump_cache(int argc, char **argv) cached_block *block; while ((block = (cached_block *)hash_next(cache->hash, &iterator)) != NULL) { if (showBlocks) { - kprintf("%08lx %9Ld %08lx %08lx %08lx %5ld %6ld %c%c%c%c%c %08lx " + kprintf("%08lx %9Ld %08lx %08lx %08lx %5ld %6ld %c%c%c%c %08lx " "%08lx\n", (addr_t)block, block->block_number, (addr_t)block->current_data, (addr_t)block->original_data, (addr_t)block->parent_data, block->ref_count, block->accessed, block->busy ? 'B' : '-', block->is_writing ? 'W' : '-', block->is_dirty ? 'B' : '-', block->unused ? 'U' : '-', - block->unmapped ? 'M' : '-', (addr_t)block->transaction, + (addr_t)block->transaction, (addr_t)block->previous_transaction); } @@ -1026,6 +951,11 @@ dump_caches(int argc, char **argv) extern "C" status_t block_cache_init(void) { + sBlockCache = create_object_cache_etc("cached blocks", sizeof(cached_block), + 8, 0, CACHE_LARGE_SLAB, NULL, NULL, NULL, NULL); + if (sBlockCache == NULL) + return B_ERROR; + #ifdef DEBUG_BLOCK_CACHE mutex_init(&sCachesLock, "block caches"); new (&sCaches) DoublyLinkedList; @@ -1035,7 +965,7 @@ block_cache_init(void) add_debugger_command("block_cache", &dump_cache, "dumps a specific block cache"); #endif - return init_block_allocator(); + return B_OK; } @@ -1498,7 +1428,6 @@ cache_blocks_in_sub_transaction(void *_cache, int32 id) // #pragma mark - public block cache API -// public interface extern "C" void diff --git a/src/system/kernel/cache/block_cache_private.h b/src/system/kernel/cache/block_cache_private.h index 67eb342e5f..16e73a6700 100644 --- a/src/system/kernel/cache/block_cache_private.h +++ b/src/system/kernel/cache/block_cache_private.h @@ -7,6 +7,7 @@ #include +#include #include struct hash_table; @@ -16,25 +17,16 @@ struct vm_page; #define DEBUG_CHANGED -static const size_t kBlockAddressSize = 128 * 1024 * 1024; // 128 MB -static const size_t kBlockRangeSize = 64 * 1024; // 64 kB -static const size_t kBlockRangeShift = 16; -static const size_t kNumBlockRangePages = kBlockRangeSize / B_PAGE_SIZE; - struct cache_transaction; struct cached_block; -struct block_chunk; struct block_cache; -struct block_range; typedef DoublyLinkedListLink block_link; -typedef DoublyLinkedListLink range_link; struct cached_block { cached_block *next; // next in hash cached_block *transaction_next; block_link link; - cached_block *chunk_next; off_t block_number; void *current_data; void *original_data; @@ -48,7 +40,6 @@ struct cached_block { bool is_writing : 1; bool is_dirty : 1; bool unused : 1; - bool unmapped : 1; cache_transaction *transaction; cache_transaction *previous_transaction; @@ -60,43 +51,6 @@ typedef DoublyLinkedList > block_list; -struct block_chunk { - cached_block *blocks; - bool mapped; - uint16 used_mask; // min chunk size is 4096 bytes; min block size is 256 bytes -}; - -struct block_range { - block_range *next; // next in hash - range_link link; - addr_t base; - uint32 used_mask; - vm_page *pages[kNumBlockRangePages]; - block_chunk chunks[0]; - - static status_t New(block_cache *cache, block_range **_range); - static void Delete(block_cache *cache, block_range *range); - - status_t Allocate(block_cache *cache, cached_block *block); - void Free(block_cache *cache, cached_block *block); - - void *Allocate(block_cache *cache, block_chunk **_chunk = NULL); - void Free(block_cache *cache, void *address); - - uint32 BlockIndex(block_cache *cache, void *address); - uint32 ChunkIndex(block_cache *cache, void *address); - block_chunk *Chunk(block_cache *cache, void *address); - - bool Unused(const block_cache *cache) const; - - static int Compare(void *_blockRange, const void *_address); - static uint32 Hash(void *_blockRange, const void *_address, uint32 range); -}; - -typedef DoublyLinkedList > range_list; - struct block_cache : DoublyLinkedListLinkImpl { hash_table *hash; benaphore lock; @@ -107,13 +61,7 @@ struct block_cache : DoublyLinkedListLinkImpl { cache_transaction *last_transaction; hash_table *transaction_hash; - hash_table *ranges_hash; - range_list free_ranges; - uint32 chunks_per_range; - size_t chunk_size; - uint32 range_mask; - uint32 chunk_mask; - block_list unmapped_blocks; + object_cache *buffer_cache; block_list unused_blocks; bool read_only; @@ -123,13 +71,11 @@ struct block_cache : DoublyLinkedListLinkImpl { status_t InitCheck(); - block_range *GetFreeRange(); - block_range *GetRange(void *address); void RemoveUnusedBlocks(int32 maxAccessed = LONG_MAX, int32 count = LONG_MAX); void FreeBlock(cached_block *block); cached_block *NewBlock(off_t blockNumber); - void Free(void *address); + void Free(void *buffer); void *Allocate(); static void LowMemoryHandler(void *data, int32 level); @@ -138,15 +84,4 @@ private: cached_block *_GetUnusedBlock(); }; - -#ifdef __cplusplus -extern "C" { -#endif - -status_t init_block_allocator(); - -#ifdef __cplusplus -} -#endif - #endif /* BLOCK_CACHE_PRIVATE_H */