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"