]> git.saurik.com Git - apple/cf.git/blame_incremental - CFBase.c
CF-1153.18.tar.gz
[apple/cf.git] / CFBase.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 2015 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-2014, 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
44struct __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
75CF_INLINE CFAllocatorRetainCallBack __CFAllocatorGetRetainFunction(const CFAllocatorContext *context) {
76 CFAllocatorRetainCallBack retval = NULL;
77 retval = context->retain;
78 return retval;
79}
80
81CF_INLINE CFAllocatorReleaseCallBack __CFAllocatorGetReleaseFunction(const CFAllocatorContext *context) {
82 CFAllocatorReleaseCallBack retval = NULL;
83 retval = context->release;
84 return retval;
85}
86
87CF_INLINE CFAllocatorCopyDescriptionCallBack __CFAllocatorGetCopyDescriptionFunction(const CFAllocatorContext *context) {
88 CFAllocatorCopyDescriptionCallBack retval = NULL;
89 retval = context->copyDescription;
90 return retval;
91}
92
93CF_INLINE CFAllocatorAllocateCallBack __CFAllocatorGetAllocateFunction(const CFAllocatorContext *context) {
94 CFAllocatorAllocateCallBack retval = NULL;
95 retval = context->allocate;
96 return retval;
97}
98
99CF_INLINE CFAllocatorReallocateCallBack __CFAllocatorGetReallocateFunction(const CFAllocatorContext *context) {
100 CFAllocatorReallocateCallBack retval = NULL;
101 retval = context->reallocate;
102 return retval;
103}
104
105CF_INLINE CFAllocatorDeallocateCallBack __CFAllocatorGetDeallocateFunction(const CFAllocatorContext *context) {
106 CFAllocatorDeallocateCallBack retval = NULL;
107 retval = context->deallocate;
108 return retval;
109}
110
111CF_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
119CF_PRIVATE void __CFAllocatorDeallocate(CFTypeRef cf);
120
121static kern_return_t __CFAllocatorZoneIntrospectNoOp(void) {
122 return 0;
123}
124
125static boolean_t __CFAllocatorZoneIntrospectTrue(void) {
126 return 1;
127}
128
129static 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
140static void *__CFAllocatorCustomMalloc(malloc_zone_t *zone, size_t size) {
141 CFAllocatorRef allocator = (CFAllocatorRef)zone;
142 return CFAllocatorAllocate(allocator, size, 0);
143}
144
145static 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
152static 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
160static void __CFAllocatorCustomFree(malloc_zone_t *zone, void *ptr) {
161 CFAllocatorRef allocator = (CFAllocatorRef)zone;
162 CFAllocatorDeallocate(allocator, ptr);
163}
164
165static 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
170static 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
181static size_t __CFAllocatorCustomGoodSize(malloc_zone_t *zone, size_t size) {
182 CFAllocatorRef allocator = (CFAllocatorRef)zone;
183 return CFAllocatorGetPreferredSizeForSize(allocator, size, 0);
184}
185
186static 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
197static size_t __CFAllocatorNullSize(malloc_zone_t *zone, const void *ptr) {
198 return 0;
199}
200
201static void * __CFAllocatorNullMalloc(malloc_zone_t *zone, size_t size) {
202 return NULL;
203}
204
205static void * __CFAllocatorNullCalloc(malloc_zone_t *zone, size_t num_items, size_t size) {
206 return NULL;
207}
208
209static void * __CFAllocatorNullValloc(malloc_zone_t *zone, size_t size) {
210 return NULL;
211}
212
213static void __CFAllocatorNullFree(malloc_zone_t *zone, void *ptr) {
214}
215
216static void * __CFAllocatorNullRealloc(malloc_zone_t *zone, void *ptr, size_t size) {
217 return NULL;
218}
219
220static void __CFAllocatorNullDestroy(malloc_zone_t *zone) {
221}
222
223static size_t __CFAllocatorNullGoodSize(malloc_zone_t *zone, size_t size) {
224 return size;
225}
226
227static 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
238static void *__CFAllocatorSystemAllocate(CFIndex size, CFOptionFlags hint, void *info) {
239 return malloc_zone_malloc(info, size);
240}
241
242static void *__CFAllocatorSystemReallocate(void *ptr, CFIndex newsize, CFOptionFlags hint, void *info) {
243 return malloc_zone_realloc(info, ptr, newsize);
244}
245
246static 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
256static void *__CFAllocatorSystemAllocate(CFIndex size, CFOptionFlags hint, void *info) {
257 return malloc(size);
258}
259
260static void *__CFAllocatorSystemReallocate(void *ptr, CFIndex newsize, CFOptionFlags hint, void *info) {
261 return realloc(ptr, newsize);
262}
263
264static void __CFAllocatorSystemDeallocate(void *ptr, void *info) {
265 free(ptr);
266}
267#endif
268
269static void *__CFAllocatorNullAllocate(CFIndex size, CFOptionFlags hint, void *info) {
270 return NULL;
271}
272
273static void *__CFAllocatorNullReallocate(void *ptr, CFIndex newsize, CFOptionFlags hint, void *info) {
274 return NULL;
275}
276
277#if defined (__cplusplus)
278static void * __CFAllocatorCPPMalloc(CFIndex allocSize, CFOptionFlags hint, void *info)
279{
280 return malloc(allocSize);
281}
282static void * __CFAllocatorCPPReAlloc(void *ptr, CFIndex newsize, CFOptionFlags hint, void *info)
283{
284 return realloc(ptr, newsize);
285}
286static void __CFAllocatorCPPFree(void *ptr, void *info)
287{
288 free(ptr);
289}
290#endif // C++
291
292
293static 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
322static 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
344static 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
366static 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
388const CFAllocatorRef kCFAllocatorDefault = NULL;
389const CFAllocatorRef kCFAllocatorSystemDefault = &__kCFAllocatorSystemDefault;
390const CFAllocatorRef kCFAllocatorMalloc = &__kCFAllocatorMalloc;
391const CFAllocatorRef kCFAllocatorMallocZone = &__kCFAllocatorMallocZone;
392const CFAllocatorRef kCFAllocatorNull = &__kCFAllocatorNull;
393const CFAllocatorRef kCFAllocatorUseContext = (CFAllocatorRef)0x03ab;
394#undef kCFAllocatorSystemDefaultGCRefZero
395#undef kCFAllocatorDefaultGCRefZero
396const CFAllocatorRef kCFAllocatorSystemDefaultGCRefZero = (CFAllocatorRef)0x03ad;
397const CFAllocatorRef kCFAllocatorDefaultGCRefZero = (CFAllocatorRef)0x03af;
398
399static 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
407CF_PRIVATE CFAllocatorRef __CFAllocatorGetAllocator(CFTypeRef cf) {
408 CFAllocatorRef allocator = (CFAllocatorRef)cf;
409 return (kCFAllocatorUseContext == allocator->_allocator) ? allocator : allocator->_allocator;
410}
411
412CF_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
435static CFTypeID __kCFAllocatorTypeID = _kCFRuntimeNotATypeID;
436
437static 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
449static void _CFAllocatorSetInstanceTypeIDAndIsa(struct __CFAllocator *memory) {
450 _CFRuntimeSetInstanceTypeID(memory, __kCFAllocatorTypeID);
451 memory->_base._cfisa = __CFISAForTypeID(__kCFAllocatorTypeID);
452}
453
454CF_PRIVATE void __CFAllocatorInitialize(void) {
455 static dispatch_once_t initOnce;
456 dispatch_once(&initOnce, ^{
457 __kCFAllocatorTypeID = _CFRuntimeRegisterClass(&__CFAllocatorClass); // initOnce covered
458
459 _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorSystemDefault);
460#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
461 __kCFAllocatorSystemDefault._context.info = (kCFUseCollectableAllocator ? objc_collectableZone() : malloc_default_zone());
462#endif
463 __kCFAllocatorSystemDefault._allocator = kCFAllocatorSystemDefault;
464
465 _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorMalloc);
466 __kCFAllocatorMalloc._allocator = kCFAllocatorSystemDefault;
467
468#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
469 _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorMallocZone);
470 __kCFAllocatorMallocZone._allocator = kCFAllocatorSystemDefault;
471 __kCFAllocatorMallocZone._context.info = malloc_default_zone();
472#endif
473
474 _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorNull);
475 __kCFAllocatorNull._allocator = kCFAllocatorSystemDefault;
476 });
477}
478
479CFTypeID CFAllocatorGetTypeID(void) {
480 return __kCFAllocatorTypeID;
481}
482
483CFAllocatorRef CFAllocatorGetDefault(void) {
484 return __CFGetDefaultAllocator();
485}
486
487void CFAllocatorSetDefault(CFAllocatorRef allocator) {
488 CFAllocatorRef current = __CFGetDefaultAllocator();
489#if defined(DEBUG)
490 if (NULL != allocator) {
491 __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
492 }
493#endif
494#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
495 if (allocator && allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
496 return; // require allocator to this function to be an allocator
497 }
498#endif
499 if (NULL != allocator && allocator != current) {
500 if (current) CFRelease(current);
501 CFRetain(allocator);
502 // We retain an extra time so that anything set as the default
503 // allocator never goes away.
504 CFRetain(allocator);
505 _CFSetTSD(__CFTSDKeyAllocator, (void *)allocator, NULL);
506 }
507}
508
509static CFAllocatorRef __CFAllocatorCreate(CFAllocatorRef allocator, CFAllocatorContext *context) {
510 struct __CFAllocator *memory = NULL;
511 CFAllocatorRetainCallBack retainFunc;
512 CFAllocatorAllocateCallBack allocateFunc;
513 void *retainedInfo;
514#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
515 if (allocator && kCFAllocatorUseContext != allocator && allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
516 return NULL; // require allocator to this function to be an allocator
517 }
518#endif
519 retainFunc = context->retain;
520 FAULT_CALLBACK((void **)&retainFunc);
521 allocateFunc = context->allocate;
522 FAULT_CALLBACK((void **)&allocateFunc);
523 if (NULL != retainFunc) {
524 retainedInfo = (void *)INVOKE_CALLBACK1(retainFunc, context->info);
525 } else {
526 retainedInfo = context->info;
527 }
528 // We don't use _CFRuntimeCreateInstance()
529 if (kCFAllocatorUseContext == allocator) {
530 memory = NULL;
531 if (allocateFunc) {
532 memory = (struct __CFAllocator *)INVOKE_CALLBACK3(allocateFunc, sizeof(struct __CFAllocator), 0, retainedInfo);
533 }
534 if (NULL == memory) {
535 return NULL;
536 }
537 } else {
538 allocator = (NULL == allocator) ? __CFGetDefaultAllocator() : allocator;
539 memory = (struct __CFAllocator *)CFAllocatorAllocate(allocator, sizeof(struct __CFAllocator), __kCFAllocatorGCObjectMemory);
540 if (NULL == memory) {
541 return NULL;
542 }
543 if (__CFOASafe) __CFSetLastAllocationEventName(memory, "CFAllocator");
544 }
545 memset(memory, 0, sizeof(CFRuntimeBase));
546#if __LP64__
547 memory->_base._rc = 1;
548#else
549 memory->_base._cfinfo[CF_RC_BITS] = 1;
550#endif
551 memory->_base._cfinfo[CF_INFO_BITS] = 0;
552 _CFAllocatorSetInstanceTypeIDAndIsa(memory);
553#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
554 memory->size = __CFAllocatorCustomSize;
555 memory->malloc = __CFAllocatorCustomMalloc;
556 memory->calloc = __CFAllocatorCustomCalloc;
557 memory->valloc = __CFAllocatorCustomValloc;
558 memory->free = __CFAllocatorCustomFree;
559 memory->realloc = __CFAllocatorCustomRealloc;
560 memory->destroy = __CFAllocatorCustomDestroy;
561 memory->zone_name = "Custom CFAllocator";
562 memory->batch_malloc = NULL;
563 memory->batch_free = NULL;
564 memory->introspect = &__CFAllocatorZoneIntrospect;
565 memory->version = 6;
566 memory->memalign = NULL;
567 memory->free_definite_size = NULL;
568#endif
569 memory->_allocator = allocator;
570 memory->_context.version = context->version;
571 memory->_context.info = retainedInfo;
572 memory->_context.retain = retainFunc;
573 memory->_context.release = context->release;
574 FAULT_CALLBACK((void **)&(memory->_context.release));
575 memory->_context.copyDescription = context->copyDescription;
576 FAULT_CALLBACK((void **)&(memory->_context.copyDescription));
577 memory->_context.allocate = allocateFunc;
578 memory->_context.reallocate = context->reallocate;
579 FAULT_CALLBACK((void **)&(memory->_context.reallocate));
580 memory->_context.deallocate = context->deallocate;
581 FAULT_CALLBACK((void **)&(memory->_context.deallocate));
582 memory->_context.preferredSize = context->preferredSize;
583 FAULT_CALLBACK((void **)&(memory->_context.preferredSize));
584
585 return memory;
586}
587
588CFAllocatorRef CFAllocatorCreate(CFAllocatorRef allocator, CFAllocatorContext *context) {
589 return __CFAllocatorCreate(allocator, context);
590}
591
592void *CFAllocatorAllocate(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint) {
593 CFAllocatorAllocateCallBack allocateFunc;
594 void *newptr = NULL;
595
596 Boolean initialRefcountOne = true;
597 if (NULL == allocator) {
598 allocator = __CFGetDefaultAllocator();
599 }
600
601#if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
602 if (allocator->_base._cfisa == __CFISAForTypeID(__kCFAllocatorTypeID)) {
603 __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
604 }
605#else
606 __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
607#endif
608 if (0 == size) return NULL;
609#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
610 if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
611 return malloc_zone_malloc((malloc_zone_t *)allocator, size);
612 }
613#endif
614 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
615 newptr = auto_zone_allocate_object((auto_zone_t*)allocator->_context.info, size, CF_GET_GC_MEMORY_TYPE(hint), initialRefcountOne, false);
616 } else {
617 newptr = NULL;
618 allocateFunc = __CFAllocatorGetAllocateFunction(&allocator->_context);
619 if (allocateFunc) {
620 newptr = (void *)INVOKE_CALLBACK3(allocateFunc, size, hint, allocator->_context.info);
621 }
622 }
623 return newptr;
624}
625
626void *CFAllocatorReallocate(CFAllocatorRef allocator, void *ptr, CFIndex newsize, CFOptionFlags hint) {
627 CFAllocatorAllocateCallBack allocateFunc;
628 CFAllocatorReallocateCallBack reallocateFunc;
629 CFAllocatorDeallocateCallBack deallocateFunc;
630 void *newptr;
631
632 if (0) {
633 allocator = kCFAllocatorSystemDefault;
634 } else if (0) {
635 allocator = kCFUseCollectableAllocator ? kCFAllocatorSystemDefault : __CFGetDefaultAllocator();
636 } else if (NULL == allocator) {
637 allocator = __CFGetDefaultAllocator();
638 }
639
640#if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
641 if (allocator->_base._cfisa == __CFISAForTypeID(__kCFAllocatorTypeID)) {
642 __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
643 }
644#else
645 __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
646#endif
647 if (NULL == ptr && 0 < newsize) {
648#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
649 if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
650 return malloc_zone_malloc((malloc_zone_t *)allocator, newsize);
651 }
652#endif
653 newptr = NULL;
654 allocateFunc = __CFAllocatorGetAllocateFunction(&allocator->_context);
655 if (allocateFunc) {
656 newptr = (void *)INVOKE_CALLBACK3(allocateFunc, newsize, hint, allocator->_context.info);
657 }
658 return newptr;
659 }
660 if (NULL != ptr && 0 == newsize) {
661#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
662 if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
663#if defined(DEBUG)
664 size_t size = malloc_size(ptr);
665 if (size) memset(ptr, 0xCC, size);
666#endif
667 malloc_zone_free((malloc_zone_t *)allocator, ptr);
668 return NULL;
669 }
670#endif
671 deallocateFunc = __CFAllocatorGetDeallocateFunction(&allocator->_context);
672 if (NULL != deallocateFunc) {
673 INVOKE_CALLBACK2(deallocateFunc, ptr, allocator->_context.info);
674 }
675 return NULL;
676 }
677 if (NULL == ptr && 0 == newsize) return NULL;
678#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
679 if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
680 return malloc_zone_realloc((malloc_zone_t *)allocator, ptr, newsize);
681 }
682#endif
683 reallocateFunc = __CFAllocatorGetReallocateFunction(&allocator->_context);
684 if (NULL == reallocateFunc) return NULL;
685 newptr = (void *)INVOKE_CALLBACK4(reallocateFunc, ptr, newsize, hint, allocator->_context.info);
686 return newptr;
687}
688
689void CFAllocatorDeallocate(CFAllocatorRef allocator, void *ptr) {
690 CFAllocatorDeallocateCallBack deallocateFunc;
691
692 if (0) {
693 allocator = kCFAllocatorSystemDefault;
694 } else if (0) {
695 allocator = kCFUseCollectableAllocator ? kCFAllocatorSystemDefault : __CFGetDefaultAllocator();
696 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) return;
697 } else if (NULL == allocator) {
698 allocator = __CFGetDefaultAllocator();
699 }
700
701#if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
702 if (allocator->_base._cfisa == __CFISAForTypeID(__kCFAllocatorTypeID)) {
703 __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
704 }
705#else
706 __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
707#endif
708#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
709 if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
710#if defined(DEBUG)
711 size_t size = malloc_size(ptr);
712 if (size) memset(ptr, 0xCC, size);
713#endif
714 return malloc_zone_free((malloc_zone_t *)allocator, ptr);
715 }
716#endif
717 deallocateFunc = __CFAllocatorGetDeallocateFunction(&allocator->_context);
718 if (NULL != ptr && NULL != deallocateFunc) {
719 INVOKE_CALLBACK2(deallocateFunc, ptr, allocator->_context.info);
720 }
721}
722
723CFIndex CFAllocatorGetPreferredSizeForSize(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint) {
724 CFAllocatorPreferredSizeCallBack prefFunc;
725 CFIndex newsize = 0;
726
727 if (0) {
728 allocator = kCFAllocatorSystemDefault;
729 } else if (0) {
730 allocator = kCFUseCollectableAllocator ? kCFAllocatorSystemDefault : __CFGetDefaultAllocator();
731 } else if (NULL == allocator) {
732 allocator = __CFGetDefaultAllocator();
733 }
734
735#if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
736 if (allocator->_base._cfisa == __CFISAForTypeID(__kCFAllocatorTypeID)) {
737 __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
738 }
739#else
740 __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
741#endif
742#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
743 if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
744 return malloc_good_size(size);
745 }
746#endif
747 prefFunc = __CFAllocatorGetPreferredSizeFunction(&allocator->_context);
748 if (0 < size && NULL != prefFunc) {
749 newsize = (CFIndex)(INVOKE_CALLBACK3(prefFunc, size, hint, allocator->_context.info));
750 }
751 if (newsize < size) newsize = size;
752 return newsize;
753}
754
755void CFAllocatorGetContext(CFAllocatorRef allocator, CFAllocatorContext *context) {
756 if (0) {
757 allocator = kCFAllocatorSystemDefault;
758 } else if (0) {
759 allocator = kCFUseCollectableAllocator ? kCFAllocatorSystemDefault : __CFGetDefaultAllocator();
760 } else if (NULL == allocator) {
761 allocator = __CFGetDefaultAllocator();
762 }
763
764#if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
765 if (allocator->_base._cfisa == __CFISAForTypeID(__kCFAllocatorTypeID)) {
766 __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
767 }
768#else
769 __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
770#endif
771 CFAssert1(0 == context->version, __kCFLogAssertion, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__);
772#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
773 if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
774 return;
775 }
776#endif
777 context->version = 0;
778 context->info = allocator->_context.info;
779 context->retain = __CFAllocatorGetRetainFunction(&allocator->_context);
780 context->release = __CFAllocatorGetReleaseFunction(&allocator->_context);
781 context->copyDescription = __CFAllocatorGetCopyDescriptionFunction(&allocator->_context);
782 context->allocate = __CFAllocatorGetAllocateFunction(&allocator->_context);
783 context->reallocate = __CFAllocatorGetReallocateFunction(&allocator->_context);
784 context->deallocate = __CFAllocatorGetDeallocateFunction(&allocator->_context);
785 context->preferredSize = __CFAllocatorGetPreferredSizeFunction(&allocator->_context);
786}
787
788CF_PRIVATE void *_CFAllocatorAllocateGC(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint)
789{
790 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator))
791 return auto_zone_allocate_object((auto_zone_t*)kCFAllocatorSystemDefault->_context.info, size, CF_GET_GC_MEMORY_TYPE(hint), false, false);
792 else
793 return CFAllocatorAllocate(allocator, size, hint);
794}
795
796CF_PRIVATE void *_CFAllocatorReallocateGC(CFAllocatorRef allocator, void *ptr, CFIndex newsize, CFOptionFlags hint)
797{
798 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
799 if (ptr && (newsize == 0)) {
800 return NULL; // equivalent to _CFAllocatorDeallocateGC.
801 }
802 if (ptr == NULL) {
803 return auto_zone_allocate_object((auto_zone_t*)kCFAllocatorSystemDefault->_context.info, newsize, CF_GET_GC_MEMORY_TYPE(hint), false, false); // eq. to _CFAllocator
804 }
805 }
806 // otherwise, auto_realloc() now preserves layout type and refCount.
807 return CFAllocatorReallocate(allocator, ptr, newsize, hint);
808}
809
810CF_PRIVATE void _CFAllocatorDeallocateGC(CFAllocatorRef allocator, void *ptr)
811{
812 // when running GC, don't deallocate.
813 if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) CFAllocatorDeallocate(allocator, ptr);
814}
815
816// -------- -------- -------- -------- -------- -------- -------- --------
817
818
819CFRange __CFRangeMake(CFIndex loc, CFIndex len) {
820 CFRange range;
821 range.location = loc;
822 range.length = len;
823 return range;
824}
825
826
827struct __CFNull {
828 CFRuntimeBase _base;
829};
830
831static struct __CFNull __kCFNull = {
832 INIT_CFRUNTIME_BASE()
833};
834const CFNullRef kCFNull = &__kCFNull;
835
836static CFStringRef __CFNullCopyDescription(CFTypeRef cf) {
837 return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFNull %p [%p]>"), cf, CFGetAllocator(cf));
838}
839
840static CFStringRef __CFNullCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) {
841 return (CFStringRef)CFRetain(CFSTR("null"));
842}
843
844static void __CFNullDeallocate(CFTypeRef cf) {
845 CFAssert(false, __kCFLogAssertion, "Deallocated CFNull!");
846}
847
848static CFTypeID __kCFNullTypeID = _kCFRuntimeNotATypeID;
849
850static const CFRuntimeClass __CFNullClass = {
851 0,
852 "CFNull",
853 NULL, // init
854 NULL, // copy
855 __CFNullDeallocate,
856 NULL,
857 NULL,
858 __CFNullCopyFormattingDescription,
859 __CFNullCopyDescription
860};
861
862CFTypeID CFNullGetTypeID(void) {
863 static dispatch_once_t initOnce;
864 dispatch_once(&initOnce, ^{
865 __kCFNullTypeID = _CFRuntimeRegisterClass(&__CFNullClass); // initOnce covered
866 _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFNull, __kCFNullTypeID);
867 });
868 return __kCFNullTypeID;
869}
870
871void CFCollection_non_gc_storage_error(void) { }
872
873
874void _CFRuntimeSetCFMPresent(void *addr) {
875}
876
877
878// void __HALT(void);
879
880/* Keep this assembly at the bottom of the source file! */
881
882
883extern void __HALT() {
884#if defined(__ppc__)
885 __asm__("trap");
886#elif defined(__i386__) || defined(__x86_64__)
887#if defined(_MSC_VER)
888 __asm int 3;
889#else
890 __asm__("int3");
891#endif
892#endif
893}
894
895