2 * Copyright (c) 2012 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 Copyright (c) 1998-2012, Apple Inc. All rights reserved.
26 Responsibility: Christopher Kane
29 #include <CoreFoundation/CFBase.h>
30 #include "CFInternal.h"
31 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
34 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
35 #include <malloc/malloc.h>
36 #include <mach/mach.h>
42 // -------- -------- -------- -------- -------- -------- -------- --------
44 struct __CFAllocator
{
46 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
47 // CFAllocator structure must match struct _malloc_zone_t!
48 // The first two reserved fields in struct _malloc_zone_t are for us with CFRuntimeBase
49 size_t (*size
)(struct _malloc_zone_t
*zone
, const void *ptr
); /* returns the size of a block or 0 if not in this zone; must be fast, especially for negative answers */
50 void *(*malloc
)(struct _malloc_zone_t
*zone
, size_t size
);
51 void *(*calloc
)(struct _malloc_zone_t
*zone
, size_t num_items
, size_t size
); /* same as malloc, but block returned is set to zero */
52 void *(*valloc
)(struct _malloc_zone_t
*zone
, size_t size
); /* same as malloc, but block returned is set to zero and is guaranteed to be page aligned */
53 void (*free
)(struct _malloc_zone_t
*zone
, void *ptr
);
54 void *(*realloc
)(struct _malloc_zone_t
*zone
, void *ptr
, size_t size
);
55 void (*destroy
)(struct _malloc_zone_t
*zone
); /* zone is destroyed and all memory reclaimed */
56 const char *zone_name
;
58 /* Optional batch callbacks; these may be NULL */
59 unsigned (*batch_malloc
)(struct _malloc_zone_t
*zone
, size_t size
, void **results
, unsigned num_requested
); /* given a size, returns pointers capable of holding that size; returns the number of pointers allocated (maybe 0 or less than num_requested) */
60 void (*batch_free
)(struct _malloc_zone_t
*zone
, void **to_be_freed
, unsigned num_to_be_freed
); /* frees all the pointers in to_be_freed; note that to_be_freed may be overwritten during the process */
62 struct malloc_introspection_t
*introspect
;
65 /* aligned memory allocation. The callback may be NULL. */
66 void *(*memalign
)(struct _malloc_zone_t
*zone
, size_t alignment
, size_t size
);
68 /* free a pointer known to be in zone and known to have the given size. The callback may be NULL. */
69 void (*free_definite_size
)(struct _malloc_zone_t
*zone
, void *ptr
, size_t size
);
71 CFAllocatorRef _allocator
;
72 CFAllocatorContext _context
;
75 CF_INLINE CFAllocatorRetainCallBack
__CFAllocatorGetRetainFunction(const CFAllocatorContext
*context
) {
76 CFAllocatorRetainCallBack retval
= NULL
;
77 retval
= context
->retain
;
81 CF_INLINE CFAllocatorReleaseCallBack
__CFAllocatorGetReleaseFunction(const CFAllocatorContext
*context
) {
82 CFAllocatorReleaseCallBack retval
= NULL
;
83 retval
= context
->release
;
87 CF_INLINE CFAllocatorCopyDescriptionCallBack
__CFAllocatorGetCopyDescriptionFunction(const CFAllocatorContext
*context
) {
88 CFAllocatorCopyDescriptionCallBack retval
= NULL
;
89 retval
= context
->copyDescription
;
93 CF_INLINE CFAllocatorAllocateCallBack
__CFAllocatorGetAllocateFunction(const CFAllocatorContext
*context
) {
94 CFAllocatorAllocateCallBack retval
= NULL
;
95 retval
= context
->allocate
;
99 CF_INLINE CFAllocatorReallocateCallBack
__CFAllocatorGetReallocateFunction(const CFAllocatorContext
*context
) {
100 CFAllocatorReallocateCallBack retval
= NULL
;
101 retval
= context
->reallocate
;
105 CF_INLINE CFAllocatorDeallocateCallBack
__CFAllocatorGetDeallocateFunction(const CFAllocatorContext
*context
) {
106 CFAllocatorDeallocateCallBack retval
= NULL
;
107 retval
= context
->deallocate
;
111 CF_INLINE CFAllocatorPreferredSizeCallBack
__CFAllocatorGetPreferredSizeFunction(const CFAllocatorContext
*context
) {
112 CFAllocatorPreferredSizeCallBack retval
= NULL
;
113 retval
= context
->preferredSize
;
117 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
119 __private_extern__
void __CFAllocatorDeallocate(CFTypeRef cf
);
121 static kern_return_t
__CFAllocatorZoneIntrospectNoOp(void) {
125 static boolean_t
__CFAllocatorZoneIntrospectTrue(void) {
129 static size_t __CFAllocatorCustomSize(malloc_zone_t
*zone
, const void *ptr
) {
132 // The only way to implement this with a version 0 allocator would be
133 // for CFAllocator to keep track of all blocks allocated itself, which
134 // could be done, but would be bad for performance, so we don't do it.
135 // size_t (*size)(struct _malloc_zone_t *zone, const void *ptr);
136 /* returns the size of a block or 0 if not in this zone;
137 * must be fast, especially for negative answers */
140 static void *__CFAllocatorCustomMalloc(malloc_zone_t
*zone
, size_t size
) {
141 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
142 return CFAllocatorAllocate(allocator
, size
, 0);
145 static void *__CFAllocatorCustomCalloc(malloc_zone_t
*zone
, size_t num_items
, size_t size
) {
146 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
147 void *newptr
= CFAllocatorAllocate(allocator
, size
, 0);
148 if (newptr
) memset(newptr
, 0, size
);
152 static void *__CFAllocatorCustomValloc(malloc_zone_t
*zone
, size_t size
) {
153 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
154 if (size
>= ULONG_MAX
- 2 * vm_page_size
) return NULL
; // avoid integer overflow plus don't allow all pages to be allocated either
155 void *newptr
= CFAllocatorAllocate(allocator
, size
+ vm_page_size
, 0);
156 newptr
= (void *)round_page((uintptr_t)newptr
);
160 static void __CFAllocatorCustomFree(malloc_zone_t
*zone
, void *ptr
) {
161 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
162 CFAllocatorDeallocate(allocator
, ptr
);
165 static void *__CFAllocatorCustomRealloc(malloc_zone_t
*zone
, void *ptr
, size_t size
) {
166 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
167 return CFAllocatorReallocate(allocator
, ptr
, size
, 0);
170 static void __CFAllocatorCustomDestroy(malloc_zone_t
*zone
) {
171 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
172 // !!! we do it, and caller of malloc_destroy_zone() assumes
173 // COMPLETE responsibility for the result; NO Apple library
174 // code should be modified as a result of discovering that
175 // some activity results in inconveniences to developers
176 // trying to use malloc_destroy_zone() with a CFAllocatorRef;
177 // that's just too bad for them.
178 __CFAllocatorDeallocate(allocator
);
181 static size_t __CFAllocatorCustomGoodSize(malloc_zone_t
*zone
, size_t size
) {
182 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
183 return CFAllocatorGetPreferredSizeForSize(allocator
, size
, 0);
186 static struct malloc_introspection_t __CFAllocatorZoneIntrospect
= {
187 (void *)__CFAllocatorZoneIntrospectNoOp
,
188 (void *)__CFAllocatorCustomGoodSize
,
189 (void *)__CFAllocatorZoneIntrospectTrue
,
190 (void *)__CFAllocatorZoneIntrospectNoOp
,
191 (void *)__CFAllocatorZoneIntrospectNoOp
,
192 (void *)__CFAllocatorZoneIntrospectNoOp
,
193 (void *)__CFAllocatorZoneIntrospectNoOp
,
194 (void *)__CFAllocatorZoneIntrospectNoOp
197 static size_t __CFAllocatorNullSize(malloc_zone_t
*zone
, const void *ptr
) {
201 static void * __CFAllocatorNullMalloc(malloc_zone_t
*zone
, size_t size
) {
205 static void * __CFAllocatorNullCalloc(malloc_zone_t
*zone
, size_t num_items
, size_t size
) {
209 static void * __CFAllocatorNullValloc(malloc_zone_t
*zone
, size_t size
) {
213 static void __CFAllocatorNullFree(malloc_zone_t
*zone
, void *ptr
) {
216 static void * __CFAllocatorNullRealloc(malloc_zone_t
*zone
, void *ptr
, size_t size
) {
220 static void __CFAllocatorNullDestroy(malloc_zone_t
*zone
) {
223 static size_t __CFAllocatorNullGoodSize(malloc_zone_t
*zone
, size_t size
) {
227 static struct malloc_introspection_t __CFAllocatorNullZoneIntrospect
= {
228 (void *)__CFAllocatorZoneIntrospectNoOp
,
229 (void *)__CFAllocatorNullGoodSize
,
230 (void *)__CFAllocatorZoneIntrospectTrue
,
231 (void *)__CFAllocatorZoneIntrospectNoOp
,
232 (void *)__CFAllocatorZoneIntrospectNoOp
,
233 (void *)__CFAllocatorZoneIntrospectNoOp
,
234 (void *)__CFAllocatorZoneIntrospectNoOp
,
235 (void *)__CFAllocatorZoneIntrospectNoOp
238 static void *__CFAllocatorSystemAllocate(CFIndex size
, CFOptionFlags hint
, void *info
) {
239 return malloc_zone_malloc(info
, size
);
242 static void *__CFAllocatorSystemReallocate(void *ptr
, CFIndex newsize
, CFOptionFlags hint
, void *info
) {
243 return malloc_zone_realloc(info
, ptr
, newsize
);
246 static void __CFAllocatorSystemDeallocate(void *ptr
, void *info
) {
248 size_t size
= malloc_size(ptr
);
249 if (size
) memset(ptr
, 0xCC, size
);
251 malloc_zone_free(info
, ptr
);
256 static void *__CFAllocatorSystemAllocate(CFIndex size
, CFOptionFlags hint
, void *info
) {
260 static void *__CFAllocatorSystemReallocate(void *ptr
, CFIndex newsize
, CFOptionFlags hint
, void *info
) {
261 return realloc(ptr
, newsize
);
264 static void __CFAllocatorSystemDeallocate(void *ptr
, void *info
) {
269 static void *__CFAllocatorNullAllocate(CFIndex size
, CFOptionFlags hint
, void *info
) {
273 static void *__CFAllocatorNullReallocate(void *ptr
, CFIndex newsize
, CFOptionFlags hint
, void *info
) {
277 #if defined (__cplusplus)
278 static void * __CFAllocatorCPPMalloc(CFIndex allocSize
, CFOptionFlags hint
, void *info
)
280 return malloc(allocSize
);
282 static void * __CFAllocatorCPPReAlloc(void *ptr
, CFIndex newsize
, CFOptionFlags hint
, void *info
)
284 return realloc(ptr
, newsize
);
286 static void __CFAllocatorCPPFree(void *ptr
, void *info
)
293 static struct __CFAllocator __kCFAllocatorMalloc
= {
294 INIT_CFRUNTIME_BASE(),
295 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
296 __CFAllocatorCustomSize
,
297 __CFAllocatorCustomMalloc
,
298 __CFAllocatorCustomCalloc
,
299 __CFAllocatorCustomValloc
,
300 __CFAllocatorCustomFree
,
301 __CFAllocatorCustomRealloc
,
302 __CFAllocatorNullDestroy
,
303 "kCFAllocatorMalloc",
306 &__CFAllocatorZoneIntrospect
,
312 // Using the malloc functions directly is a total cheat, but works (in C)
313 // because the function signatures match in their common prefix of arguments.
314 // This saves us one hop through an adaptor function.
315 #if !defined (__cplusplus)
316 {0, NULL
, NULL
, NULL
, NULL
, (void *)malloc
, (void *)realloc
, (void *)free
, NULL
}
318 {0, NULL
, NULL
, NULL
, NULL
, __CFAllocatorCPPMalloc
,__CFAllocatorCPPReAlloc
, __CFAllocatorCPPFree
, NULL
}
319 #endif // __cplusplus
322 static struct __CFAllocator __kCFAllocatorMallocZone
= {
323 INIT_CFRUNTIME_BASE(),
324 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
325 __CFAllocatorCustomSize
,
326 __CFAllocatorCustomMalloc
,
327 __CFAllocatorCustomCalloc
,
328 __CFAllocatorCustomValloc
,
329 __CFAllocatorCustomFree
,
330 __CFAllocatorCustomRealloc
,
331 __CFAllocatorNullDestroy
,
332 "kCFAllocatorMallocZone",
335 &__CFAllocatorZoneIntrospect
,
341 {0, NULL
, NULL
, NULL
, NULL
, __CFAllocatorSystemAllocate
, __CFAllocatorSystemReallocate
, __CFAllocatorSystemDeallocate
, NULL
}
344 static struct __CFAllocator __kCFAllocatorSystemDefault
= {
345 INIT_CFRUNTIME_BASE(),
346 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
347 __CFAllocatorCustomSize
,
348 __CFAllocatorCustomMalloc
,
349 __CFAllocatorCustomCalloc
,
350 __CFAllocatorCustomValloc
,
351 __CFAllocatorCustomFree
,
352 __CFAllocatorCustomRealloc
,
353 __CFAllocatorNullDestroy
,
354 "kCFAllocatorSystemDefault",
357 &__CFAllocatorZoneIntrospect
,
363 {0, NULL
, NULL
, NULL
, NULL
, __CFAllocatorSystemAllocate
, __CFAllocatorSystemReallocate
, __CFAllocatorSystemDeallocate
, NULL
}
366 static struct __CFAllocator __kCFAllocatorNull
= {
367 INIT_CFRUNTIME_BASE(),
368 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
369 __CFAllocatorNullSize
,
370 __CFAllocatorNullMalloc
,
371 __CFAllocatorNullCalloc
,
372 __CFAllocatorNullValloc
,
373 __CFAllocatorNullFree
,
374 __CFAllocatorNullRealloc
,
375 __CFAllocatorNullDestroy
,
379 &__CFAllocatorNullZoneIntrospect
,
385 {0, NULL
, NULL
, NULL
, NULL
, __CFAllocatorNullAllocate
, __CFAllocatorNullReallocate
, NULL
, NULL
}
388 const CFAllocatorRef kCFAllocatorDefault
= NULL
;
389 const CFAllocatorRef kCFAllocatorSystemDefault
= &__kCFAllocatorSystemDefault
;
390 const CFAllocatorRef kCFAllocatorMalloc
= &__kCFAllocatorMalloc
;
391 const CFAllocatorRef kCFAllocatorMallocZone
= &__kCFAllocatorMallocZone
;
392 const CFAllocatorRef kCFAllocatorNull
= &__kCFAllocatorNull
;
393 const CFAllocatorRef kCFAllocatorUseContext
= (CFAllocatorRef
)0x03ab;
394 #undef kCFAllocatorSystemDefaultGCRefZero
395 #undef kCFAllocatorDefaultGCRefZero
396 const CFAllocatorRef kCFAllocatorSystemDefaultGCRefZero
= (CFAllocatorRef
)0x03ad;
397 const CFAllocatorRef kCFAllocatorDefaultGCRefZero
= (CFAllocatorRef
)0x03af;
399 static CFStringRef
__CFAllocatorCopyDescription(CFTypeRef cf
) {
400 CFAllocatorRef self
= (CFAllocatorRef
)cf
;
401 CFAllocatorRef allocator
= (kCFAllocatorUseContext
== self
->_allocator
) ? self
: self
->_allocator
;
402 return CFStringCreateWithFormat(allocator
, NULL
, CFSTR("<CFAllocator %p [%p]>{info = %p}"), cf
, allocator
, self
->_context
.info
);
403 // CF: should use copyDescription function here to describe info field
404 // remember to release value returned from copydescr function when this happens
407 __private_extern__ CFAllocatorRef
__CFAllocatorGetAllocator(CFTypeRef cf
) {
408 CFAllocatorRef allocator
= (CFAllocatorRef
)cf
;
409 return (kCFAllocatorUseContext
== allocator
->_allocator
) ? allocator
: allocator
->_allocator
;
412 __private_extern__
void __CFAllocatorDeallocate(CFTypeRef cf
) {
413 CFAllocatorRef self
= (CFAllocatorRef
)cf
;
414 CFAllocatorRef allocator
= self
->_allocator
;
415 CFAllocatorReleaseCallBack releaseFunc
= __CFAllocatorGetReleaseFunction(&self
->_context
);
416 if (kCFAllocatorUseContext
== allocator
) {
417 /* Rather a chicken and egg problem here, so we do things
418 in the reverse order from what was done at create time. */
419 CFAllocatorDeallocateCallBack deallocateFunc
= __CFAllocatorGetDeallocateFunction(&self
->_context
);
420 void *info
= self
->_context
.info
;
421 if (NULL
!= deallocateFunc
) {
422 INVOKE_CALLBACK2(deallocateFunc
, (void *)self
, info
);
424 if (NULL
!= releaseFunc
) {
425 INVOKE_CALLBACK1(releaseFunc
, info
);
428 if (NULL
!= releaseFunc
) {
429 INVOKE_CALLBACK1(releaseFunc
, self
->_context
.info
);
431 if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) CFAllocatorDeallocate(allocator
, (void *)self
);
435 static CFTypeID __kCFAllocatorTypeID
= _kCFRuntimeNotATypeID
;
437 static const CFRuntimeClass __CFAllocatorClass
= {
446 __CFAllocatorCopyDescription
449 __private_extern__
void __CFAllocatorInitialize(void) {
450 __kCFAllocatorTypeID
= _CFRuntimeRegisterClass(&__CFAllocatorClass
);
452 _CFRuntimeSetInstanceTypeID(&__kCFAllocatorSystemDefault
, __kCFAllocatorTypeID
);
453 __kCFAllocatorSystemDefault
._base
._cfisa
= __CFISAForTypeID(__kCFAllocatorTypeID
);
454 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
455 __kCFAllocatorSystemDefault
._context
.info
= (kCFUseCollectableAllocator
? objc_collectableZone() : malloc_default_zone());
457 __kCFAllocatorSystemDefault
._allocator
= kCFAllocatorSystemDefault
;
459 _CFRuntimeSetInstanceTypeID(&__kCFAllocatorMalloc
, __kCFAllocatorTypeID
);
460 __kCFAllocatorMalloc
._base
._cfisa
= __CFISAForTypeID(__kCFAllocatorTypeID
);
461 __kCFAllocatorMalloc
._allocator
= kCFAllocatorSystemDefault
;
463 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
464 _CFRuntimeSetInstanceTypeID(&__kCFAllocatorMallocZone
, __kCFAllocatorTypeID
);
465 __kCFAllocatorMallocZone
._base
._cfisa
= __CFISAForTypeID(__kCFAllocatorTypeID
);
466 __kCFAllocatorMallocZone
._allocator
= kCFAllocatorSystemDefault
;
467 __kCFAllocatorMallocZone
._context
.info
= malloc_default_zone();
470 _CFRuntimeSetInstanceTypeID(&__kCFAllocatorNull
, __kCFAllocatorTypeID
);
471 __kCFAllocatorNull
._base
._cfisa
= __CFISAForTypeID(__kCFAllocatorTypeID
);
472 __kCFAllocatorNull
._allocator
= kCFAllocatorSystemDefault
;
476 CFTypeID
CFAllocatorGetTypeID(void) {
477 return __kCFAllocatorTypeID
;
480 CFAllocatorRef
CFAllocatorGetDefault(void) {
481 return __CFGetDefaultAllocator();
484 void CFAllocatorSetDefault(CFAllocatorRef allocator
) {
485 if (kCFAllocatorSystemDefaultGCRefZero
== allocator
|| kCFAllocatorDefaultGCRefZero
== allocator
) {
488 CFAllocatorRef current
= __CFGetDefaultAllocator();
490 if (NULL
!= allocator
) {
491 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
494 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
495 if (allocator
&& allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
496 return; // require allocator to this function to be an allocator
499 if (NULL
!= allocator
&& allocator
!= current
) {
500 if (current
) CFRelease(current
);
502 // We retain an extra time so that anything set as the default
503 // allocator never goes away.
505 _CFSetTSD(__CFTSDKeyAllocator
, (void *)allocator
, NULL
);
509 static CFAllocatorRef
__CFAllocatorCreate(CFAllocatorRef allocator
, CFAllocatorContext
*context
) {
510 struct __CFAllocator
*memory
= NULL
;
511 CFAllocatorRetainCallBack retainFunc
;
512 CFAllocatorAllocateCallBack allocateFunc
;
514 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
515 if (allocator
&& kCFAllocatorUseContext
!= allocator
&& allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
516 return NULL
; // require allocator to this function to be an allocator
519 retainFunc
= context
->retain
;
520 FAULT_CALLBACK((void **)&retainFunc
);
521 allocateFunc
= context
->allocate
;
522 FAULT_CALLBACK((void **)&allocateFunc
);
523 if (NULL
!= retainFunc
) {
524 retainedInfo
= (void *)INVOKE_CALLBACK1(retainFunc
, context
->info
);
526 retainedInfo
= context
->info
;
528 // We don't use _CFRuntimeCreateInstance()
529 if (kCFAllocatorUseContext
== allocator
) {
532 memory
= (struct __CFAllocator
*)INVOKE_CALLBACK3(allocateFunc
, sizeof(struct __CFAllocator
), 0, retainedInfo
);
534 if (NULL
== memory
) {
538 allocator
= (NULL
== allocator
) ? __CFGetDefaultAllocator() : allocator
;
539 memory
= (struct __CFAllocator
*)CFAllocatorAllocate(allocator
, sizeof(struct __CFAllocator
), __kCFAllocatorGCObjectMemory
);
540 if (NULL
== memory
) {
543 if (__CFOASafe
) __CFSetLastAllocationEventName(memory
, "CFAllocator");
545 memset(memory
, 0, sizeof(CFRuntimeBase
));
546 memory
->_base
._cfisa
= 0;
548 memory
->_base
._rc
= 1;
550 memory
->_base
._cfinfo
[CF_RC_BITS
] = 1;
552 memory
->_base
._cfinfo
[CF_INFO_BITS
] = 0;
553 _CFRuntimeSetInstanceTypeID(memory
, __kCFAllocatorTypeID
);
554 memory
->_base
._cfisa
= __CFISAForTypeID(__kCFAllocatorTypeID
);
555 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
556 memory
->size
= __CFAllocatorCustomSize
;
557 memory
->malloc
= __CFAllocatorCustomMalloc
;
558 memory
->calloc
= __CFAllocatorCustomCalloc
;
559 memory
->valloc
= __CFAllocatorCustomValloc
;
560 memory
->free
= __CFAllocatorCustomFree
;
561 memory
->realloc
= __CFAllocatorCustomRealloc
;
562 memory
->destroy
= __CFAllocatorCustomDestroy
;
563 memory
->zone_name
= "Custom CFAllocator";
564 memory
->batch_malloc
= NULL
;
565 memory
->batch_free
= NULL
;
566 memory
->introspect
= &__CFAllocatorZoneIntrospect
;
568 memory
->memalign
= NULL
;
569 memory
->free_definite_size
= NULL
;
571 memory
->_allocator
= allocator
;
572 memory
->_context
.version
= context
->version
;
573 memory
->_context
.info
= retainedInfo
;
574 memory
->_context
.retain
= retainFunc
;
575 memory
->_context
.release
= context
->release
;
576 FAULT_CALLBACK((void **)&(memory
->_context
.release
));
577 memory
->_context
.copyDescription
= context
->copyDescription
;
578 FAULT_CALLBACK((void **)&(memory
->_context
.copyDescription
));
579 memory
->_context
.allocate
= allocateFunc
;
580 memory
->_context
.reallocate
= context
->reallocate
;
581 FAULT_CALLBACK((void **)&(memory
->_context
.reallocate
));
582 memory
->_context
.deallocate
= context
->deallocate
;
583 FAULT_CALLBACK((void **)&(memory
->_context
.deallocate
));
584 memory
->_context
.preferredSize
= context
->preferredSize
;
585 FAULT_CALLBACK((void **)&(memory
->_context
.preferredSize
));
590 CFAllocatorRef
CFAllocatorCreate(CFAllocatorRef allocator
, CFAllocatorContext
*context
) {
591 return __CFAllocatorCreate(allocator
, context
);
594 void *CFAllocatorAllocate(CFAllocatorRef allocator
, CFIndex size
, CFOptionFlags hint
) {
595 CFAllocatorAllocateCallBack allocateFunc
;
598 Boolean initialRefcountOne
= true;
599 if (kCFAllocatorSystemDefaultGCRefZero
== allocator
) {
600 allocator
= kCFAllocatorSystemDefault
;
601 initialRefcountOne
= false;
602 } else if (kCFAllocatorDefaultGCRefZero
== allocator
) {
603 // Under GC, we can't use just any old allocator when the GCRefZero allocator was requested
604 allocator
= kCFUseCollectableAllocator
? kCFAllocatorSystemDefault
: __CFGetDefaultAllocator();
605 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) initialRefcountOne
= false;
606 } else if (NULL
== allocator
) {
607 allocator
= __CFGetDefaultAllocator();
610 #if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
611 if (allocator
->_base
._cfisa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
612 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
615 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
617 if (0 == size
) return NULL
;
618 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
619 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
620 return malloc_zone_malloc((malloc_zone_t
*)allocator
, size
);
623 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) {
624 newptr
= auto_zone_allocate_object((auto_zone_t
*)allocator
->_context
.info
, size
, CF_GET_GC_MEMORY_TYPE(hint
), initialRefcountOne
, false);
627 allocateFunc
= __CFAllocatorGetAllocateFunction(&allocator
->_context
);
629 newptr
= (void *)INVOKE_CALLBACK3(allocateFunc
, size
, hint
, allocator
->_context
.info
);
635 void *CFAllocatorReallocate(CFAllocatorRef allocator
, void *ptr
, CFIndex newsize
, CFOptionFlags hint
) {
636 CFAllocatorAllocateCallBack allocateFunc
;
637 CFAllocatorReallocateCallBack reallocateFunc
;
638 CFAllocatorDeallocateCallBack deallocateFunc
;
641 if (kCFAllocatorSystemDefaultGCRefZero
== allocator
) {
642 allocator
= kCFAllocatorSystemDefault
;
643 } else if (kCFAllocatorDefaultGCRefZero
== allocator
) {
644 // Under GC, we can't use just any old allocator when the GCRefZero allocator was requested
645 allocator
= kCFUseCollectableAllocator
? kCFAllocatorSystemDefault
: __CFGetDefaultAllocator();
646 } else if (NULL
== allocator
) {
647 allocator
= __CFGetDefaultAllocator();
650 #if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
651 if (allocator
->_base
._cfisa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
652 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
655 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
657 if (NULL
== ptr
&& 0 < newsize
) {
658 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
659 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
660 return malloc_zone_malloc((malloc_zone_t
*)allocator
, newsize
);
664 allocateFunc
= __CFAllocatorGetAllocateFunction(&allocator
->_context
);
666 newptr
= (void *)INVOKE_CALLBACK3(allocateFunc
, newsize
, hint
, allocator
->_context
.info
);
670 if (NULL
!= ptr
&& 0 == newsize
) {
671 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
672 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
674 size_t size
= malloc_size(ptr
);
675 if (size
) memset(ptr
, 0xCC, size
);
677 malloc_zone_free((malloc_zone_t
*)allocator
, ptr
);
681 deallocateFunc
= __CFAllocatorGetDeallocateFunction(&allocator
->_context
);
682 if (NULL
!= deallocateFunc
) {
683 INVOKE_CALLBACK2(deallocateFunc
, ptr
, allocator
->_context
.info
);
687 if (NULL
== ptr
&& 0 == newsize
) return NULL
;
688 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
689 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
690 return malloc_zone_realloc((malloc_zone_t
*)allocator
, ptr
, newsize
);
693 reallocateFunc
= __CFAllocatorGetReallocateFunction(&allocator
->_context
);
694 if (NULL
== reallocateFunc
) return NULL
;
695 newptr
= (void *)INVOKE_CALLBACK4(reallocateFunc
, ptr
, newsize
, hint
, allocator
->_context
.info
);
699 void CFAllocatorDeallocate(CFAllocatorRef allocator
, void *ptr
) {
700 CFAllocatorDeallocateCallBack deallocateFunc
;
702 if (kCFAllocatorSystemDefaultGCRefZero
== allocator
) {
703 if (_CFAllocatorIsGCRefZero(allocator
)) return;
704 allocator
= kCFAllocatorSystemDefault
;
705 } else if (kCFAllocatorDefaultGCRefZero
== allocator
) {
706 // Under GC, we can't use just any old allocator when the GCRefZero allocator was requested
707 allocator
= kCFUseCollectableAllocator
? kCFAllocatorSystemDefault
: __CFGetDefaultAllocator();
708 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) return;
709 } else if (NULL
== allocator
) {
710 allocator
= __CFGetDefaultAllocator();
713 #if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
714 if (allocator
->_base
._cfisa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
715 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
718 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
720 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
721 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
723 size_t size
= malloc_size(ptr
);
724 if (size
) memset(ptr
, 0xCC, size
);
726 return malloc_zone_free((malloc_zone_t
*)allocator
, ptr
);
729 deallocateFunc
= __CFAllocatorGetDeallocateFunction(&allocator
->_context
);
730 if (NULL
!= ptr
&& NULL
!= deallocateFunc
) {
731 INVOKE_CALLBACK2(deallocateFunc
, ptr
, allocator
->_context
.info
);
735 CFIndex
CFAllocatorGetPreferredSizeForSize(CFAllocatorRef allocator
, CFIndex size
, CFOptionFlags hint
) {
736 CFAllocatorPreferredSizeCallBack prefFunc
;
739 if (kCFAllocatorSystemDefaultGCRefZero
== allocator
) {
740 allocator
= kCFAllocatorSystemDefault
;
741 } else if (kCFAllocatorDefaultGCRefZero
== allocator
) {
742 // Under GC, we can't use just any old allocator when the GCRefZero allocator was requested
743 allocator
= kCFUseCollectableAllocator
? kCFAllocatorSystemDefault
: __CFGetDefaultAllocator();
744 } else if (NULL
== allocator
) {
745 allocator
= __CFGetDefaultAllocator();
748 #if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
749 if (allocator
->_base
._cfisa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
750 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
753 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
755 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
756 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
757 return malloc_good_size(size
);
760 prefFunc
= __CFAllocatorGetPreferredSizeFunction(&allocator
->_context
);
761 if (0 < size
&& NULL
!= prefFunc
) {
762 newsize
= (CFIndex
)(INVOKE_CALLBACK3(prefFunc
, size
, hint
, allocator
->_context
.info
));
764 if (newsize
< size
) newsize
= size
;
768 void CFAllocatorGetContext(CFAllocatorRef allocator
, CFAllocatorContext
*context
) {
769 if (kCFAllocatorSystemDefaultGCRefZero
== allocator
) {
770 allocator
= kCFAllocatorSystemDefault
;
771 } else if (kCFAllocatorDefaultGCRefZero
== allocator
) {
772 // Under GC, we can't use just any old allocator when the GCRefZero allocator was requested
773 allocator
= kCFUseCollectableAllocator
? kCFAllocatorSystemDefault
: __CFGetDefaultAllocator();
774 } else if (NULL
== allocator
) {
775 allocator
= __CFGetDefaultAllocator();
778 #if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
779 if (allocator
->_base
._cfisa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
780 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
783 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
785 CFAssert1(0 == context
->version
, __kCFLogAssertion
, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__
);
786 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
787 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
791 context
->version
= 0;
792 context
->info
= allocator
->_context
.info
;
793 context
->retain
= __CFAllocatorGetRetainFunction(&allocator
->_context
);
794 context
->release
= __CFAllocatorGetReleaseFunction(&allocator
->_context
);
795 context
->copyDescription
= __CFAllocatorGetCopyDescriptionFunction(&allocator
->_context
);
796 context
->allocate
= __CFAllocatorGetAllocateFunction(&allocator
->_context
);
797 context
->reallocate
= __CFAllocatorGetReallocateFunction(&allocator
->_context
);
798 context
->deallocate
= __CFAllocatorGetDeallocateFunction(&allocator
->_context
);
799 context
->preferredSize
= __CFAllocatorGetPreferredSizeFunction(&allocator
->_context
);
802 __private_extern__
void *_CFAllocatorAllocateGC(CFAllocatorRef allocator
, CFIndex size
, CFOptionFlags hint
)
804 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
))
805 return auto_zone_allocate_object((auto_zone_t
*)kCFAllocatorSystemDefault
->_context
.info
, size
, CF_GET_GC_MEMORY_TYPE(hint
), false, false);
807 return CFAllocatorAllocate(allocator
, size
, hint
);
810 __private_extern__
void *_CFAllocatorReallocateGC(CFAllocatorRef allocator
, void *ptr
, CFIndex newsize
, CFOptionFlags hint
)
812 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) {
813 if (ptr
&& (newsize
== 0)) {
814 return NULL
; // equivalent to _CFAllocatorDeallocateGC.
817 return auto_zone_allocate_object((auto_zone_t
*)kCFAllocatorSystemDefault
->_context
.info
, newsize
, CF_GET_GC_MEMORY_TYPE(hint
), false, false); // eq. to _CFAllocator
820 // otherwise, auto_realloc() now preserves layout type and refCount.
821 return CFAllocatorReallocate(allocator
, ptr
, newsize
, hint
);
824 __private_extern__
void _CFAllocatorDeallocateGC(CFAllocatorRef allocator
, void *ptr
)
826 // when running GC, don't deallocate.
827 if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) CFAllocatorDeallocate(allocator
, ptr
);
830 // -------- -------- -------- -------- -------- -------- -------- --------
833 CFRange
__CFRangeMake(CFIndex loc
, CFIndex len
) {
835 range
.location
= loc
;
845 static struct __CFNull __kCFNull
= {
846 INIT_CFRUNTIME_BASE()
848 const CFNullRef kCFNull
= &__kCFNull
;
850 static CFStringRef
__CFNullCopyDescription(CFTypeRef cf
) {
851 return CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("<CFNull %p [%p]>"), cf
, CFGetAllocator(cf
));
854 static CFStringRef
__CFNullCopyFormattingDescription(CFTypeRef cf
, CFDictionaryRef formatOptions
) {
855 return (CFStringRef
)CFRetain(CFSTR("null"));
858 static void __CFNullDeallocate(CFTypeRef cf
) {
859 CFAssert(false, __kCFLogAssertion
, "Deallocated CFNull!");
862 static CFTypeID __kCFNullTypeID
= _kCFRuntimeNotATypeID
;
864 static const CFRuntimeClass __CFNullClass
= {
872 __CFNullCopyFormattingDescription
,
873 __CFNullCopyDescription
876 __private_extern__
void __CFNullInitialize(void) {
877 __kCFNullTypeID
= _CFRuntimeRegisterClass(&__CFNullClass
);
878 _CFRuntimeSetInstanceTypeID(&__kCFNull
, __kCFNullTypeID
);
879 __kCFNull
._base
._cfisa
= __CFISAForTypeID(__kCFNullTypeID
);
882 CFTypeID
CFNullGetTypeID(void) {
883 return __kCFNullTypeID
;
886 void CFCollection_non_gc_storage_error(void) { }
889 void _CFRuntimeSetCFMPresent(void *addr
) {
893 // void __HALT(void);
895 /* Keep this assembly at the bottom of the source file! */
898 extern void __HALT() {
901 #elif defined(__i386__) || defined(__x86_64__)
902 #if defined(_MSC_VER)