]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/cssmalloc.cpp
7994e803f2f0ab71f99e7a2c86bbc6a65080b937
[apple/security.git] / cdsa / cdsa_utilities / cssmalloc.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 //
20 // cssmalloc - memory allocation in the CDSA world.
21 //
22 // Don't eat heavily before inspecting this code.
23 //
24 #include <Security/cssmalloc.h>
25 #include <Security/memutils.h>
26 #include <Security/globalizer.h>
27 #include <stdlib.h>
28 #include <errno.h>
29
30 using LowLevelMemoryUtilities::alignof;
31 using LowLevelMemoryUtilities::increment;
32 using LowLevelMemoryUtilities::alignUp;
33
34
35 //
36 // Features of the CssmAllocator root class
37 //
38 bool CssmAllocator::operator == (const CssmAllocator &alloc) const
39 {
40 return this == &alloc;
41 }
42
43 CssmAllocator::~CssmAllocator()
44 {
45 }
46
47
48 //
49 // Standard CssmAllocator variants.
50 // Note that all calls to CssmAllocator::standard(xxx) with the same xxx argument
51 // must produce compatible allocators (i.e. they must be work on a common memory
52 // pool). This is trivially achieved here by using singletons.
53 //
54 struct DefaultCssmAllocator : public CssmAllocator {
55 void *malloc(size_t size);
56 void free(void *addr);
57 void *realloc(void *addr, size_t size);
58 };
59
60 static ModuleNexus<DefaultCssmAllocator> defaultAllocator;
61
62
63 CssmAllocator &CssmAllocator::standard(uint32)
64 {
65 return defaultAllocator();
66 }
67
68 void *DefaultCssmAllocator::malloc(size_t size)
69 {
70 if (void *result = ::malloc(size))
71 return result;
72 throw std::bad_alloc();
73 }
74
75 void DefaultCssmAllocator::free(void *addr)
76 {
77 ::free(addr);
78 }
79
80 void *DefaultCssmAllocator::realloc(void *addr, size_t newSize)
81 {
82 if (void *result = ::realloc(addr, newSize))
83 return result;
84 throw std::bad_alloc();
85 }
86
87 TrackingAllocator::~TrackingAllocator()
88 {
89 AllocSet::iterator first = mAllocSet.begin(), last = mAllocSet.end();
90 for (; first != last; ++first)
91 mAllocator.free(*first);
92 }
93
94 //
95 // CssmMemoryFunctionsAllocators
96 //
97 void *CssmMemoryFunctionsAllocator::malloc(size_t size)
98 { return functions.malloc(size); }
99
100 void CssmMemoryFunctionsAllocator::free(void *addr)
101 { return functions.free(addr); }
102
103 void *CssmMemoryFunctionsAllocator::realloc(void *addr, size_t size)
104 { return functions.realloc(addr, size); }
105
106
107 //
108 // CssmAllocatorMemoryFunctions
109 //
110 CssmAllocatorMemoryFunctions::CssmAllocatorMemoryFunctions(CssmAllocator &alloc)
111 {
112 AllocRef = &alloc;
113 malloc_func = relayMalloc;
114 free_func = relayFree;
115 realloc_func = relayRealloc;
116 calloc_func = relayCalloc;
117 }
118
119 void *CssmAllocatorMemoryFunctions::relayMalloc(size_t size, void *ref)
120 { return allocator(ref).malloc(size); }
121
122 void CssmAllocatorMemoryFunctions::relayFree(void *mem, void *ref)
123 { allocator(ref).free(mem); }
124
125 void *CssmAllocatorMemoryFunctions::relayRealloc(void *mem, size_t size, void *ref)
126 { return allocator(ref).realloc(mem, size); }
127
128 void *CssmAllocatorMemoryFunctions::relayCalloc(uint32 count, size_t size, void *ref)
129 {
130 // CssmAllocator doesn't have a calloc() method
131 void *mem = allocator(ref).malloc(size * count);
132 memset(mem, 0, size * count);
133 return mem;
134 }
135
136
137 //
138 // Memory allocators for CssmHeap objects.
139 // This implementation stores a pointer to the allocator used into memory
140 // *after* the object's proper storage block. This allows the usual free()
141 // functions to safely free our (hidden) pointer without knowing about it.
142 // An allocator argument of NULL is interpreted as the standard allocator.
143 //
144 void *CssmHeap::operator new (size_t size, CssmAllocator *alloc)
145 {
146 if (alloc == NULL)
147 alloc = &CssmAllocator::standard();
148 size = alignUp(size, alignof<CssmAllocator *>());
149 size_t totalSize = size + sizeof(CssmAllocator *);
150 void *addr = alloc->malloc(totalSize);
151 *(CssmAllocator **)increment(addr, size) = alloc;
152 return addr;
153 }
154
155 void CssmHeap::operator delete (void *addr, size_t size, CssmAllocator *alloc)
156 {
157 alloc->free(addr); // as per C++ std, called (only) if construction fails
158 }
159
160 void CssmHeap::operator delete (void *addr, size_t size)
161 {
162 void *end = increment(addr, alignUp(size, alignof<CssmAllocator *>()));
163 (*(CssmAllocator **)end)->free(addr);
164 }