2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 Copyright 1998-2002, Apple, Inc. All rights reserved.
27 Responsibility: Christopher Kane
30 #include <CoreFoundation/CFBase.h>
31 #include "CFInternal.h"
32 #if defined(__MACH__) || defined(__LINUX__) || defined(__FREEBSD__)
37 #if defined(__WIN32__)
41 #include <mach-o/dyld.h>
42 #include <malloc/malloc.h>
43 #include <mach/mach.h>
48 extern size_t malloc_good_size(size_t size
);
50 // -------- -------- -------- -------- -------- -------- -------- --------
53 // CFAllocator structure must match struct _malloc_zone_t!
54 // The first two reserved fields in struct _malloc_zone_t are for us with CFRuntimeBase
56 struct __CFAllocator
{
59 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 */
60 void *(*malloc
)(struct _malloc_zone_t
*zone
, size_t size
);
61 void *(*calloc
)(struct _malloc_zone_t
*zone
, size_t num_items
, size_t size
); /* same as malloc, but block returned is set to zero */
62 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 */
63 void (*free
)(struct _malloc_zone_t
*zone
, void *ptr
);
64 void *(*realloc
)(struct _malloc_zone_t
*zone
, void *ptr
, size_t size
);
65 void (*destroy
)(struct _malloc_zone_t
*zone
); /* zone is destroyed and all memory reclaimed */
66 const char *zone_name
;
67 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) */
68 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 */
69 struct malloc_introspection_t
*introspect
;
72 CFAllocatorRef _allocator
;
73 CFAllocatorContext _context
;
76 CF_INLINE CFAllocatorRetainCallBack
__CFAllocatorGetRetainFunction(const CFAllocatorContext
*context
) {
77 CFAllocatorRetainCallBack retval
= NULL
;
78 retval
= context
->retain
;
82 CF_INLINE CFAllocatorReleaseCallBack
__CFAllocatorGetReleaseFunction(const CFAllocatorContext
*context
) {
83 CFAllocatorReleaseCallBack retval
= NULL
;
84 retval
= context
->release
;
88 CF_INLINE CFAllocatorCopyDescriptionCallBack
__CFAllocatorGetCopyDescriptionFunction(const CFAllocatorContext
*context
) {
89 CFAllocatorCopyDescriptionCallBack retval
= NULL
;
90 retval
= context
->copyDescription
;
94 CF_INLINE CFAllocatorAllocateCallBack
__CFAllocatorGetAllocateFunction(const CFAllocatorContext
*context
) {
95 CFAllocatorAllocateCallBack retval
= NULL
;
96 retval
= context
->allocate
;
100 CF_INLINE CFAllocatorReallocateCallBack
__CFAllocatorGetReallocateFunction(const CFAllocatorContext
*context
) {
101 CFAllocatorReallocateCallBack retval
= NULL
;
102 retval
= context
->reallocate
;
106 CF_INLINE CFAllocatorDeallocateCallBack
__CFAllocatorGetDeallocateFunction(const CFAllocatorContext
*context
) {
107 CFAllocatorDeallocateCallBack retval
= NULL
;
108 retval
= context
->deallocate
;
112 CF_INLINE CFAllocatorPreferredSizeCallBack
__CFAllocatorGetPreferredSizeFunction(const CFAllocatorContext
*context
) {
113 CFAllocatorPreferredSizeCallBack retval
= NULL
;
114 retval
= context
->preferredSize
;
118 #if defined(__MACH__)
120 __private_extern__
void __CFAllocatorDeallocate(CFTypeRef cf
);
122 static kern_return_t
__CFAllocatorZoneIntrospectNoOp(void) {
126 static boolean_t
__CFAllocatorZoneIntrospectTrue(void) {
130 static size_t __CFAllocatorCustomSize(malloc_zone_t
*zone
, const void *ptr
) {
133 // The only way to implement this with a version 0 allocator would be
134 // for CFAllocator to keep track of all blocks allocated itself, which
135 // could be done, but would be bad for performance, so we don't do it.
136 // size_t (*size)(struct _malloc_zone_t *zone, const void *ptr);
137 /* returns the size of a block or 0 if not in this zone;
138 * must be fast, especially for negative answers */
141 static void *__CFAllocatorCustomMalloc(malloc_zone_t
*zone
, size_t size
) {
142 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
143 return CFAllocatorAllocate(allocator
, size
, 0);
146 static void *__CFAllocatorCustomCalloc(malloc_zone_t
*zone
, size_t num_items
, size_t size
) {
147 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
148 void *newptr
= CFAllocatorAllocate(allocator
, size
, 0);
149 if (newptr
) memset(newptr
, 0, size
);
153 static void *__CFAllocatorCustomValloc(malloc_zone_t
*zone
, size_t size
) {
154 CFAllocatorRef allocator
= (CFAllocatorRef
)zone
;
155 void *newptr
= CFAllocatorAllocate(allocator
, size
+ vm_page_size
, 0);
156 newptr
= (void *)round_page((unsigned)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
) {
247 malloc_zone_free(info
, ptr
);
252 #if defined(__WIN32__) || defined(__LINUX__) || defined(__FREEBSD__)
253 static void *__CFAllocatorSystemAllocate(CFIndex size
, CFOptionFlags hint
, void *info
) {
257 static void *__CFAllocatorSystemReallocate(void *ptr
, CFIndex newsize
, CFOptionFlags hint
, void *info
) {
258 return realloc(ptr
, newsize
);
261 static void __CFAllocatorSystemDeallocate(void *ptr
, void *info
) {
266 static void *__CFAllocatorNullAllocate(CFIndex size
, CFOptionFlags hint
, void *info
) {
270 static void *__CFAllocatorNullReallocate(void *ptr
, CFIndex newsize
, CFOptionFlags hint
, void *info
) {
274 static struct __CFAllocator __kCFAllocatorMalloc
= {
276 #if defined(__MACH__)
277 __CFAllocatorCustomSize
,
278 __CFAllocatorCustomMalloc
,
279 __CFAllocatorCustomCalloc
,
280 __CFAllocatorCustomValloc
,
281 __CFAllocatorCustomFree
,
282 __CFAllocatorCustomRealloc
,
283 __CFAllocatorNullDestroy
,
284 "kCFAllocatorMalloc",
287 &__CFAllocatorZoneIntrospect
,
291 // Using the malloc functions directly is a total cheat, but works (in C)
292 // because the function signatures match in their common prefix of arguments.
293 // This saves us one hop through an adaptor function.
294 {0, NULL
, NULL
, NULL
, NULL
, (void *)malloc
, (void *)realloc
, (void *)free
, NULL
}
297 static struct __CFAllocator __kCFAllocatorSystemDefault
= {
299 #if defined(__MACH__)
300 __CFAllocatorCustomSize
,
301 __CFAllocatorCustomMalloc
,
302 __CFAllocatorCustomCalloc
,
303 __CFAllocatorCustomValloc
,
304 __CFAllocatorCustomFree
,
305 __CFAllocatorCustomRealloc
,
306 __CFAllocatorNullDestroy
,
307 "kCFAllocatorSystemDefault",
310 &__CFAllocatorZoneIntrospect
,
314 {0, NULL
, NULL
, NULL
, NULL
, __CFAllocatorSystemAllocate
, __CFAllocatorSystemReallocate
, __CFAllocatorSystemDeallocate
, NULL
}
317 static struct __CFAllocator __kCFAllocatorNull
= {
319 #if defined(__MACH__)
320 __CFAllocatorNullSize
,
321 __CFAllocatorNullMalloc
,
322 __CFAllocatorNullCalloc
,
323 __CFAllocatorNullValloc
,
324 __CFAllocatorNullFree
,
325 __CFAllocatorNullRealloc
,
326 __CFAllocatorNullDestroy
,
330 &__CFAllocatorNullZoneIntrospect
,
334 {0, NULL
, NULL
, NULL
, NULL
, __CFAllocatorNullAllocate
, __CFAllocatorNullReallocate
, NULL
, NULL
}
337 const CFAllocatorRef kCFAllocatorDefault
= NULL
;
338 const CFAllocatorRef kCFAllocatorSystemDefault
= &__kCFAllocatorSystemDefault
;
339 const CFAllocatorRef kCFAllocatorMalloc
= &__kCFAllocatorMalloc
;
340 const CFAllocatorRef kCFAllocatorNull
= &__kCFAllocatorNull
;
341 const CFAllocatorRef kCFAllocatorUseContext
= (CFAllocatorRef
)0x0227;
343 static CFStringRef
__CFAllocatorCopyDescription(CFTypeRef cf
) {
344 CFAllocatorRef self
= cf
;
345 CFAllocatorRef allocator
= (kCFAllocatorUseContext
== self
->_allocator
) ? self
: self
->_allocator
;
346 return CFStringCreateWithFormat(allocator
, NULL
, CFSTR("<CFAllocator 0x%x [0x%x]>{info = 0x%x}"), (UInt32
)cf
, (UInt32
)allocator
, self
->_context
.info
);
347 // CF: should use copyDescription function here to describe info field
348 // remember to release value returned from copydescr function when this happens
351 __private_extern__ CFAllocatorRef
__CFAllocatorGetAllocator(CFTypeRef cf
) {
352 CFAllocatorRef allocator
= cf
;
353 return (kCFAllocatorUseContext
== allocator
->_allocator
) ? allocator
: allocator
->_allocator
;
356 __private_extern__
void __CFAllocatorDeallocate(CFTypeRef cf
) {
357 CFAllocatorRef self
= cf
;
358 CFAllocatorRef allocator
= self
->_allocator
;
359 CFAllocatorReleaseCallBack releaseFunc
= __CFAllocatorGetReleaseFunction(&self
->_context
);
360 if (kCFAllocatorUseContext
== allocator
) {
361 /* Rather a chicken and egg problem here, so we do things
362 in the reverse order from what was done at create time. */
363 CFAllocatorDeallocateCallBack deallocateFunc
= __CFAllocatorGetDeallocateFunction(&self
->_context
);
364 void *info
= self
->_context
.info
;
365 if (NULL
!= deallocateFunc
) {
366 INVOKE_CALLBACK2(deallocateFunc
, (void *)self
, info
);
368 if (NULL
!= releaseFunc
) {
369 INVOKE_CALLBACK1(releaseFunc
, info
);
372 if (NULL
!= releaseFunc
) {
373 INVOKE_CALLBACK1(releaseFunc
, self
->_context
.info
);
375 CFAllocatorDeallocate(allocator
, (void *)self
);
379 static CFTypeID __kCFAllocatorTypeID
= _kCFRuntimeNotATypeID
;
381 static const CFRuntimeClass __CFAllocatorClass
= {
386 __CFAllocatorDeallocate
,
390 __CFAllocatorCopyDescription
393 __private_extern__
void __CFAllocatorInitialize(void) {
394 __kCFAllocatorTypeID
= _CFRuntimeRegisterClass(&__CFAllocatorClass
);
396 _CFRuntimeSetInstanceTypeID(&__kCFAllocatorSystemDefault
, __kCFAllocatorTypeID
);
397 __kCFAllocatorSystemDefault
._base
._isa
= __CFISAForTypeID(__kCFAllocatorTypeID
);
398 #if defined(__MACH__)
399 __kCFAllocatorSystemDefault
._context
.info
= malloc_default_zone();
401 __kCFAllocatorSystemDefault
._allocator
= kCFAllocatorSystemDefault
;
402 memset(malloc_default_zone(), 0, 8);
404 _CFRuntimeSetInstanceTypeID(&__kCFAllocatorMalloc
, __kCFAllocatorTypeID
);
405 __kCFAllocatorMalloc
._base
._isa
= __CFISAForTypeID(__kCFAllocatorTypeID
);
406 __kCFAllocatorMalloc
._allocator
= kCFAllocatorSystemDefault
;
408 _CFRuntimeSetInstanceTypeID(&__kCFAllocatorNull
, __kCFAllocatorTypeID
);
409 __kCFAllocatorNull
._base
._isa
= __CFISAForTypeID(__kCFAllocatorTypeID
);
410 __kCFAllocatorNull
._allocator
= kCFAllocatorSystemDefault
;
414 CFTypeID
CFAllocatorGetTypeID(void) {
415 return __kCFAllocatorTypeID
;
418 CFAllocatorRef
CFAllocatorGetDefault(void) {
419 CFAllocatorRef allocator
= __CFGetThreadSpecificData_inline()->_allocator
;
420 if (NULL
== allocator
) {
421 allocator
= kCFAllocatorSystemDefault
;
426 void CFAllocatorSetDefault(CFAllocatorRef allocator
) {
427 CFAllocatorRef current
= __CFGetThreadSpecificData_inline()->_allocator
;
429 if (NULL
!= allocator
) {
430 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
433 #if defined(__MACH__)
434 if (allocator
&& allocator
->_base
._isa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
435 return; // require allocator to this function to be an allocator
438 if (NULL
!= allocator
&& allocator
!= current
) {
439 if (current
) CFRelease(current
);
441 // We retain an extra time so that anything set as the default
442 // allocator never goes away.
444 __CFGetThreadSpecificData_inline()->_allocator
= (void *)allocator
;
448 CFAllocatorRef
CFAllocatorCreate(CFAllocatorRef allocator
, CFAllocatorContext
*context
) {
449 struct __CFAllocator
*memory
;
450 CFAllocatorRetainCallBack retainFunc
;
451 CFAllocatorAllocateCallBack allocateFunc
;
454 if (NULL
== context
->allocate
) {
458 #if defined(__MACH__)
459 if (allocator
&& kCFAllocatorUseContext
!= allocator
&& allocator
->_base
._isa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
460 return NULL
; // require allocator to this function to be an allocator
463 retainFunc
= context
->retain
;
464 FAULT_CALLBACK((void **)&retainFunc
);
465 allocateFunc
= context
->allocate
;
466 FAULT_CALLBACK((void **)&allocateFunc
);
467 if (NULL
!= retainFunc
) {
468 retainedInfo
= (void *)INVOKE_CALLBACK1(retainFunc
, context
->info
);
470 retainedInfo
= context
->info
;
472 // We don't use _CFRuntimeCreateInstance()
473 if (kCFAllocatorUseContext
== allocator
) {
474 memory
= (void *)INVOKE_CALLBACK3(allocateFunc
, sizeof(struct __CFAllocator
), 0, retainedInfo
);
475 if (NULL
== memory
) {
479 allocator
= (NULL
== allocator
) ? __CFGetDefaultAllocator() : allocator
;
480 memory
= CFAllocatorAllocate(allocator
, sizeof(struct __CFAllocator
), 0);
481 if (__CFOASafe
) __CFSetLastAllocationEventName(memory
, "CFAllocator");
482 if (NULL
== memory
) {
486 memory
->_base
._isa
= 0;
487 memory
->_base
._rc
= 1;
488 memory
->_base
._info
= 0;
489 _CFRuntimeSetInstanceTypeID(memory
, __kCFAllocatorTypeID
);
490 memory
->_base
._isa
= __CFISAForTypeID(__kCFAllocatorTypeID
);
491 #if defined(__MACH__)
492 memory
->size
= __CFAllocatorCustomSize
;
493 memory
->malloc
= __CFAllocatorCustomMalloc
;
494 memory
->calloc
= __CFAllocatorCustomCalloc
;
495 memory
->valloc
= __CFAllocatorCustomValloc
;
496 memory
->free
= __CFAllocatorCustomFree
;
497 memory
->realloc
= __CFAllocatorCustomRealloc
;
498 memory
->destroy
= __CFAllocatorCustomDestroy
;
499 memory
->zone_name
= "Custom CFAllocator";
500 memory
->batch_malloc
= NULL
;
501 memory
->batch_free
= NULL
;
502 memory
->introspect
= &__CFAllocatorZoneIntrospect
;
503 memory
->reserved5
= NULL
;
505 memory
->_allocator
= allocator
;
506 memory
->_context
.version
= context
->version
;
507 memory
->_context
.info
= retainedInfo
;
508 memory
->_context
.retain
= retainFunc
;
509 memory
->_context
.release
= context
->release
;
510 FAULT_CALLBACK((void **)&(memory
->_context
.release
));
511 memory
->_context
.copyDescription
= context
->copyDescription
;
512 FAULT_CALLBACK((void **)&(memory
->_context
.copyDescription
));
513 memory
->_context
.allocate
= allocateFunc
;
514 memory
->_context
.reallocate
= context
->reallocate
;
515 FAULT_CALLBACK((void **)&(memory
->_context
.reallocate
));
516 memory
->_context
.deallocate
= context
->deallocate
;
517 FAULT_CALLBACK((void **)&(memory
->_context
.deallocate
));
518 memory
->_context
.preferredSize
= context
->preferredSize
;
519 FAULT_CALLBACK((void **)&(memory
->_context
.preferredSize
));
524 void *CFAllocatorAllocate(CFAllocatorRef allocator
, CFIndex size
, CFOptionFlags hint
) {
525 CFAllocatorAllocateCallBack allocateFunc
;
527 allocator
= (NULL
== allocator
) ? __CFGetDefaultAllocator() : allocator
;
528 #if defined(__MACH__) && defined(DEBUG)
529 if (allocator
->_base
._isa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
530 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
533 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
535 if (0 == size
) return NULL
;
536 #if defined(__MACH__)
537 if (allocator
->_base
._isa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
538 return malloc_zone_malloc((malloc_zone_t
*)allocator
, size
);
541 allocateFunc
= __CFAllocatorGetAllocateFunction(&allocator
->_context
);
542 newptr
= (void *)INVOKE_CALLBACK3(allocateFunc
, size
, hint
, allocator
->_context
.info
);
546 void *CFAllocatorReallocate(CFAllocatorRef allocator
, void *ptr
, CFIndex newsize
, CFOptionFlags hint
) {
547 CFAllocatorAllocateCallBack allocateFunc
;
548 CFAllocatorReallocateCallBack reallocateFunc
;
549 CFAllocatorDeallocateCallBack deallocateFunc
;
551 allocator
= (NULL
== allocator
) ? __CFGetDefaultAllocator() : allocator
;
552 #if defined(__MACH__) && defined(DEBUG)
553 if (allocator
->_base
._isa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
554 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
557 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
559 if (NULL
== ptr
&& 0 < newsize
) {
560 #if defined(__MACH__)
561 if (allocator
->_base
._isa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
562 return malloc_zone_malloc((malloc_zone_t
*)allocator
, newsize
);
565 allocateFunc
= __CFAllocatorGetAllocateFunction(&allocator
->_context
);
566 newptr
= (void *)INVOKE_CALLBACK3(allocateFunc
, newsize
, hint
, allocator
->_context
.info
);
569 if (NULL
!= ptr
&& 0 == newsize
) {
570 #if defined(__MACH__)
571 if (allocator
->_base
._isa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
572 malloc_zone_free((malloc_zone_t
*)allocator
, ptr
);
576 deallocateFunc
= __CFAllocatorGetDeallocateFunction(&allocator
->_context
);
577 if (NULL
!= deallocateFunc
) {
578 INVOKE_CALLBACK2(deallocateFunc
, ptr
, allocator
->_context
.info
);
582 if (NULL
== ptr
&& 0 == newsize
) return NULL
;
583 #if defined(__MACH__)
584 if (allocator
->_base
._isa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
585 return malloc_zone_realloc((malloc_zone_t
*)allocator
, ptr
, newsize
);
588 reallocateFunc
= __CFAllocatorGetReallocateFunction(&allocator
->_context
);
589 if (NULL
== reallocateFunc
) return NULL
;
590 newptr
= (void *)INVOKE_CALLBACK4(reallocateFunc
, ptr
, newsize
, hint
, allocator
->_context
.info
);
594 void CFAllocatorDeallocate(CFAllocatorRef allocator
, void *ptr
) {
595 CFAllocatorDeallocateCallBack deallocateFunc
;
596 allocator
= (NULL
== allocator
) ? __CFGetDefaultAllocator() : allocator
;
597 #if defined(__MACH__) && defined(DEBUG)
598 if (allocator
->_base
._isa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
599 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
602 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
604 #if defined(__MACH__)
605 if (allocator
->_base
._isa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
606 return malloc_zone_free((malloc_zone_t
*)allocator
, ptr
);
609 deallocateFunc
= __CFAllocatorGetDeallocateFunction(&allocator
->_context
);
610 if (NULL
!= ptr
&& NULL
!= deallocateFunc
) {
611 INVOKE_CALLBACK2(deallocateFunc
, ptr
, allocator
->_context
.info
);
615 CFIndex
CFAllocatorGetPreferredSizeForSize(CFAllocatorRef allocator
, CFIndex size
, CFOptionFlags hint
) {
616 CFAllocatorPreferredSizeCallBack prefFunc
;
618 allocator
= (NULL
== allocator
) ? __CFGetDefaultAllocator() : allocator
;
619 #if defined(__MACH__) && defined(DEBUG)
620 if (allocator
->_base
._isa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
621 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
624 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
626 #if defined(__MACH__)
627 if (allocator
->_base
._isa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
628 return malloc_good_size(size
);
631 prefFunc
= __CFAllocatorGetPreferredSizeFunction(&allocator
->_context
);
632 if (0 < size
&& NULL
!= prefFunc
) {
633 newsize
= (CFIndex
)(INVOKE_CALLBACK3(prefFunc
, size
, hint
, allocator
->_context
.info
));
635 if (newsize
< size
) newsize
= size
;
639 void CFAllocatorGetContext(CFAllocatorRef allocator
, CFAllocatorContext
*context
) {
640 allocator
= (NULL
== allocator
) ? __CFGetDefaultAllocator() : allocator
;
641 #if defined(__MACH__) && defined(DEBUG)
642 if (allocator
->_base
._isa
== __CFISAForTypeID(__kCFAllocatorTypeID
)) {
643 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
646 __CFGenericValidateType(allocator
, __kCFAllocatorTypeID
);
648 CFAssert1(0 == context
->version
, __kCFLogAssertion
, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__
);
649 #if defined(__MACH__)
650 if (allocator
->_base
._isa
!= __CFISAForTypeID(__kCFAllocatorTypeID
)) { // malloc_zone_t *
654 context
->version
= 0;
655 context
->info
= allocator
->_context
.info
;
656 context
->retain
= __CFAllocatorGetRetainFunction(&allocator
->_context
);
657 context
->release
= __CFAllocatorGetReleaseFunction(&allocator
->_context
);
658 context
->copyDescription
= __CFAllocatorGetCopyDescriptionFunction(&allocator
->_context
);
659 context
->allocate
= __CFAllocatorGetAllocateFunction(&allocator
->_context
);
660 context
->reallocate
= __CFAllocatorGetReallocateFunction(&allocator
->_context
);
661 context
->deallocate
= __CFAllocatorGetDeallocateFunction(&allocator
->_context
);
662 context
->preferredSize
= __CFAllocatorGetPreferredSizeFunction(&allocator
->_context
);
663 context
->retain
= (void *)((uintptr_t)context
->retain
& ~0x3);
664 context
->release
= (void *)((uintptr_t)context
->release
& ~0x3);
665 context
->copyDescription
= (void *)((uintptr_t)context
->copyDescription
& ~0x3);
666 context
->allocate
= (void *)((uintptr_t)context
->allocate
& ~0x3);
667 context
->reallocate
= (void *)((uintptr_t)context
->reallocate
& ~0x3);
668 context
->deallocate
= (void *)((uintptr_t)context
->deallocate
& ~0x3);
669 context
->preferredSize
= (void *)((uintptr_t)context
->preferredSize
& ~0x3);
672 // -------- -------- -------- -------- -------- -------- -------- --------
674 #if defined(__MACH__) || defined(__LINUX__) || defined(__FREEBSD__)
675 __private_extern__ pthread_key_t __CFTSDKey
= (pthread_key_t
)NULL
;
677 #if defined(__WIN32__)
678 __private_extern__ DWORD __CFTSDKey
= 0xFFFFFFFF;
681 // Called for each thread as it exits
682 static void __CFFinalizeThreadData(void *arg
) {
683 __CFThreadSpecificData
*tsd
= (__CFThreadSpecificData
*)arg
;
684 if (NULL
== tsd
) return;
685 if (tsd
->_allocator
) CFRelease(tsd
->_allocator
);
686 if (tsd
->_runLoop
) CFRelease(tsd
->_runLoop
);
687 CFAllocatorDeallocate(kCFAllocatorSystemDefault
, tsd
);
690 __private_extern__ __CFThreadSpecificData
*__CFGetThreadSpecificData(void) {
691 #if defined(__MACH__) || defined(__LINUX__) || defined(__FREEBSD__)
692 __CFThreadSpecificData
*data
;
693 data
= pthread_getspecific(__CFTSDKey
);
697 data
= CFAllocatorAllocate(kCFAllocatorSystemDefault
, sizeof(__CFThreadSpecificData
), 0);
698 if (__CFOASafe
) __CFSetLastAllocationEventName(data
, "CFUtilities (thread-data)");
699 memset(data
, 0, sizeof(__CFThreadSpecificData
));
700 pthread_setspecific(__CFTSDKey
, data
);
702 #elif defined(__WIN32__)
703 __CFThreadSpecificData
*data
;
704 data
= TlsGetValue(__CFTSDKey
);
708 data
= CFAllocatorAllocate(kCFAllocatorSystemDefault
, sizeof(__CFThreadSpecificData
), 0);
709 if (__CFOASafe
) __CFSetLastAllocationEventName(data
, "CFUtilities (thread-data)");
710 memset(data
, 0, sizeof(__CFThreadSpecificData
));
711 TlsSetValue(__CFTSDKey
, data
);
716 __private_extern__
void __CFBaseInitialize(void) {
717 #if defined(__MACH__) || defined(__LINUX__) || defined(__FREEBSD__)
718 pthread_key_create(&__CFTSDKey
, __CFFinalizeThreadData
);
720 #if defined(__WIN32__)
721 __CFTSDKey
= TlsAlloc();
726 CFRange
__CFRangeMake(CFIndex loc
, CFIndex len
) {
728 range
.location
= loc
;
733 __private_extern__
const void *__CFTypeCollectionRetain(CFAllocatorRef allocator
, const void *ptr
) {
734 return (const void *)CFRetain(ptr
);
737 __private_extern__
void __CFTypeCollectionRelease(CFAllocatorRef allocator
, const void *ptr
) {
746 static struct __CFNull __kCFNull
= {
749 const CFNullRef kCFNull
= &__kCFNull
;
751 static CFStringRef
__CFNullCopyDescription(CFTypeRef cf
) {
752 return CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("<CFNull %p [%p]>"), cf
, CFGetAllocator(cf
));
755 static CFStringRef
__CFNullCopyFormattingDescription(CFTypeRef cf
, CFDictionaryRef formatOptions
) {
756 return CFRetain(CFSTR("null"));
759 static void __CFNullDeallocate(CFTypeRef cf
) {
760 CFAssert(false, __kCFLogAssertion
, "Deallocated CFNull!");
763 static CFTypeID __kCFNullTypeID
= _kCFRuntimeNotATypeID
;
765 static const CFRuntimeClass __CFNullClass
= {
773 __CFNullCopyFormattingDescription
,
774 __CFNullCopyDescription
777 __private_extern__
void __CFNullInitialize(void) {
778 __kCFNullTypeID
= _CFRuntimeRegisterClass(&__CFNullClass
);
779 _CFRuntimeSetInstanceTypeID(&__kCFNull
, __kCFNullTypeID
);
780 __kCFNull
._base
._isa
= __CFISAForTypeID(__kCFNullTypeID
);
783 CFTypeID
CFNullGetTypeID(void) {
784 return __kCFNullTypeID
;
788 static int hasCFM
= 0;
790 void _CFRuntimeSetCFMPresent(int a
) {
794 #if defined(__MACH__) && defined(__ppc__)
796 /* See comments below */
797 __private_extern__
void __CF_FAULT_CALLBACK(void **ptr
) {
798 uintptr_t p
= (uintptr_t)*ptr
;
799 if ((0 == p
) || (p
& 0x1)) return;
801 *ptr
= (void *)(p
| 0x1);
803 int __known
= _dyld_image_containing_address(p
);
804 *ptr
= (void *)(p
| (__known
? 0x1 : 0x3));
809 Jump to callback function. r2 is not saved and restored
810 in the jump-to-CFM case, since we assume that dyld code
811 never uses that register and that CF is dyld.
813 There are three states for (ptr & 0x3):
814 0b00: check not yet done (or not going to be done, and is a dyld func ptr)
815 0b01: check done, dyld function pointer
816 0b11: check done, CFM tvector pointer
817 (but a NULL callback just stays NULL)
819 There may be up to 5 word-sized arguments. Floating point
820 arguments can be done, but count as two word arguments.
821 Return value can be integral or real.
824 /* Keep this assembly at the bottom of the source file! */
829 ".private_extern ___CF_INVOKE_CALLBACK\n"
830 "___CF_INVOKE_CALLBACK:\n"
831 "rlwinm r12,r3,0,0,29\n"
841 "Lcall: mtspr ctr,r12\n"
847 // void __HALT(void);
853 #if defined(__MACH__)
854 ".private_extern ___HALT\n"
863 #if defined(__i386__)
867 #if defined(__MACH__)
868 ".private_extern ___HALT\n"