]> git.saurik.com Git - apple/cf.git/blob - CFBase.c
CF-855.14.tar.gz
[apple/cf.git] / CFBase.c
1 /*
2 * Copyright (c) 2014 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /* CFBase.c
25 Copyright (c) 1998-2013, Apple Inc. All rights reserved.
26 Responsibility: Christopher Kane
27 */
28
29 #include <CoreFoundation/CFBase.h>
30 #include "CFInternal.h"
31 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
32 #include <pthread.h>
33 #endif
34 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
35 #include <malloc/malloc.h>
36 #include <mach/mach.h>
37 #include <dlfcn.h>
38 #endif
39 #include <stdlib.h>
40 #include <string.h>
41
42 // -------- -------- -------- -------- -------- -------- -------- --------
43
44 struct __CFAllocator {
45 CFRuntimeBase _base;
46 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
47 // CFAllocator structure must match struct _malloc_zone_t!
48 // The first two reserved fields in struct _malloc_zone_t are for us with CFRuntimeBase
49 size_t (*size)(struct _malloc_zone_t *zone, const void *ptr); /* returns the size of a block or 0 if not in this zone; must be fast, especially for negative answers */
50 void *(*malloc)(struct _malloc_zone_t *zone, size_t size);
51 void *(*calloc)(struct _malloc_zone_t *zone, size_t num_items, size_t size); /* same as malloc, but block returned is set to zero */
52 void *(*valloc)(struct _malloc_zone_t *zone, size_t size); /* same as malloc, but block returned is set to zero and is guaranteed to be page aligned */
53 void (*free)(struct _malloc_zone_t *zone, void *ptr);
54 void *(*realloc)(struct _malloc_zone_t *zone, void *ptr, size_t size);
55 void (*destroy)(struct _malloc_zone_t *zone); /* zone is destroyed and all memory reclaimed */
56 const char *zone_name;
57
58 /* Optional batch callbacks; these may be NULL */
59 unsigned (*batch_malloc)(struct _malloc_zone_t *zone, size_t size, void **results, unsigned num_requested); /* given a size, returns pointers capable of holding that size; returns the number of pointers allocated (maybe 0 or less than num_requested) */
60 void (*batch_free)(struct _malloc_zone_t *zone, void **to_be_freed, unsigned num_to_be_freed); /* frees all the pointers in to_be_freed; note that to_be_freed may be overwritten during the process */
61
62 struct malloc_introspection_t *introspect;
63 unsigned version;
64
65 /* aligned memory allocation. The callback may be NULL. */
66 void *(*memalign)(struct _malloc_zone_t *zone, size_t alignment, size_t size);
67
68 /* free a pointer known to be in zone and known to have the given size. The callback may be NULL. */
69 void (*free_definite_size)(struct _malloc_zone_t *zone, void *ptr, size_t size);
70 #endif
71 CFAllocatorRef _allocator;
72 CFAllocatorContext _context;
73 };
74
75 CF_INLINE CFAllocatorRetainCallBack __CFAllocatorGetRetainFunction(const CFAllocatorContext *context) {
76 CFAllocatorRetainCallBack retval = NULL;
77 retval = context->retain;
78 return retval;
79 }
80
81 CF_INLINE CFAllocatorReleaseCallBack __CFAllocatorGetReleaseFunction(const CFAllocatorContext *context) {
82 CFAllocatorReleaseCallBack retval = NULL;
83 retval = context->release;
84 return retval;
85 }
86
87 CF_INLINE CFAllocatorCopyDescriptionCallBack __CFAllocatorGetCopyDescriptionFunction(const CFAllocatorContext *context) {
88 CFAllocatorCopyDescriptionCallBack retval = NULL;
89 retval = context->copyDescription;
90 return retval;
91 }
92
93 CF_INLINE CFAllocatorAllocateCallBack __CFAllocatorGetAllocateFunction(const CFAllocatorContext *context) {
94 CFAllocatorAllocateCallBack retval = NULL;
95 retval = context->allocate;
96 return retval;
97 }
98
99 CF_INLINE CFAllocatorReallocateCallBack __CFAllocatorGetReallocateFunction(const CFAllocatorContext *context) {
100 CFAllocatorReallocateCallBack retval = NULL;
101 retval = context->reallocate;
102 return retval;
103 }
104
105 CF_INLINE CFAllocatorDeallocateCallBack __CFAllocatorGetDeallocateFunction(const CFAllocatorContext *context) {
106 CFAllocatorDeallocateCallBack retval = NULL;
107 retval = context->deallocate;
108 return retval;
109 }
110
111 CF_INLINE CFAllocatorPreferredSizeCallBack __CFAllocatorGetPreferredSizeFunction(const CFAllocatorContext *context) {
112 CFAllocatorPreferredSizeCallBack retval = NULL;
113 retval = context->preferredSize;
114 return retval;
115 }
116
117 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
118
119 CF_PRIVATE void __CFAllocatorDeallocate(CFTypeRef cf);
120
121 static kern_return_t __CFAllocatorZoneIntrospectNoOp(void) {
122 return 0;
123 }
124
125 static boolean_t __CFAllocatorZoneIntrospectTrue(void) {
126 return 1;
127 }
128
129 static size_t __CFAllocatorCustomSize(malloc_zone_t *zone, const void *ptr) {
130 return 0;
131
132 // The only way to implement this with a version 0 allocator would be
133 // for CFAllocator to keep track of all blocks allocated itself, which
134 // could be done, but would be bad for performance, so we don't do it.
135 // size_t (*size)(struct _malloc_zone_t *zone, const void *ptr);
136 /* returns the size of a block or 0 if not in this zone;
137 * must be fast, especially for negative answers */
138 }
139
140 static void *__CFAllocatorCustomMalloc(malloc_zone_t *zone, size_t size) {
141 CFAllocatorRef allocator = (CFAllocatorRef)zone;
142 return CFAllocatorAllocate(allocator, size, 0);
143 }
144
145 static void *__CFAllocatorCustomCalloc(malloc_zone_t *zone, size_t num_items, size_t size) {
146 CFAllocatorRef allocator = (CFAllocatorRef)zone;
147 void *newptr = CFAllocatorAllocate(allocator, size, 0);
148 if (newptr) memset(newptr, 0, size);
149 return newptr;
150 }
151
152 static void *__CFAllocatorCustomValloc(malloc_zone_t *zone, size_t size) {
153 CFAllocatorRef allocator = (CFAllocatorRef)zone;
154 if (size >= ULONG_MAX - 2 * vm_page_size) return NULL; // avoid integer overflow plus don't allow all pages to be allocated either
155 void *newptr = CFAllocatorAllocate(allocator, size + vm_page_size, 0);
156 newptr = (void *)round_page((uintptr_t)newptr);
157 return newptr;
158 }
159
160 static void __CFAllocatorCustomFree(malloc_zone_t *zone, void *ptr) {
161 CFAllocatorRef allocator = (CFAllocatorRef)zone;
162 CFAllocatorDeallocate(allocator, ptr);
163 }
164
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);
168 }
169
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);
179 }
180
181 static size_t __CFAllocatorCustomGoodSize(malloc_zone_t *zone, size_t size) {
182 CFAllocatorRef allocator = (CFAllocatorRef)zone;
183 return CFAllocatorGetPreferredSizeForSize(allocator, size, 0);
184 }
185
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
195 };
196
197 static size_t __CFAllocatorNullSize(malloc_zone_t *zone, const void *ptr) {
198 return 0;
199 }
200
201 static void * __CFAllocatorNullMalloc(malloc_zone_t *zone, size_t size) {
202 return NULL;
203 }
204
205 static void * __CFAllocatorNullCalloc(malloc_zone_t *zone, size_t num_items, size_t size) {
206 return NULL;
207 }
208
209 static void * __CFAllocatorNullValloc(malloc_zone_t *zone, size_t size) {
210 return NULL;
211 }
212
213 static void __CFAllocatorNullFree(malloc_zone_t *zone, void *ptr) {
214 }
215
216 static void * __CFAllocatorNullRealloc(malloc_zone_t *zone, void *ptr, size_t size) {
217 return NULL;
218 }
219
220 static void __CFAllocatorNullDestroy(malloc_zone_t *zone) {
221 }
222
223 static size_t __CFAllocatorNullGoodSize(malloc_zone_t *zone, size_t size) {
224 return size;
225 }
226
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
236 };
237
238 static void *__CFAllocatorSystemAllocate(CFIndex size, CFOptionFlags hint, void *info) {
239 return malloc_zone_malloc(info, size);
240 }
241
242 static void *__CFAllocatorSystemReallocate(void *ptr, CFIndex newsize, CFOptionFlags hint, void *info) {
243 return malloc_zone_realloc(info, ptr, newsize);
244 }
245
246 static void __CFAllocatorSystemDeallocate(void *ptr, void *info) {
247 #if defined(DEBUG)
248 size_t size = malloc_size(ptr);
249 if (size) memset(ptr, 0xCC, size);
250 #endif
251 malloc_zone_free(info, ptr);
252 }
253
254 #else
255
256 static void *__CFAllocatorSystemAllocate(CFIndex size, CFOptionFlags hint, void *info) {
257 return malloc(size);
258 }
259
260 static void *__CFAllocatorSystemReallocate(void *ptr, CFIndex newsize, CFOptionFlags hint, void *info) {
261 return realloc(ptr, newsize);
262 }
263
264 static void __CFAllocatorSystemDeallocate(void *ptr, void *info) {
265 free(ptr);
266 }
267 #endif
268
269 static void *__CFAllocatorNullAllocate(CFIndex size, CFOptionFlags hint, void *info) {
270 return NULL;
271 }
272
273 static void *__CFAllocatorNullReallocate(void *ptr, CFIndex newsize, CFOptionFlags hint, void *info) {
274 return NULL;
275 }
276
277 #if defined (__cplusplus)
278 static void * __CFAllocatorCPPMalloc(CFIndex allocSize, CFOptionFlags hint, void *info)
279 {
280 return malloc(allocSize);
281 }
282 static void * __CFAllocatorCPPReAlloc(void *ptr, CFIndex newsize, CFOptionFlags hint, void *info)
283 {
284 return realloc(ptr, newsize);
285 }
286 static void __CFAllocatorCPPFree(void *ptr, void *info)
287 {
288 free(ptr);
289 }
290 #endif // C++
291
292
293 static struct __CFAllocator __kCFAllocatorMalloc = {
294 INIT_CFRUNTIME_BASE(),
295 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
296 __CFAllocatorCustomSize,
297 __CFAllocatorCustomMalloc,
298 __CFAllocatorCustomCalloc,
299 __CFAllocatorCustomValloc,
300 __CFAllocatorCustomFree,
301 __CFAllocatorCustomRealloc,
302 __CFAllocatorNullDestroy,
303 "kCFAllocatorMalloc",
304 NULL,
305 NULL,
306 &__CFAllocatorZoneIntrospect,
307 6,
308 NULL,
309 NULL,
310 #endif
311 NULL, // _allocator
312 // Using the malloc functions directly is a total cheat, but works (in C)
313 // because the function signatures match in their common prefix of arguments.
314 // This saves us one hop through an adaptor function.
315 #if !defined (__cplusplus)
316 {0, NULL, NULL, NULL, NULL, (void *)malloc, (void *)realloc, (void *)free, NULL}
317 #else
318 {0, NULL, NULL, NULL, NULL, __CFAllocatorCPPMalloc,__CFAllocatorCPPReAlloc, __CFAllocatorCPPFree, NULL}
319 #endif // __cplusplus
320 };
321
322 static struct __CFAllocator __kCFAllocatorMallocZone = {
323 INIT_CFRUNTIME_BASE(),
324 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
325 __CFAllocatorCustomSize,
326 __CFAllocatorCustomMalloc,
327 __CFAllocatorCustomCalloc,
328 __CFAllocatorCustomValloc,
329 __CFAllocatorCustomFree,
330 __CFAllocatorCustomRealloc,
331 __CFAllocatorNullDestroy,
332 "kCFAllocatorMallocZone",
333 NULL,
334 NULL,
335 &__CFAllocatorZoneIntrospect,
336 6,
337 NULL,
338 NULL,
339 #endif
340 NULL, // _allocator
341 {0, NULL, NULL, NULL, NULL, __CFAllocatorSystemAllocate, __CFAllocatorSystemReallocate, __CFAllocatorSystemDeallocate, NULL}
342 };
343
344 static struct __CFAllocator __kCFAllocatorSystemDefault = {
345 INIT_CFRUNTIME_BASE(),
346 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
347 __CFAllocatorCustomSize,
348 __CFAllocatorCustomMalloc,
349 __CFAllocatorCustomCalloc,
350 __CFAllocatorCustomValloc,
351 __CFAllocatorCustomFree,
352 __CFAllocatorCustomRealloc,
353 __CFAllocatorNullDestroy,
354 "kCFAllocatorSystemDefault",
355 NULL,
356 NULL,
357 &__CFAllocatorZoneIntrospect,
358 6,
359 NULL,
360 NULL,
361 #endif
362 NULL, // _allocator
363 {0, NULL, NULL, NULL, NULL, __CFAllocatorSystemAllocate, __CFAllocatorSystemReallocate, __CFAllocatorSystemDeallocate, NULL}
364 };
365
366 static struct __CFAllocator __kCFAllocatorNull = {
367 INIT_CFRUNTIME_BASE(),
368 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
369 __CFAllocatorNullSize,
370 __CFAllocatorNullMalloc,
371 __CFAllocatorNullCalloc,
372 __CFAllocatorNullValloc,
373 __CFAllocatorNullFree,
374 __CFAllocatorNullRealloc,
375 __CFAllocatorNullDestroy,
376 "kCFAllocatorNull",
377 NULL,
378 NULL,
379 &__CFAllocatorNullZoneIntrospect,
380 6,
381 NULL,
382 NULL,
383 #endif
384 NULL, // _allocator
385 {0, NULL, NULL, NULL, NULL, __CFAllocatorNullAllocate, __CFAllocatorNullReallocate, NULL, NULL}
386 };
387
388 const CFAllocatorRef kCFAllocatorDefault = NULL;
389 const CFAllocatorRef kCFAllocatorSystemDefault = &__kCFAllocatorSystemDefault;
390 const CFAllocatorRef kCFAllocatorMalloc = &__kCFAllocatorMalloc;
391 const CFAllocatorRef kCFAllocatorMallocZone = &__kCFAllocatorMallocZone;
392 const CFAllocatorRef kCFAllocatorNull = &__kCFAllocatorNull;
393 const CFAllocatorRef kCFAllocatorUseContext = (CFAllocatorRef)0x03ab;
394 #undef kCFAllocatorSystemDefaultGCRefZero
395 #undef kCFAllocatorDefaultGCRefZero
396 const CFAllocatorRef kCFAllocatorSystemDefaultGCRefZero = (CFAllocatorRef)0x03ad;
397 const CFAllocatorRef kCFAllocatorDefaultGCRefZero = (CFAllocatorRef)0x03af;
398
399 static CFStringRef __CFAllocatorCopyDescription(CFTypeRef cf) {
400 CFAllocatorRef self = (CFAllocatorRef)cf;
401 CFAllocatorRef allocator = (kCFAllocatorUseContext == self->_allocator) ? self : self->_allocator;
402 return CFStringCreateWithFormat(allocator, NULL, CFSTR("<CFAllocator %p [%p]>{info = %p}"), cf, allocator, self->_context.info);
403 // CF: should use copyDescription function here to describe info field
404 // remember to release value returned from copydescr function when this happens
405 }
406
407 CF_PRIVATE CFAllocatorRef __CFAllocatorGetAllocator(CFTypeRef cf) {
408 CFAllocatorRef allocator = (CFAllocatorRef)cf;
409 return (kCFAllocatorUseContext == allocator->_allocator) ? allocator : allocator->_allocator;
410 }
411
412 CF_PRIVATE void __CFAllocatorDeallocate(CFTypeRef cf) {
413 CFAllocatorRef self = (CFAllocatorRef)cf;
414 CFAllocatorRef allocator = self->_allocator;
415 CFAllocatorReleaseCallBack releaseFunc = __CFAllocatorGetReleaseFunction(&self->_context);
416 if (kCFAllocatorUseContext == allocator) {
417 /* Rather a chicken and egg problem here, so we do things
418 in the reverse order from what was done at create time. */
419 CFAllocatorDeallocateCallBack deallocateFunc = __CFAllocatorGetDeallocateFunction(&self->_context);
420 void *info = self->_context.info;
421 if (NULL != deallocateFunc) {
422 INVOKE_CALLBACK2(deallocateFunc, (void *)self, info);
423 }
424 if (NULL != releaseFunc) {
425 INVOKE_CALLBACK1(releaseFunc, info);
426 }
427 } else {
428 if (NULL != releaseFunc) {
429 INVOKE_CALLBACK1(releaseFunc, self->_context.info);
430 }
431 if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) CFAllocatorDeallocate(allocator, (void *)self);
432 }
433 }
434
435 static CFTypeID __kCFAllocatorTypeID = _kCFRuntimeNotATypeID;
436
437 static const CFRuntimeClass __CFAllocatorClass = {
438 0,
439 "CFAllocator",
440 NULL, // init
441 NULL, // copy
442 NULL,
443 NULL, // equal
444 NULL, // hash
445 NULL, //
446 __CFAllocatorCopyDescription
447 };
448
449 static void _CFAllocatorSetInstanceTypeIDAndIsa(struct __CFAllocator *memory) {
450 _CFRuntimeSetInstanceTypeID(memory, __kCFAllocatorTypeID);
451 memory->_base._cfisa = __CFISAForTypeID(__kCFAllocatorTypeID);
452 }
453
454 CF_PRIVATE void __CFAllocatorInitialize(void) {
455 __kCFAllocatorTypeID = _CFRuntimeRegisterClass(&__CFAllocatorClass);
456
457 _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorSystemDefault);
458 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
459 __kCFAllocatorSystemDefault._context.info = (kCFUseCollectableAllocator ? objc_collectableZone() : malloc_default_zone());
460 #endif
461 __kCFAllocatorSystemDefault._allocator = kCFAllocatorSystemDefault;
462
463 _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorMalloc);
464 __kCFAllocatorMalloc._allocator = kCFAllocatorSystemDefault;
465
466 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
467 _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorMallocZone);
468 __kCFAllocatorMallocZone._allocator = kCFAllocatorSystemDefault;
469 __kCFAllocatorMallocZone._context.info = malloc_default_zone();
470 #endif
471
472 _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorNull);
473 __kCFAllocatorNull._allocator = kCFAllocatorSystemDefault;
474 }
475
476 CFTypeID CFAllocatorGetTypeID(void) {
477 return __kCFAllocatorTypeID;
478 }
479
480 CFAllocatorRef CFAllocatorGetDefault(void) {
481 return __CFGetDefaultAllocator();
482 }
483
484 void CFAllocatorSetDefault(CFAllocatorRef allocator) {
485 CFAllocatorRef current = __CFGetDefaultAllocator();
486 #if defined(DEBUG)
487 if (NULL != allocator) {
488 __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
489 }
490 #endif
491 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
492 if (allocator && allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
493 return; // require allocator to this function to be an allocator
494 }
495 #endif
496 if (NULL != allocator && allocator != current) {
497 if (current) CFRelease(current);
498 CFRetain(allocator);
499 // We retain an extra time so that anything set as the default
500 // allocator never goes away.
501 CFRetain(allocator);
502 _CFSetTSD(__CFTSDKeyAllocator, (void *)allocator, NULL);
503 }
504 }
505
506 static CFAllocatorRef __CFAllocatorCreate(CFAllocatorRef allocator, CFAllocatorContext *context) {
507 struct __CFAllocator *memory = NULL;
508 CFAllocatorRetainCallBack retainFunc;
509 CFAllocatorAllocateCallBack allocateFunc;
510 void *retainedInfo;
511 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
512 if (allocator && kCFAllocatorUseContext != allocator && allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
513 return NULL; // require allocator to this function to be an allocator
514 }
515 #endif
516 retainFunc = context->retain;
517 FAULT_CALLBACK((void **)&retainFunc);
518 allocateFunc = context->allocate;
519 FAULT_CALLBACK((void **)&allocateFunc);
520 if (NULL != retainFunc) {
521 retainedInfo = (void *)INVOKE_CALLBACK1(retainFunc, context->info);
522 } else {
523 retainedInfo = context->info;
524 }
525 // We don't use _CFRuntimeCreateInstance()
526 if (kCFAllocatorUseContext == allocator) {
527 memory = NULL;
528 if (allocateFunc) {
529 memory = (struct __CFAllocator *)INVOKE_CALLBACK3(allocateFunc, sizeof(struct __CFAllocator), 0, retainedInfo);
530 }
531 if (NULL == memory) {
532 return NULL;
533 }
534 } else {
535 allocator = (NULL == allocator) ? __CFGetDefaultAllocator() : allocator;
536 memory = (struct __CFAllocator *)CFAllocatorAllocate(allocator, sizeof(struct __CFAllocator), __kCFAllocatorGCObjectMemory);
537 if (NULL == memory) {
538 return NULL;
539 }
540 if (__CFOASafe) __CFSetLastAllocationEventName(memory, "CFAllocator");
541 }
542 memset(memory, 0, sizeof(CFRuntimeBase));
543 #if __LP64__
544 memory->_base._rc = 1;
545 #else
546 memory->_base._cfinfo[CF_RC_BITS] = 1;
547 #endif
548 memory->_base._cfinfo[CF_INFO_BITS] = 0;
549 _CFAllocatorSetInstanceTypeIDAndIsa(memory);
550 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
551 memory->size = __CFAllocatorCustomSize;
552 memory->malloc = __CFAllocatorCustomMalloc;
553 memory->calloc = __CFAllocatorCustomCalloc;
554 memory->valloc = __CFAllocatorCustomValloc;
555 memory->free = __CFAllocatorCustomFree;
556 memory->realloc = __CFAllocatorCustomRealloc;
557 memory->destroy = __CFAllocatorCustomDestroy;
558 memory->zone_name = "Custom CFAllocator";
559 memory->batch_malloc = NULL;
560 memory->batch_free = NULL;
561 memory->introspect = &__CFAllocatorZoneIntrospect;
562 memory->version = 6;
563 memory->memalign = NULL;
564 memory->free_definite_size = NULL;
565 #endif
566 memory->_allocator = allocator;
567 memory->_context.version = context->version;
568 memory->_context.info = retainedInfo;
569 memory->_context.retain = retainFunc;
570 memory->_context.release = context->release;
571 FAULT_CALLBACK((void **)&(memory->_context.release));
572 memory->_context.copyDescription = context->copyDescription;
573 FAULT_CALLBACK((void **)&(memory->_context.copyDescription));
574 memory->_context.allocate = allocateFunc;
575 memory->_context.reallocate = context->reallocate;
576 FAULT_CALLBACK((void **)&(memory->_context.reallocate));
577 memory->_context.deallocate = context->deallocate;
578 FAULT_CALLBACK((void **)&(memory->_context.deallocate));
579 memory->_context.preferredSize = context->preferredSize;
580 FAULT_CALLBACK((void **)&(memory->_context.preferredSize));
581
582 return memory;
583 }
584
585 CFAllocatorRef CFAllocatorCreate(CFAllocatorRef allocator, CFAllocatorContext *context) {
586 return __CFAllocatorCreate(allocator, context);
587 }
588
589 void *CFAllocatorAllocate(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint) {
590 CFAllocatorAllocateCallBack allocateFunc;
591 void *newptr = NULL;
592
593 Boolean initialRefcountOne = true;
594 if (NULL == allocator) {
595 allocator = __CFGetDefaultAllocator();
596 }
597
598 #if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
599 if (allocator->_base._cfisa == __CFISAForTypeID(__kCFAllocatorTypeID)) {
600 __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
601 }
602 #else
603 __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
604 #endif
605 if (0 == size) return NULL;
606 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
607 if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
608 return malloc_zone_malloc((malloc_zone_t *)allocator, size);
609 }
610 #endif
611 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
612 newptr = auto_zone_allocate_object((auto_zone_t*)allocator->_context.info, size, CF_GET_GC_MEMORY_TYPE(hint), initialRefcountOne, false);
613 } else {
614 newptr = NULL;
615 allocateFunc = __CFAllocatorGetAllocateFunction(&allocator->_context);
616 if (allocateFunc) {
617 newptr = (void *)INVOKE_CALLBACK3(allocateFunc, size, hint, allocator->_context.info);
618 }
619 }
620 return newptr;
621 }
622
623 void *CFAllocatorReallocate(CFAllocatorRef allocator, void *ptr, CFIndex newsize, CFOptionFlags hint) {
624 CFAllocatorAllocateCallBack allocateFunc;
625 CFAllocatorReallocateCallBack reallocateFunc;
626 CFAllocatorDeallocateCallBack deallocateFunc;
627 void *newptr;
628
629 if (0) {
630 allocator = kCFAllocatorSystemDefault;
631 } else if (0) {
632 allocator = kCFUseCollectableAllocator ? kCFAllocatorSystemDefault : __CFGetDefaultAllocator();
633 } else if (NULL == allocator) {
634 allocator = __CFGetDefaultAllocator();
635 }
636
637 #if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
638 if (allocator->_base._cfisa == __CFISAForTypeID(__kCFAllocatorTypeID)) {
639 __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
640 }
641 #else
642 __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
643 #endif
644 if (NULL == ptr && 0 < newsize) {
645 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
646 if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
647 return malloc_zone_malloc((malloc_zone_t *)allocator, newsize);
648 }
649 #endif
650 newptr = NULL;
651 allocateFunc = __CFAllocatorGetAllocateFunction(&allocator->_context);
652 if (allocateFunc) {
653 newptr = (void *)INVOKE_CALLBACK3(allocateFunc, newsize, hint, allocator->_context.info);
654 }
655 return newptr;
656 }
657 if (NULL != ptr && 0 == newsize) {
658 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
659 if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
660 #if defined(DEBUG)
661 size_t size = malloc_size(ptr);
662 if (size) memset(ptr, 0xCC, size);
663 #endif
664 malloc_zone_free((malloc_zone_t *)allocator, ptr);
665 return NULL;
666 }
667 #endif
668 deallocateFunc = __CFAllocatorGetDeallocateFunction(&allocator->_context);
669 if (NULL != deallocateFunc) {
670 INVOKE_CALLBACK2(deallocateFunc, ptr, allocator->_context.info);
671 }
672 return NULL;
673 }
674 if (NULL == ptr && 0 == newsize) return NULL;
675 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
676 if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
677 return malloc_zone_realloc((malloc_zone_t *)allocator, ptr, newsize);
678 }
679 #endif
680 reallocateFunc = __CFAllocatorGetReallocateFunction(&allocator->_context);
681 if (NULL == reallocateFunc) return NULL;
682 newptr = (void *)INVOKE_CALLBACK4(reallocateFunc, ptr, newsize, hint, allocator->_context.info);
683 return newptr;
684 }
685
686 void CFAllocatorDeallocate(CFAllocatorRef allocator, void *ptr) {
687 CFAllocatorDeallocateCallBack deallocateFunc;
688
689 if (0) {
690 allocator = kCFAllocatorSystemDefault;
691 } else if (0) {
692 allocator = kCFUseCollectableAllocator ? kCFAllocatorSystemDefault : __CFGetDefaultAllocator();
693 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) return;
694 } else if (NULL == allocator) {
695 allocator = __CFGetDefaultAllocator();
696 }
697
698 #if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
699 if (allocator->_base._cfisa == __CFISAForTypeID(__kCFAllocatorTypeID)) {
700 __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
701 }
702 #else
703 __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
704 #endif
705 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
706 if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
707 #if defined(DEBUG)
708 size_t size = malloc_size(ptr);
709 if (size) memset(ptr, 0xCC, size);
710 #endif
711 return malloc_zone_free((malloc_zone_t *)allocator, ptr);
712 }
713 #endif
714 deallocateFunc = __CFAllocatorGetDeallocateFunction(&allocator->_context);
715 if (NULL != ptr && NULL != deallocateFunc) {
716 INVOKE_CALLBACK2(deallocateFunc, ptr, allocator->_context.info);
717 }
718 }
719
720 CFIndex CFAllocatorGetPreferredSizeForSize(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint) {
721 CFAllocatorPreferredSizeCallBack prefFunc;
722 CFIndex newsize = 0;
723
724 if (0) {
725 allocator = kCFAllocatorSystemDefault;
726 } else if (0) {
727 allocator = kCFUseCollectableAllocator ? kCFAllocatorSystemDefault : __CFGetDefaultAllocator();
728 } else if (NULL == allocator) {
729 allocator = __CFGetDefaultAllocator();
730 }
731
732 #if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
733 if (allocator->_base._cfisa == __CFISAForTypeID(__kCFAllocatorTypeID)) {
734 __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
735 }
736 #else
737 __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
738 #endif
739 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
740 if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
741 return malloc_good_size(size);
742 }
743 #endif
744 prefFunc = __CFAllocatorGetPreferredSizeFunction(&allocator->_context);
745 if (0 < size && NULL != prefFunc) {
746 newsize = (CFIndex)(INVOKE_CALLBACK3(prefFunc, size, hint, allocator->_context.info));
747 }
748 if (newsize < size) newsize = size;
749 return newsize;
750 }
751
752 void CFAllocatorGetContext(CFAllocatorRef allocator, CFAllocatorContext *context) {
753 if (0) {
754 allocator = kCFAllocatorSystemDefault;
755 } else if (0) {
756 allocator = kCFUseCollectableAllocator ? kCFAllocatorSystemDefault : __CFGetDefaultAllocator();
757 } else if (NULL == allocator) {
758 allocator = __CFGetDefaultAllocator();
759 }
760
761 #if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
762 if (allocator->_base._cfisa == __CFISAForTypeID(__kCFAllocatorTypeID)) {
763 __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
764 }
765 #else
766 __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
767 #endif
768 CFAssert1(0 == context->version, __kCFLogAssertion, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__);
769 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
770 if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
771 return;
772 }
773 #endif
774 context->version = 0;
775 context->info = allocator->_context.info;
776 context->retain = __CFAllocatorGetRetainFunction(&allocator->_context);
777 context->release = __CFAllocatorGetReleaseFunction(&allocator->_context);
778 context->copyDescription = __CFAllocatorGetCopyDescriptionFunction(&allocator->_context);
779 context->allocate = __CFAllocatorGetAllocateFunction(&allocator->_context);
780 context->reallocate = __CFAllocatorGetReallocateFunction(&allocator->_context);
781 context->deallocate = __CFAllocatorGetDeallocateFunction(&allocator->_context);
782 context->preferredSize = __CFAllocatorGetPreferredSizeFunction(&allocator->_context);
783 }
784
785 CF_PRIVATE void *_CFAllocatorAllocateGC(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint)
786 {
787 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator))
788 return auto_zone_allocate_object((auto_zone_t*)kCFAllocatorSystemDefault->_context.info, size, CF_GET_GC_MEMORY_TYPE(hint), false, false);
789 else
790 return CFAllocatorAllocate(allocator, size, hint);
791 }
792
793 CF_PRIVATE void *_CFAllocatorReallocateGC(CFAllocatorRef allocator, void *ptr, CFIndex newsize, CFOptionFlags hint)
794 {
795 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
796 if (ptr && (newsize == 0)) {
797 return NULL; // equivalent to _CFAllocatorDeallocateGC.
798 }
799 if (ptr == NULL) {
800 return auto_zone_allocate_object((auto_zone_t*)kCFAllocatorSystemDefault->_context.info, newsize, CF_GET_GC_MEMORY_TYPE(hint), false, false); // eq. to _CFAllocator
801 }
802 }
803 // otherwise, auto_realloc() now preserves layout type and refCount.
804 return CFAllocatorReallocate(allocator, ptr, newsize, hint);
805 }
806
807 CF_PRIVATE void _CFAllocatorDeallocateGC(CFAllocatorRef allocator, void *ptr)
808 {
809 // when running GC, don't deallocate.
810 if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) CFAllocatorDeallocate(allocator, ptr);
811 }
812
813 // -------- -------- -------- -------- -------- -------- -------- --------
814
815
816 CFRange __CFRangeMake(CFIndex loc, CFIndex len) {
817 CFRange range;
818 range.location = loc;
819 range.length = len;
820 return range;
821 }
822
823
824 struct __CFNull {
825 CFRuntimeBase _base;
826 };
827
828 static struct __CFNull __kCFNull = {
829 INIT_CFRUNTIME_BASE()
830 };
831 const CFNullRef kCFNull = &__kCFNull;
832
833 static CFStringRef __CFNullCopyDescription(CFTypeRef cf) {
834 return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFNull %p [%p]>"), cf, CFGetAllocator(cf));
835 }
836
837 static CFStringRef __CFNullCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) {
838 return (CFStringRef)CFRetain(CFSTR("null"));
839 }
840
841 static void __CFNullDeallocate(CFTypeRef cf) {
842 CFAssert(false, __kCFLogAssertion, "Deallocated CFNull!");
843 }
844
845 static CFTypeID __kCFNullTypeID = _kCFRuntimeNotATypeID;
846
847 static const CFRuntimeClass __CFNullClass = {
848 0,
849 "CFNull",
850 NULL, // init
851 NULL, // copy
852 __CFNullDeallocate,
853 NULL,
854 NULL,
855 __CFNullCopyFormattingDescription,
856 __CFNullCopyDescription
857 };
858
859 CF_PRIVATE void __CFNullInitialize(void) {
860 __kCFNullTypeID = _CFRuntimeRegisterClass(&__CFNullClass);
861 _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFNull, __kCFNullTypeID);
862 }
863
864 CFTypeID CFNullGetTypeID(void) {
865 return __kCFNullTypeID;
866 }
867
868 void CFCollection_non_gc_storage_error(void) { }
869
870
871 void _CFRuntimeSetCFMPresent(void *addr) {
872 }
873
874
875 // void __HALT(void);
876
877 /* Keep this assembly at the bottom of the source file! */
878
879
880 extern void __HALT() {
881 #if defined(__ppc__)
882 __asm__("trap");
883 #elif defined(__i386__) || defined(__x86_64__)
884 #if defined(_MSC_VER)
885 __asm int 3;
886 #else
887 __asm__("int3");
888 #endif
889 #endif
890 }
891
892