2 * Copyright (c) 2008 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@
24 Copyright 1998-2002, Apple, Inc. All rights reserved.
25 Responsibility: Christopher Kane
28 #include <CoreFoundation/CFBase.h>
29 #include "CFInternal.h"
31 #include <malloc/malloc.h>
32 extern size_t malloc_good_size(size_t size
);
33 #include <mach/mach.h>
38 #if defined(__CYGWIN32__) || defined (D__CYGWIN_)
39 #error CoreFoundation is currently built with the Microsoft C Runtime, which is incompatible with the Cygwin DLL. You must either use the -mno-cygwin flag, or complete a port of CF to the Cygwin environment.
42 // -------- -------- -------- -------- -------- -------- -------- --------
44 // CFAllocator structure must match struct _malloc_zone_t!
45 // The first two reserved fields in struct _malloc_zone_t are for us with CFRuntimeBase
46 struct __CFAllocator
{
48 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 */
49 void *(*malloc
)(struct _malloc_zone_t
*zone
, size_t size
);
50 void *(*calloc
)(struct _malloc_zone_t
*zone
, size_t num_items
, size_t size
); /* same as malloc, but block returned is set to zero */
51 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 */
52 void (*free
)(struct _malloc_zone_t
*zone
, void *ptr
);
53 void *(*realloc
)(struct _malloc_zone_t
*zone
, void *ptr
, size_t size
);
54 void (*destroy
)(struct _malloc_zone_t
*zone
); /* zone is destroyed and all memory reclaimed */
55 const char *zone_name
;
56 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) */
57 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 */
58 struct malloc_introspection_t
*introspect
;
60 CFAllocatorRef _allocator
;
61 CFAllocatorContext _context
;
64 CF_INLINE CFAllocatorRetainCallBack
__CFAllocatorGetRetainFunction(const CFAllocatorContext
*context
) {
65 CFAllocatorRetainCallBack retval
= NULL
;
66 retval
= context
->retain
;
70 CF_INLINE CFAllocatorReleaseCallBack
__CFAllocatorGetReleaseFunction(const CFAllocatorContext
*context
) {
71 CFAllocatorReleaseCallBack retval
= NULL
;
72 retval
= context
->release
;
76 CF_INLINE CFAllocatorCopyDescriptionCallBack
__CFAllocatorGetCopyDescriptionFunction(const CFAllocatorContext
*context
) {
77 CFAllocatorCopyDescriptionCallBack retval
= NULL
;
78 retval
= context
->copyDescription
;
82 CF_INLINE CFAllocatorAllocateCallBack
__CFAllocatorGetAllocateFunction(const CFAllocatorContext
*context
) {
83 CFAllocatorAllocateCallBack retval
= NULL
;
84 retval
= context
->allocate
;
88 CF_INLINE CFAllocatorReallocateCallBack
__CFAllocatorGetReallocateFunction(const CFAllocatorContext
*context
) {
89 CFAllocatorReallocateCallBack retval
= NULL
;
90 retval
= context
->reallocate
;
94 CF_INLINE CFAllocatorDeallocateCallBack
__CFAllocatorGetDeallocateFunction(const CFAllocatorContext
*context
) {
95 CFAllocatorDeallocateCallBack retval
= NULL
;
96 retval
= context
->deallocate
;
100 CF_INLINE CFAllocatorPreferredSizeCallBack
__CFAllocatorGetPreferredSizeFunction(const CFAllocatorContext
*context
) {
101 CFAllocatorPreferredSizeCallBack retval
= NULL
;
102 retval
= context
->preferredSize
;
106 #if DEPLOYMENT_TARGET_MACOSX
108 __private_extern__
void __CFAllocatorDeallocate(CFTypeRef cf
);
110 static kern_return_t
__CFAllocatorZoneIntrospectNoOp(void) {
114 static boolean_t
__CFAllocatorZoneIntrospectTrue(void) {
118 static size_t __CFAllocatorCustomSize(malloc_zone_t
*zone
, const void *ptr
) {
121 // The only way to implement this with a version 0 allocator would be
122 // for CFAllocator to keep track of all blocks allocated itself, which
123 // could be done, but would be bad for performance, so we don't do it.
124 // size_t (*size)(struct _malloc_zone_t *zone, const void *ptr);
125 /* returns the size of a block or 0 if not in this zone;
126 * must be fast, especially for negative answers */
129 static void *__CFAllocatorCustomMalloc(malloc_zone_t
*zone
, size_t size
) {
130 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
131 return CFAllocatorAllocate(allocator
, size
, 0);
134 static void *__CFAllocatorCustomCalloc(malloc_zone_t
*zone
, size_t num_items
, size_t size
) {
135 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
136 void *newptr
= CFAllocatorAllocate(allocator
, size
, 0);
137 if (newptr
) memset(newptr
, 0, size
);
141 static void *__CFAllocatorCustomValloc(malloc_zone_t
*zone
, size_t size
) {
142 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
143 void *newptr
= CFAllocatorAllocate(allocator
, size
+ vm_page_size
, 0);
144 newptr
= (void *)round_page((uintptr_t)newptr
);
148 static void __CFAllocatorCustomFree(malloc_zone_t
*zone
, void *ptr
) {
149 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
150 CFAllocatorDeallocate(allocator
, ptr
);
153 static void *__CFAllocatorCustomRealloc(malloc_zone_t
*zone
, void *ptr
, size_t size
) {
154 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
155 return CFAllocatorReallocate(allocator
, ptr
, size
, 0);
158 static void __CFAllocatorCustomDestroy(malloc_zone_t
*zone
) {
159 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
160 // !!! we do it, and caller of malloc_destroy_zone() assumes
161 // COMPLETE responsibility for the result; NO Apple library
162 // code should be modified as a result of discovering that
163 // some activity results in inconveniences to developers
164 // trying to use malloc_destroy_zone() with a CFAllocatorRef;
165 // that's just too bad for them.
166 __CFAllocatorDeallocate(allocator
);
169 static size_t __CFAllocatorCustomGoodSize(malloc_zone_t
*zone
, size_t size
) {
170 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
171 return CFAllocatorGetPreferredSizeForSize(allocator
, size
, 0);
174 static struct malloc_introspection_t __CFAllocatorZoneIntrospect
= {
175 (void *)__CFAllocatorZoneIntrospectNoOp
,
176 (void *)__CFAllocatorCustomGoodSize
,
177 (void *)__CFAllocatorZoneIntrospectTrue
,
178 (void *)__CFAllocatorZoneIntrospectNoOp
,
179 (void *)__CFAllocatorZoneIntrospectNoOp
,
180 (void *)__CFAllocatorZoneIntrospectNoOp
,
181 (void *)__CFAllocatorZoneIntrospectNoOp
,
182 (void *)__CFAllocatorZoneIntrospectNoOp
185 static size_t __CFAllocatorNullSize(malloc_zone_t
*zone
, const void *ptr
) {
189 static void * __CFAllocatorNullMalloc(malloc_zone_t
*zone
, size_t size
) {
193 static void * __CFAllocatorNullCalloc(malloc_zone_t
*zone
, size_t num_items
, size_t size
) {
197 static void * __CFAllocatorNullValloc(malloc_zone_t
*zone
, size_t size
) {
201 static void __CFAllocatorNullFree(malloc_zone_t
*zone
, void *ptr
) {
204 static void * __CFAllocatorNullRealloc(malloc_zone_t
*zone
, void *ptr
, size_t size
) {
208 static void __CFAllocatorNullDestroy(malloc_zone_t
*zone
) {
211 static size_t __CFAllocatorNullGoodSize(malloc_zone_t
*zone
, size_t size
) {
215 static struct malloc_introspection_t __CFAllocatorNullZoneIntrospect
= {
216 (void *)__CFAllocatorZoneIntrospectNoOp
,
217 (void *)__CFAllocatorNullGoodSize
,
218 (void *)__CFAllocatorZoneIntrospectTrue
,
219 (void *)__CFAllocatorZoneIntrospectNoOp
,
220 (void *)__CFAllocatorZoneIntrospectNoOp
,
221 (void *)__CFAllocatorZoneIntrospectNoOp
,
222 (void *)__CFAllocatorZoneIntrospectNoOp
,
223 (void *)__CFAllocatorZoneIntrospectNoOp
226 static void *__CFAllocatorSystemAllocate(CFIndex size
, CFOptionFlags hint
, void *info
) {
227 return malloc_zone_malloc(info
, size
);
230 static void *__CFAllocatorSystemReallocate(void *ptr
, CFIndex newsize
, CFOptionFlags hint
, void *info
) {
231 return malloc_zone_realloc(info
, ptr
, newsize
);
234 static void __CFAllocatorSystemDeallocate(void *ptr
, void *info
) {
236 size_t size
= malloc_size(ptr
);
237 if (size
) memset(ptr
, 0xCC, size
);
239 malloc_zone_free(info
, ptr
);
244 #if defined(__WIN32__) || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
245 static void *__CFAllocatorSystemAllocate(CFIndex size
, CFOptionFlags hint
, void *info
) {
249 static void *__CFAllocatorSystemReallocate(void *ptr
, CFIndex newsize
, CFOptionFlags hint
, void *info
) {
250 return realloc(ptr
, newsize
);
253 static void __CFAllocatorSystemDeallocate(void *ptr
, void *info
) {
258 static void *__CFAllocatorNullAllocate(CFIndex size
, CFOptionFlags hint
, void *info
) {
262 static void *__CFAllocatorNullReallocate(void *ptr
, CFIndex newsize
, CFOptionFlags hint
, void *info
) {
266 #if defined (__cplusplus)
267 static void * __CFAllocatorCPPMalloc(CFIndex allocSize
, CFOptionFlags hint
, void *info
)
269 return malloc(allocSize
);
271 static void * __CFAllocatorCPPReAlloc(void *ptr
, CFIndex newsize
, CFOptionFlags hint
, void *info
)
273 return realloc(ptr
, newsize
);
275 static void __CFAllocatorCPPFree(void *ptr
, void *info
)
282 static struct __CFAllocator __kCFAllocatorMalloc
= {
283 INIT_CFRUNTIME_BASE(),
284 #if DEPLOYMENT_TARGET_MACOSX
285 __CFAllocatorCustomSize
,
286 __CFAllocatorCustomMalloc
,
287 __CFAllocatorCustomCalloc
,
288 __CFAllocatorCustomValloc
,
289 __CFAllocatorCustomFree
,
290 __CFAllocatorCustomRealloc
,
291 __CFAllocatorNullDestroy
,
292 "kCFAllocatorMalloc",
295 &__CFAllocatorZoneIntrospect
,
299 // Using the malloc functions directly is a total cheat, but works (in C)
300 // because the function signatures match in their common prefix of arguments.
301 // This saves us one hop through an adaptor function.
302 #if !defined (__cplusplus)
303 {0, NULL
, NULL
, NULL
, NULL
, (void *)malloc
, (void *)realloc
, (void *)free
, NULL
}
305 {0, NULL
, NULL
, NULL
, NULL
, __CFAllocatorCPPMalloc
,__CFAllocatorCPPReAlloc
, __CFAllocatorCPPFree
, NULL
}
306 #endif // __cplusplus
309 static struct __CFAllocator __kCFAllocatorMallocZone
= {
310 INIT_CFRUNTIME_BASE(),
311 #if DEPLOYMENT_TARGET_MACOSX
312 __CFAllocatorCustomSize
,
313 __CFAllocatorCustomMalloc
,
314 __CFAllocatorCustomCalloc
,
315 __CFAllocatorCustomValloc
,
316 __CFAllocatorCustomFree
,
317 __CFAllocatorCustomRealloc
,
318 __CFAllocatorNullDestroy
,
319 "kCFAllocatorMallocZone",
322 &__CFAllocatorZoneIntrospect
,
326 {0, NULL
, NULL
, NULL
, NULL
, __CFAllocatorSystemAllocate
, __CFAllocatorSystemReallocate
, __CFAllocatorSystemDeallocate
, NULL
}
329 static struct __CFAllocator __kCFAllocatorSystemDefault
= {
330 INIT_CFRUNTIME_BASE(),
331 #if DEPLOYMENT_TARGET_MACOSX
332 __CFAllocatorCustomSize
,
333 __CFAllocatorCustomMalloc
,
334 __CFAllocatorCustomCalloc
,
335 __CFAllocatorCustomValloc
,
336 __CFAllocatorCustomFree
,
337 __CFAllocatorCustomRealloc
,
338 __CFAllocatorNullDestroy
,
339 "kCFAllocatorSystemDefault",
342 &__CFAllocatorZoneIntrospect
,
346 {0, NULL
, NULL
, NULL
, NULL
, __CFAllocatorSystemAllocate
, __CFAllocatorSystemReallocate
, __CFAllocatorSystemDeallocate
, NULL
}
349 static struct __CFAllocator __kCFAllocatorNull
= {
350 INIT_CFRUNTIME_BASE(),
351 #if DEPLOYMENT_TARGET_MACOSX
352 __CFAllocatorNullSize
,
353 __CFAllocatorNullMalloc
,
354 __CFAllocatorNullCalloc
,
355 __CFAllocatorNullValloc
,
356 __CFAllocatorNullFree
,
357 __CFAllocatorNullRealloc
,
358 __CFAllocatorNullDestroy
,
362 &__CFAllocatorNullZoneIntrospect
,
366 {0, NULL
, NULL
, NULL
, NULL
, __CFAllocatorNullAllocate
, __CFAllocatorNullReallocate
, NULL
, NULL
}
369 const CFAllocatorRef kCFAllocatorDefault
= NULL
;
370 const CFAllocatorRef kCFAllocatorSystemDefault
= &__kCFAllocatorSystemDefault
;
371 const CFAllocatorRef kCFAllocatorMalloc
= &__kCFAllocatorMalloc
;
372 const CFAllocatorRef kCFAllocatorMallocZone
= &__kCFAllocatorMallocZone
;
373 const CFAllocatorRef kCFAllocatorNull
= &__kCFAllocatorNull
;
374 const CFAllocatorRef kCFAllocatorUseContext
= (CFAllocatorRef
)0x0257;
376 static CFStringRef
__CFAllocatorCopyDescription(CFTypeRef cf
) {
377 CFAllocatorRef self
= (CFAllocatorRef
)cf
;
378 CFAllocatorRef allocator
= (kCFAllocatorUseContext
== self
->_allocator
) ? self
: self
->_allocator
;
379 return CFStringCreateWithFormat(allocator
, NULL
, CFSTR("<CFAllocator %p [%p]>{info = %p}"), cf
, allocator
, self
->_context
.info
);
380 // CF: should use copyDescription function here to describe info field
381 // remember to release value returned from copydescr function when this happens
384 __private_extern__ CFAllocatorRef
__CFAllocatorGetAllocator(CFTypeRef cf
) {
385 CFAllocatorRef allocator
= (CFAllocatorRef
)cf
;
386 return (kCFAllocatorUseContext
== allocator
->_allocator
) ? allocator
: allocator
->_allocator
;
389 __private_extern__
void __CFAllocatorDeallocate(CFTypeRef cf
) {
390 CFAllocatorRef self
= (CFAllocatorRef
)cf
;
391 CFAllocatorRef allocator
= self
->_allocator
;
392 CFAllocatorReleaseCallBack releaseFunc
= __CFAllocatorGetReleaseFunction(&self
->_context
);
393 if (kCFAllocatorUseContext
== allocator
) {
394 /* Rather a chicken and egg problem here, so we do things
395 in the reverse order from what was done at create time. */
396 CFAllocatorDeallocateCallBack deallocateFunc
= __CFAllocatorGetDeallocateFunction(&self
->_context
);
397 void *info
= self
->_context
.info
;
398 if (NULL
!= deallocateFunc
) {
399 INVOKE_CALLBACK2(deallocateFunc
, (void *)self
, info
);
401 if (NULL
!= releaseFunc
) {
402 INVOKE_CALLBACK1(releaseFunc
, info
);
405 if (NULL
!= releaseFunc
) {
406 INVOKE_CALLBACK1(releaseFunc
, self
->_context
.info
);
408 _CFAllocatorDeallocateGC(allocator
, (void *)self
);
412 static CFTypeID __kCFAllocatorTypeID
= _kCFRuntimeNotATypeID
;
414 static const CFRuntimeClass __CFAllocatorClass
= {
419 __CFAllocatorDeallocate
,
423 __CFAllocatorCopyDescription
426 __private_extern__
void __CFAllocatorInitialize(void) {
427 __kCFAllocatorTypeID
= _CFRuntimeRegisterClass(&__CFAllocatorClass
);
429 _CFRuntimeSetInstanceTypeID(&__kCFAllocatorSystemDefault
, __kCFAllocatorTypeID
);
430 __kCFAllocatorSystemDefault
._base
._cfisa
= __CFISAForTypeID(__kCFAllocatorTypeID
);
431 #if DEPLOYMENT_TARGET_MACOSX
432 __kCFAllocatorSystemDefault
._context
.info
= (CF_USING_COLLECTABLE_MEMORY
? __CFCollectableZone
: malloc_default_zone());
433 memset(malloc_default_zone(), 0, 2 * sizeof(void *));
435 __kCFAllocatorSystemDefault
._allocator
= kCFAllocatorSystemDefault
;
437 _CFRuntimeSetInstanceTypeID(&__kCFAllocatorMalloc
, __kCFAllocatorTypeID
);
438 __kCFAllocatorMalloc
._base
._cfisa
= __CFISAForTypeID(__kCFAllocatorTypeID
);
439 __kCFAllocatorMalloc
._allocator
= kCFAllocatorSystemDefault
;
441 #if DEPLOYMENT_TARGET_MACOSX
442 _CFRuntimeSetInstanceTypeID(&__kCFAllocatorMallocZone
, __kCFAllocatorTypeID
);
443 __kCFAllocatorMallocZone
._base
._cfisa
= __CFISAForTypeID(__kCFAllocatorTypeID
);
444 __kCFAllocatorMallocZone
._allocator
= kCFAllocatorSystemDefault
;
445 __kCFAllocatorMallocZone
._context
.info
= malloc_default_zone();
448 _CFRuntimeSetInstanceTypeID(&__kCFAllocatorNull
, __kCFAllocatorTypeID
);
449 __kCFAllocatorNull
._base
._cfisa
= __CFISAForTypeID(__kCFAllocatorTypeID
);
450 __kCFAllocatorNull
._allocator
= kCFAllocatorSystemDefault
;
454 CFTypeID
CFAllocatorGetTypeID(void) {
455 return __kCFAllocatorTypeID
;
458 CFAllocatorRef
CFAllocatorGetDefault(void) {
459 CFAllocatorRef allocator
= (CFAllocatorRef
)__CFGetThreadSpecificData_inline()->_allocator
;
460 if (NULL
== allocator
) {
461 allocator
= kCFAllocatorSystemDefault
;
466 void CFAllocatorSetDefault(CFAllocatorRef allocator
) {
467 CFAllocatorRef current
= (CFAllocatorRef
)__CFGetThreadSpecificData_inline()->_allocator
;
469 if (NULL
!= allocator
) {
470 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
473 #if DEPLOYMENT_TARGET_MACOSX
474 if (allocator
&& allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
475 return; // require allocator to this function to be an allocator
478 if (NULL
!= allocator
&& allocator
!= current
) {
479 if (current
) CFRelease(current
);
481 // We retain an extra time so that anything set as the default
482 // allocator never goes away.
484 __CFGetThreadSpecificData_inline()->_allocator
= (void *)allocator
;
488 static CFAllocatorRef
__CFAllocatorCreate(CFAllocatorRef allocator
, CFAllocatorContext
*context
) {
489 struct __CFAllocator
*memory
= NULL
;
490 CFAllocatorRetainCallBack retainFunc
;
491 CFAllocatorAllocateCallBack allocateFunc
;
493 #if DEPLOYMENT_TARGET_MACOSX
494 if (allocator
&& kCFAllocatorUseContext
!= allocator
&& allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
495 return NULL
; // require allocator to this function to be an allocator
498 retainFunc
= context
->retain
;
499 FAULT_CALLBACK((void **)&retainFunc
);
500 allocateFunc
= context
->allocate
;
501 FAULT_CALLBACK((void **)&allocateFunc
);
502 if (NULL
!= retainFunc
) {
503 retainedInfo
= (void *)INVOKE_CALLBACK1(retainFunc
, context
->info
);
505 retainedInfo
= context
->info
;
507 // We don't use _CFRuntimeCreateInstance()
508 if (kCFAllocatorUseContext
== allocator
) {
511 memory
= (struct __CFAllocator
*)INVOKE_CALLBACK3(allocateFunc
, sizeof(struct __CFAllocator
), 0, retainedInfo
);
513 if (NULL
== memory
) {
517 allocator
= (NULL
== allocator
) ? __CFGetDefaultAllocator() : allocator
;
518 memory
= (struct __CFAllocator
*)CFAllocatorAllocate(allocator
, sizeof(struct __CFAllocator
), __kCFAllocatorGCObjectMemory
);
519 if (__CFOASafe
) __CFSetLastAllocationEventName(memory
, "CFAllocator");
520 if (NULL
== memory
) {
524 memory
->_base
._cfisa
= 0;
526 memory
->_base
._rc
= 1;
528 memory
->_base
._cfinfo
[CF_RC_BITS
] = 1;
530 memory
->_base
._cfinfo
[CF_INFO_BITS
] = 0;
531 _CFRuntimeSetInstanceTypeID(memory
, __kCFAllocatorTypeID
);
532 memory
->_base
._cfisa
= __CFISAForTypeID(__kCFAllocatorTypeID
);
533 #if DEPLOYMENT_TARGET_MACOSX
534 memory
->size
= __CFAllocatorCustomSize
;
535 memory
->malloc
= __CFAllocatorCustomMalloc
;
536 memory
->calloc
= __CFAllocatorCustomCalloc
;
537 memory
->valloc
= __CFAllocatorCustomValloc
;
538 memory
->free
= __CFAllocatorCustomFree
;
539 memory
->realloc
= __CFAllocatorCustomRealloc
;
540 memory
->destroy
= __CFAllocatorCustomDestroy
;
541 memory
->zone_name
= "Custom CFAllocator";
542 memory
->batch_malloc
= NULL
;
543 memory
->batch_free
= NULL
;
544 memory
->introspect
= &__CFAllocatorZoneIntrospect
;
545 memory
->reserved5
= NULL
;
547 memory
->_allocator
= allocator
;
548 memory
->_context
.version
= context
->version
;
549 memory
->_context
.info
= retainedInfo
;
550 memory
->_context
.retain
= retainFunc
;
551 memory
->_context
.release
= context
->release
;
552 FAULT_CALLBACK((void **)&(memory
->_context
.release
));
553 memory
->_context
.copyDescription
= context
->copyDescription
;
554 FAULT_CALLBACK((void **)&(memory
->_context
.copyDescription
));
555 memory
->_context
.allocate
= allocateFunc
;
556 memory
->_context
.reallocate
= context
->reallocate
;
557 FAULT_CALLBACK((void **)&(memory
->_context
.reallocate
));
558 memory
->_context
.deallocate
= context
->deallocate
;
559 FAULT_CALLBACK((void **)&(memory
->_context
.deallocate
));
560 memory
->_context
.preferredSize
= context
->preferredSize
;
561 FAULT_CALLBACK((void **)&(memory
->_context
.preferredSize
));
566 CFAllocatorRef
CFAllocatorCreate(CFAllocatorRef allocator
, CFAllocatorContext
*context
) {
567 CFAssert1(!CF_USING_COLLECTABLE_MEMORY
, __kCFLogAssertion
, "%s(): Shouldn't be called when GC is enabled!", __PRETTY_FUNCTION__
);
569 if (CF_USING_COLLECTABLE_MEMORY
)
572 return __CFAllocatorCreate(allocator
, context
);
575 CFAllocatorRef
_CFAllocatorCreateGC(CFAllocatorRef allocator
, CFAllocatorContext
*context
) {
576 return __CFAllocatorCreate(allocator
, context
);
579 void *CFAllocatorAllocate(CFAllocatorRef allocator
, CFIndex size
, CFOptionFlags hint
) {
580 CFAllocatorAllocateCallBack allocateFunc
;
582 allocator
= (NULL
== allocator
) ? __CFGetDefaultAllocator() : allocator
;
583 #if (DEPLOYMENT_TARGET_MACOSX) && defined(DEBUG)
584 if (allocator
->_base
._cfisa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
585 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
588 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
590 if (0 == size
) return NULL
;
591 #if DEPLOYMENT_TARGET_MACOSX
592 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
593 return malloc_zone_malloc((malloc_zone_t
*)allocator
, size
);
596 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) {
597 newptr
= auto_zone_allocate_object((auto_zone_t
*)allocator
->_context
.info
, size
, CF_GET_GC_MEMORY_TYPE(hint
), true, false);
600 allocateFunc
= __CFAllocatorGetAllocateFunction(&allocator
->_context
);
602 newptr
= (void *)INVOKE_CALLBACK3(allocateFunc
, size
, hint
, allocator
->_context
.info
);
608 void *CFAllocatorReallocate(CFAllocatorRef allocator
, void *ptr
, CFIndex newsize
, CFOptionFlags hint
) {
609 CFAllocatorAllocateCallBack allocateFunc
;
610 CFAllocatorReallocateCallBack reallocateFunc
;
611 CFAllocatorDeallocateCallBack deallocateFunc
;
613 allocator
= (NULL
== allocator
) ? __CFGetDefaultAllocator() : allocator
;
614 #if (DEPLOYMENT_TARGET_MACOSX) && defined(DEBUG)
615 if (allocator
->_base
._cfisa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
616 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
619 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
621 if (NULL
== ptr
&& 0 < newsize
) {
622 #if DEPLOYMENT_TARGET_MACOSX
623 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
624 return malloc_zone_malloc((malloc_zone_t
*)allocator
, newsize
);
628 allocateFunc
= __CFAllocatorGetAllocateFunction(&allocator
->_context
);
630 newptr
= (void *)INVOKE_CALLBACK3(allocateFunc
, newsize
, hint
, allocator
->_context
.info
);
634 if (NULL
!= ptr
&& 0 == newsize
) {
635 #if DEPLOYMENT_TARGET_MACOSX
636 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
638 size_t size
= malloc_size(ptr
);
639 if (size
) memset(ptr
, 0xCC, size
);
641 malloc_zone_free((malloc_zone_t
*)allocator
, ptr
);
645 deallocateFunc
= __CFAllocatorGetDeallocateFunction(&allocator
->_context
);
646 if (NULL
!= deallocateFunc
) {
647 INVOKE_CALLBACK2(deallocateFunc
, ptr
, allocator
->_context
.info
);
651 if (NULL
== ptr
&& 0 == newsize
) return NULL
;
652 #if DEPLOYMENT_TARGET_MACOSX
653 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
654 return malloc_zone_realloc((malloc_zone_t
*)allocator
, ptr
, newsize
);
657 reallocateFunc
= __CFAllocatorGetReallocateFunction(&allocator
->_context
);
658 if (NULL
== reallocateFunc
) return NULL
;
659 newptr
= (void *)INVOKE_CALLBACK4(reallocateFunc
, ptr
, newsize
, hint
, allocator
->_context
.info
);
663 void CFAllocatorDeallocate(CFAllocatorRef allocator
, void *ptr
) {
664 CFAllocatorDeallocateCallBack deallocateFunc
;
665 allocator
= (NULL
== allocator
) ? __CFGetDefaultAllocator() : allocator
;
666 #if (DEPLOYMENT_TARGET_MACOSX) && defined(DEBUG)
667 if (allocator
->_base
._cfisa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
668 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
671 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
673 #if DEPLOYMENT_TARGET_MACOSX
674 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
676 size_t size
= malloc_size(ptr
);
677 if (size
) memset(ptr
, 0xCC, size
);
679 return malloc_zone_free((malloc_zone_t
*)allocator
, ptr
);
682 deallocateFunc
= __CFAllocatorGetDeallocateFunction(&allocator
->_context
);
683 if (NULL
!= ptr
&& NULL
!= deallocateFunc
) {
684 INVOKE_CALLBACK2(deallocateFunc
, ptr
, allocator
->_context
.info
);
688 CFIndex
CFAllocatorGetPreferredSizeForSize(CFAllocatorRef allocator
, CFIndex size
, CFOptionFlags hint
) {
689 CFAllocatorPreferredSizeCallBack prefFunc
;
691 allocator
= (NULL
== allocator
) ? __CFGetDefaultAllocator() : allocator
;
692 #if (DEPLOYMENT_TARGET_MACOSX) && defined(DEBUG)
693 if (allocator
->_base
._cfisa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
694 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
697 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
699 #if DEPLOYMENT_TARGET_MACOSX
700 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
701 return malloc_good_size(size
);
704 prefFunc
= __CFAllocatorGetPreferredSizeFunction(&allocator
->_context
);
705 if (0 < size
&& NULL
!= prefFunc
) {
706 newsize
= (CFIndex
)(INVOKE_CALLBACK3(prefFunc
, size
, hint
, allocator
->_context
.info
));
708 if (newsize
< size
) newsize
= size
;
712 void CFAllocatorGetContext(CFAllocatorRef allocator
, CFAllocatorContext
*context
) {
713 allocator
= (NULL
== allocator
) ? __CFGetDefaultAllocator() : allocator
;
714 #if (DEPLOYMENT_TARGET_MACOSX) && defined(DEBUG)
715 if (allocator
->_base
._cfisa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
716 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
719 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
721 CFAssert1(0 == context
->version
, __kCFLogAssertion
, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__
);
722 #if DEPLOYMENT_TARGET_MACOSX
723 if (allocator
->_base
._cfisa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
727 context
->version
= 0;
728 context
->info
= allocator
->_context
.info
;
729 context
->retain
= __CFAllocatorGetRetainFunction(&allocator
->_context
);
730 context
->release
= __CFAllocatorGetReleaseFunction(&allocator
->_context
);
731 context
->copyDescription
= __CFAllocatorGetCopyDescriptionFunction(&allocator
->_context
);
732 context
->allocate
= __CFAllocatorGetAllocateFunction(&allocator
->_context
);
733 context
->reallocate
= __CFAllocatorGetReallocateFunction(&allocator
->_context
);
734 context
->deallocate
= __CFAllocatorGetDeallocateFunction(&allocator
->_context
);
735 context
->preferredSize
= __CFAllocatorGetPreferredSizeFunction(&allocator
->_context
);
736 #if (DEPLOYMENT_TARGET_MACOSX) && defined(__ppc__)
737 context
->retain
= (void *)((uintptr_t)context
->retain
& ~0x3);
738 context
->release
= (void *)((uintptr_t)context
->release
& ~0x3);
739 context
->copyDescription
= (void *)((uintptr_t)context
->copyDescription
& ~0x3);
740 context
->allocate
= (void *)((uintptr_t)context
->allocate
& ~0x3);
741 context
->reallocate
= (void *)((uintptr_t)context
->reallocate
& ~0x3);
742 context
->deallocate
= (void *)((uintptr_t)context
->deallocate
& ~0x3);
743 context
->preferredSize
= (void *)((uintptr_t)context
->preferredSize
& ~0x3);
747 void *_CFAllocatorAllocateGC(CFAllocatorRef allocator
, CFIndex size
, CFOptionFlags hint
)
749 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
))
750 return auto_zone_allocate_object((auto_zone_t
*)kCFAllocatorSystemDefault
->_context
.info
, size
, CF_GET_GC_MEMORY_TYPE(hint
), false, false);
752 return CFAllocatorAllocate(allocator
, size
, hint
);
755 void *_CFAllocatorReallocateGC(CFAllocatorRef allocator
, void *ptr
, CFIndex newsize
, CFOptionFlags hint
)
757 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) {
758 if (ptr
&& (newsize
== 0)) {
759 return NULL
; // equivalent to _CFAllocatorDeallocateGC.
762 return auto_zone_allocate_object((auto_zone_t
*)kCFAllocatorSystemDefault
->_context
.info
, newsize
, CF_GET_GC_MEMORY_TYPE(hint
), false, false); // eq. to _CFAllocator
765 // otherwise, auto_realloc() now preserves layout type and refCount.
766 return CFAllocatorReallocate(allocator
, ptr
, newsize
, hint
);
769 void _CFAllocatorDeallocateGC(CFAllocatorRef allocator
, void *ptr
)
771 // when running GC, don't deallocate.
772 if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) CFAllocatorDeallocate(allocator
, ptr
);
775 // -------- -------- -------- -------- -------- -------- -------- --------
777 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
778 __private_extern__ pthread_key_t __CFTSDKey
= (pthread_key_t
)NULL
;
781 __private_extern__ DWORD __CFTSDKey
= 0xFFFFFFFF;
784 extern void _CFRunLoop1(void);
786 // Called for each thread as it exits
787 __private_extern__
void __CFFinalizeThreadData(void *arg
) {
788 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
789 __CFThreadSpecificData
*tsd
= (__CFThreadSpecificData
*)arg
;
790 #elif defined(__WIN32__)
791 __CFThreadSpecificData
*tsd
= (__CFThreadSpecificData
*)TlsGetValue(__CFTSDKey
);
792 TlsSetValue(__CFTSDKey
, NULL
);
794 if (NULL
== tsd
) return;
795 if (tsd
->_allocator
) CFRelease(tsd
->_allocator
);
796 #if DEPLOYMENT_TARGET_MACOSX
801 if (tsd
->_messageHook
) UnhookWindowsHookEx(tsd
->_messageHook
);
805 CFAllocatorDeallocate(kCFAllocatorSystemDefault
, tsd
);
808 __private_extern__ __CFThreadSpecificData
*__CFGetThreadSpecificData(void) {
809 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
810 __CFThreadSpecificData
*data
;
811 data
= pthread_getspecific(__CFTSDKey
);
815 data
= CFAllocatorAllocate(kCFAllocatorSystemDefault
, sizeof(__CFThreadSpecificData
), 0);
816 if (__CFOASafe
) __CFSetLastAllocationEventName(data
, "CFUtilities (thread-data)");
817 memset(data
, 0, sizeof(__CFThreadSpecificData
));
818 pthread_setspecific(__CFTSDKey
, data
);
820 #elif defined(__WIN32__)
821 __CFThreadSpecificData
*data
;
822 data
= (__CFThreadSpecificData
*)TlsGetValue(__CFTSDKey
);
826 data
= (__CFThreadSpecificData
*)CFAllocatorAllocate(kCFAllocatorSystemDefault
, sizeof(__CFThreadSpecificData
), 0);
827 if (__CFOASafe
) __CFSetLastAllocationEventName(data
, "CFUtilities (thread-data)");
828 memset(data
, 0, sizeof(__CFThreadSpecificData
));
829 TlsSetValue(__CFTSDKey
, data
);
834 __private_extern__
void __CFBaseInitialize(void) {
835 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
836 pthread_key_create(&__CFTSDKey
, __CFFinalizeThreadData
);
839 __CFTSDKey
= TlsAlloc();
844 __private_extern__
void __CFBaseCleanup(void) {
850 static CFBadErrorCallBack __CFOutOfMemoryCallBack
= NULL
;
852 CFBadErrorCallBack
_CFGetOutOfMemoryErrorCallBack(void) {
853 return __CFOutOfMemoryCallBack
;
856 void _CFSetOutOfMemoryErrorCallBack(CFBadErrorCallBack callBack
) {
857 __CFOutOfMemoryCallBack
= callBack
;
861 CFRange
__CFRangeMake(CFIndex loc
, CFIndex len
) {
863 range
.location
= loc
;
873 static struct __CFNull __kCFNull
= {
874 INIT_CFRUNTIME_BASE()
876 const CFNullRef kCFNull
= &__kCFNull
;
878 static CFStringRef
__CFNullCopyDescription(CFTypeRef cf
) {
879 return CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("<CFNull %p [%p]>"), cf
, CFGetAllocator(cf
));
882 static CFStringRef
__CFNullCopyFormattingDescription(CFTypeRef cf
, CFDictionaryRef formatOptions
) {
883 return (CFStringRef
)CFRetain(CFSTR("null"));
886 static void __CFNullDeallocate(CFTypeRef cf
) {
887 CFAssert(false, __kCFLogAssertion
, "Deallocated CFNull!");
890 static CFTypeID __kCFNullTypeID
= _kCFRuntimeNotATypeID
;
892 static const CFRuntimeClass __CFNullClass
= {
900 __CFNullCopyFormattingDescription
,
901 __CFNullCopyDescription
904 __private_extern__
void __CFNullInitialize(void) {
905 __kCFNullTypeID
= _CFRuntimeRegisterClass(&__CFNullClass
);
906 _CFRuntimeSetInstanceTypeID(&__kCFNull
, __kCFNullTypeID
);
907 __kCFNull
._base
._cfisa
= __CFISAForTypeID(__kCFNullTypeID
);
910 CFTypeID
CFNullGetTypeID(void) {
911 return __kCFNullTypeID
;
914 void CFCollection_non_gc_storage_error(void) { }
917 static int hasCFM
= 0;
919 void _CFRuntimeSetCFMPresent(void *addr
) {
923 #if (DEPLOYMENT_TARGET_MACOSX) && defined(__ppc__)
925 /* See comments below */
926 __private_extern__
void __CF_FAULT_CALLBACK(void **ptr
) {
927 uintptr_t p
= (uintptr_t)*ptr
;
928 if ((0 == p
) || (p
& 0x1)) return;
929 if (0 == hasCFM
|| (0x90000000 <= p
&& p
< 0xA0000000)) {
930 *ptr
= (void *)(p
| 0x1);
932 static CFMutableDictionaryRef cache
= NULL
;
933 static CFSpinLock_t lock
= CFSpinLockInit
;
934 uintptr_t known
= ~0;
936 if (!cache
|| !CFDictionaryGetValueIfPresent(cache
, (const void *)p
, (const void **)&known
)) {
938 cache
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, NULL
, NULL
);
941 known
= dladdr((void *)p
, &info
);
942 CFDictionarySetValue(cache
, (const void *)p
, (const void *)known
);
944 __CFSpinUnlock(&lock
);
945 *ptr
= (void *)(p
| (known
? 0x1 : 0x3));
950 Jump to callback function. r2 is not saved and restored
951 in the jump-to-CFM case, since we assume that dyld code
952 never uses that register and that CF is dyld.
954 There are three states for (ptr & 0x3):
955 0b00: check not yet done (or not going to be done, and is a dyld func ptr)
956 0b01: check done, dyld function pointer
957 0b11: check done, CFM tvector pointer
958 (but a NULL callback just stays NULL)
960 There may be up to 5 word-sized arguments. Floating point
961 arguments can be done, but count as two word arguments.
962 Return value can be integral or real.
965 /* Keep this assembly at the bottom of the source file! */
970 ".private_extern ___CF_INVOKE_CALLBACK\n"
971 "___CF_INVOKE_CALLBACK:\n"
972 "rlwinm r12,r3,0,0,29\n"
982 "Lcall: mtspr ctr,r12\n"
988 // void __HALT(void);
990 #if defined(__ppc__) || defined(__ppc64__)
994 #if DEPLOYMENT_TARGET_MACOSX
995 ".private_extern ___HALT\n"
1004 #if defined(__i386__) || defined(__x86_64__)
1005 #if defined(_MSC_VER)
1013 #if DEPLOYMENT_TARGET_MACOSX
1014 ".private_extern ___HALT\n"