/* * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ // // cssmalloc - memory allocation in the CDSA world. // // Don't eat heavily before inspecting this code. // #include #include #include #include #include #include using LowLevelMemoryUtilities::alignof; using LowLevelMemoryUtilities::increment; using LowLevelMemoryUtilities::alignUp; extern "C" size_t malloc_size(void *); // // Features of the Allocator root class // bool Allocator::operator == (const Allocator &alloc) const throw() { return this == &alloc; } Allocator::~Allocator() { } // // Standard Allocator variants. // Note that all calls to Allocator::standard(xxx) with the same xxx argument // must produce compatible allocators (i.e. they must be work on a common memory // pool). This is trivially achieved here by using singletons. // struct DefaultAllocator : public Allocator { void *malloc(size_t size) throw(std::bad_alloc); void free(void *addr) throw(); void *realloc(void *addr, size_t size) throw(std::bad_alloc); }; struct SensitiveAllocator : public DefaultAllocator { void free(void *addr) throw(); void *realloc(void *addr, size_t size) throw(std::bad_alloc); }; struct DefaultAllocators { DefaultAllocator standard; SensitiveAllocator sensitive; }; static ModuleNexus defaultAllocators; Allocator &Allocator::standard(UInt32 request) { switch (request) { case normal: return defaultAllocators().standard; case sensitive: return defaultAllocators().sensitive; default: UnixError::throwMe(ENOMEM); } } void *DefaultAllocator::malloc(size_t size) throw(std::bad_alloc) { if (void *result = ::malloc(size)) return result; throw std::bad_alloc(); } void DefaultAllocator::free(void *addr) throw() { ::free(addr); } void *DefaultAllocator::realloc(void *addr, size_t newSize) throw(std::bad_alloc) { if (void *result = ::realloc(addr, newSize)) return result; throw std::bad_alloc(); } void SensitiveAllocator::free(void *addr) throw() { memset(addr, 0, malloc_size(addr)); DefaultAllocator::free(addr); } void *SensitiveAllocator::realloc(void *addr, size_t newSize) throw(std::bad_alloc) { size_t oldSize = malloc_size(addr); if (newSize < oldSize) memset(increment(addr, newSize), 0, oldSize - newSize); return DefaultAllocator::realloc(addr, newSize); } TrackingAllocator::~TrackingAllocator() { AllocSet::iterator first = mAllocSet.begin(), last = mAllocSet.end(); for (; first != last; ++first) mAllocator.free(*first); } // // Memory allocators for CssmHeap objects. // This implementation stores a pointer to the allocator used into memory // *after* the object's proper storage block. This allows the usual free() // functions to safely free our (hidden) pointer without knowing about it. // An allocator argument of NULL is interpreted as the standard allocator. // void *CssmHeap::operator new (size_t size, Allocator *alloc) throw(std::bad_alloc) { if (alloc == NULL) alloc = &Allocator::standard(); size = alignUp(size, alignof()); size_t totalSize = size + sizeof(Allocator *); void *addr = alloc->malloc(totalSize); *(Allocator **)increment(addr, size) = alloc; return addr; } void CssmHeap::operator delete (void *addr, size_t size, Allocator *alloc) throw() { alloc->free(addr); // as per C++ std, called (only) if construction fails } void CssmHeap::operator delete (void *addr, size_t size) throw() { void *end = increment(addr, alignUp(size, alignof())); (*(Allocator **)end)->free(addr); } // // CssmVector //