1/* 2 * Copyright (c) 2011 Apple Inc. All rights reserved. 3 * 4 * @APPLE_APACHE_LICENSE_HEADER_START@ 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 * @APPLE_APACHE_LICENSE_HEADER_END@ 19 */ 20/* 21 auto_zone.h 22 Automatic Garbage Collection. 23 Copyright (c) 2002-2011 Apple Inc. All rights reserved. 24 */ 25 26#ifndef __AUTO_ZONE__ 27#define __AUTO_ZONE__ 28 29#include <stdint.h> 30#include <stdio.h> 31#include <sys/types.h> 32#include <malloc/malloc.h> 33#include <Availability.h> 34#include <AvailabilityMacros.h> 35#include <TargetConditionals.h> 36 37#include <dispatch/dispatch.h> 38 39#define AUTO_EXPORT extern __attribute__((visibility("default"))) 40 41__BEGIN_DECLS 42 43typedef malloc_zone_t auto_zone_t; 44 // an auto zone carries a little more state but can be cast into a malloc_zone_t 45 46AUTO_EXPORT auto_zone_t *auto_zone_create(const char *name) 47 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 48 // create an garbage collected zone. Can be (theoretically) done more than once. 49 // memory can be allocated by malloc_zone_malloc(result, size) 50 // by default, this memory must be malloc_zone_free(result, ptr) as well (or generic free()) 51 52AUTO_EXPORT struct malloc_introspection_t auto_zone_introspection() 53 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 54 // access the zone introspection functions independent of any particular auto zone instance. 55 // this is used by tools to be able to introspect a zone in another process. 56 // the introspection functions returned are required to do version checking on the zone. 57 58#define AUTO_RETAINED_BLOCK_TYPE 0x100 /* zone enumerator returns only blocks with nonzero retain count */ 59 60/********* External (Global) Use counting ************/ 61 62AUTO_EXPORT void auto_zone_retain(auto_zone_t *zone, void *ptr) 63 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 64AUTO_EXPORT unsigned int auto_zone_release(auto_zone_t *zone, void *ptr) 65 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 66AUTO_EXPORT unsigned int auto_zone_retain_count(auto_zone_t *zone, const void *ptr) 67 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 68 // All pointer in the auto zone have an explicit retain count 69 // Objects will not be collected when the retain count is non-zero 70 71/********* Object information ************/ 72 73AUTO_EXPORT const void *auto_zone_base_pointer(auto_zone_t *zone, const void *ptr) 74 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 75 // return base of interior pointer (or NULL). 76AUTO_EXPORT boolean_t auto_zone_is_valid_pointer(auto_zone_t *zone, const void *ptr) 77 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 78 // is this a pointer to the base of an allocated block? 79AUTO_EXPORT size_t auto_zone_size(auto_zone_t *zone, const void *ptr) 80 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 81 82/********* Write-barrier ************/ 83 84AUTO_EXPORT boolean_t auto_zone_set_write_barrier(auto_zone_t *zone, const void *dest, const void *new_value) 85 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 86 // must be used when an object field/slot in the auto zone is set to another object in the auto zone 87 // returns true if the dest was a valid target whose write-barrier was set 88 89AUTO_EXPORT boolean_t auto_zone_atomicCompareAndSwap(auto_zone_t *zone, void *existingValue, void *newValue, void *volatile *location, boolean_t isGlobal, boolean_t issueBarrier) 90 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 91 // Atomically update a location with a new GC value. These use OSAtomicCompareAndSwapPtr{Barrier} with appropriate write-barrier interlocking logic. 92 93AUTO_EXPORT boolean_t auto_zone_atomicCompareAndSwapPtr(auto_zone_t *zone, void *existingValue, void *newValue, void *volatile *location, boolean_t issueBarrier) 94 __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0); 95 // Atomically update a location with a new GC value. These use OSAtomicCompareAndSwapPtr{Barrier} with appropriate write-barrier interlocking logic. 96 // This version checks location, and if it points into global storage, registers a root. 97 98AUTO_EXPORT void *auto_zone_write_barrier_memmove(auto_zone_t *zone, void *dst, const void *src, size_t size) 99 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 100 // copy content from an arbitrary source area to an arbitrary destination area 101 // marking write barrier if necessary 102 103/********* Read-barrier ************/ 104 105AUTO_EXPORT void *auto_zone_strong_read_barrier(auto_zone_t *zone, void **source) 106 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 107 108/********* Statistics ************/ 109 110typedef uint64_t auto_date_t; 111 112typedef struct { 113 auto_date_t total_duration; 114 auto_date_t scan_duration; 115 auto_date_t enlivening_duration; 116 auto_date_t finalize_duration; 117 auto_date_t reclaim_duration; 118} auto_collection_durations_t; 119 120typedef struct { 121 /* Memory usage */ 122 malloc_statistics_t malloc_statistics; 123 /* GC stats */ 124 // version 0 125 uint32_t version; // set to 1 before calling 126 /* When there is an array, 0 stands for full collection, 1 for generational */ 127 size_t num_collections[2]; 128 boolean_t last_collection_was_generational; 129 size_t bytes_in_use_after_last_collection[2]; 130 size_t bytes_allocated_after_last_collection[2]; 131 size_t bytes_freed_during_last_collection[2]; 132 // durations 133 auto_collection_durations_t total[2]; // running total of each field 134 auto_collection_durations_t last[2]; // most recent result 135 auto_collection_durations_t maximum[2]; // on a per item basis, the max. Thus, total != scan + finalize ... 136 // version 1 additions 137 size_t thread_collections_total; 138 size_t thread_blocks_recovered_total; 139 size_t thread_bytes_recovered_total; 140} auto_statistics_t; 141 142AUTO_EXPORT void auto_zone_statistics(auto_zone_t *zone, auto_statistics_t *stats) 143 __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_5,__MAC_10_7, __IPHONE_5_0,__IPHONE_5_0); 144 // set version to 0 145 146/********* Garbage Collection ************/ 147 148enum { 149 AUTO_COLLECT_RATIO_COLLECTION = (0 << 0), // run generational or full depending on applying AUTO_COLLECTION_RATIO 150 AUTO_COLLECT_GENERATIONAL_COLLECTION = (1 << 0), // collect young objects. Internal only. 151 AUTO_COLLECT_FULL_COLLECTION = (2 << 0), // collect entire heap. Internal only. 152 AUTO_COLLECT_EXHAUSTIVE_COLLECTION = (3 << 0), // run full collections until object count stabilizes. 153 AUTO_COLLECT_SYNCHRONOUS = (1 << 2), // block caller until scanning is finished. 154 AUTO_COLLECT_IF_NEEDED = (1 << 3), // only collect if AUTO_COLLECTION_THRESHOLD exceeded. 155}; 156typedef uint32_t auto_collection_mode_t; 157 158enum { 159 AUTO_LOG_COLLECTIONS = (1 << 1), // log block statistics whenever a collection occurs 160 AUTO_LOG_TIMINGS = (1 << 2), // log timing data whenever a collection occurs 161 AUTO_LOG_REGIONS = (1 << 4), // log whenever a new region is allocated 162 AUTO_LOG_UNUSUAL = (1 << 5), // log unusual circumstances 163 AUTO_LOG_WEAK = (1 << 6), // log weak reference manipulation 164 AUTO_LOG_ALL = (~0u), 165 AUTO_LOG_NONE = 0 166}; 167typedef uint32_t auto_log_mask_t; 168 169enum { 170 AUTO_HEAP_HOLES_SHRINKING = 1, // total size of holes is approaching zero 171 AUTO_HEAP_HOLES_EXHAUSTED = 2, // all holes exhausted, will use hitherto unused memory in "subzone" 172 AUTO_HEAP_SUBZONE_EXHAUSTED = 3, // will add subzone 173 AUTO_HEAP_REGION_EXHAUSTED = 4, // no more subzones available, need to add region 174 AUTO_HEAP_ARENA_EXHAUSTED = 5, // arena exhausted. (64-bit only) 175}; 176typedef uint32_t auto_heap_growth_info_t; 177 178typedef struct auto_zone_cursor *auto_zone_cursor_t; 179typedef void (*auto_zone_foreach_object_t) (auto_zone_cursor_t cursor, void (*op) (void *ptr, void *data), void* data); 180 181typedef struct { 182 uint32_t version; // sizeof(auto_collection_control_t) 183 void (*batch_invalidate) (auto_zone_t *zone, auto_zone_foreach_object_t foreach, auto_zone_cursor_t cursor, size_t cursor_size); 184 // After unreached objects are found, collector calls this routine with internal context. 185 // Typically, one enters a try block to call back into the collector with a function pointer to be used to 186 // invalidate each object. This amortizes the cost of the try block as well as allows the collector to use 187 // efficient contexts. 188 void (*resurrect) (auto_zone_t *zone, void *ptr); 189 // Objects on the garbage list may be assigned into live objects in an attempted resurrection. This is not allowed. 190 // This function, if supplied, is called for these objects to turn them into zombies. The zombies may well hold 191 // pointers to other objects on the garbage list. No attempt is made to preserved these objects beyond this collection. 192 const unsigned char* (*layout_for_address)(auto_zone_t *zone, void *ptr); 193 // The collector assumes that the first word of every "object" is a class pointer. 194 // For each class pointer discovered this function is called to return a layout, or NULL 195 // if the object should be scanned conservatively. 196 // The layout format is nibble pairs {skipcount, scancount} XXX 197 const unsigned char* (*weak_layout_for_address)(auto_zone_t *zone, void *ptr); 198 // called once for each allocation encountered for which we don't know the weak layout 199 // the callee returns a weak layout for the allocation or NULL if the allocation has no weak references. 200 char* (*name_for_address) (auto_zone_t *zone, vm_address_t base, vm_address_t offset); 201 // if supplied, is used during logging for errors such as resurrections 202 auto_log_mask_t log; 203 // set to auto_log_mask_t bits as desired 204 boolean_t disable_generational; 205 // if true, ignores requests to do generational GC. 206 boolean_t malloc_stack_logging; 207 // if true, logs allocations for malloc stack logging. Automatically set if MallocStackLogging{NoCompact} is set 208 void (*scan_external_callout)(void *context, void (*scanner)(void *context, void *start, void *end)) DEPRECATED_ATTRIBUTE; 209 // no longer used 210 211 void (*will_grow)(auto_zone_t *zone, auto_heap_growth_info_t) DEPRECATED_ATTRIBUTE; 212 // no longer used 213 214 size_t collection_threshold; 215 // if_needed threshold: collector will initiate a collection after this number of bytes is allocated. 216 size_t full_vs_gen_frequency; 217 // after full_vs_gen_frequency generational collections, a full collection will occur, if the if_needed threshold exceeded 218 const char* (*name_for_object) (auto_zone_t *zone, void *object); 219 // provides a type name for an AUTO_OBJECT 220} auto_collection_control_t; 221 222AUTO_EXPORT auto_collection_control_t *auto_collection_parameters(auto_zone_t *zone) 223 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 224 // FIXME: API is to get the control struct and slam it 225 // sets a parameter that decides when callback gets called 226 227AUTO_EXPORT void auto_collector_disable(auto_zone_t *zone) 228 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 229AUTO_EXPORT void auto_collector_reenable(auto_zone_t *zone) 230 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 231 // these two functions turn off/on the collector 232 // default is on 233 // use with great care. 234 235AUTO_EXPORT boolean_t auto_zone_is_enabled(auto_zone_t *zone) 236 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 237AUTO_EXPORT boolean_t auto_zone_is_collecting(auto_zone_t *zone) 238 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 239 240AUTO_EXPORT void auto_collect(auto_zone_t *zone, auto_collection_mode_t mode, void *collection_context) 241 __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_5,__MAC_10_7, __IPHONE_5_0,__IPHONE_5_0); 242 // deprecated, use auto_zone_collect() instead 243 244AUTO_EXPORT void auto_collect_multithreaded(auto_zone_t *zone) 245 __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_5,__MAC_10_7, __IPHONE_5_0,__IPHONE_5_0); 246 // deprecated 247 248 249// Options to auto_zone_collect(). 250enum { 251 /* 252 Request a collection with no options. This produces an advisory collection request which 253 allows the collector to choose what collection is performed (or none) based on its internal 254 heuristics. This is generally the only option that should be used in production code. 255 All other options are intended primarily to support debugging and unit tests and may change 256 meaning without notice. 257 */ 258 AUTO_ZONE_COLLECT_NO_OPTIONS = 0, 259 260 // The low order nibble specifies a request for a global heap collection. 261 // Note that the ordinal value is significant. Higher numbered collection modes can override lower numbered. 262 AUTO_ZONE_COLLECT_RATIO_COLLECTION = 1, // requests either a generational or a full collection, based on memory use heuristics. 263 AUTO_ZONE_COLLECT_GENERATIONAL_COLLECTION = 2, // requests a generational heap collection. 264 AUTO_ZONE_COLLECT_FULL_COLLECTION = 3, // requests a full heap collection. 265 AUTO_ZONE_COLLECT_EXHAUSTIVE_COLLECTION = 4, // requests an exhaustive heap collection. 266 267 AUTO_ZONE_COLLECT_GLOBAL_MODE_MAX = AUTO_ZONE_COLLECT_EXHAUSTIVE_COLLECTION, // the highest numbered global mode 268 AUTO_ZONE_COLLECT_GLOBAL_MODE_COUNT = AUTO_ZONE_COLLECT_EXHAUSTIVE_COLLECTION+1, // the highest numbered global mode 269 AUTO_ZONE_COLLECT_GLOBAL_COLLECTION_MODE_MASK = 0xf, 270 271 272 // These bits requests a local collections be performed on the calling thread. It is permitted to request both a local collection and a global collection, in which case both will be performed. 273 274 AUTO_ZONE_COLLECT_LOCAL_COLLECTION = (1<<8), // perform a normal thread local collection 275 276 AUTO_ZONE_COLLECT_COALESCE = (1<<15), // allows the request to be skipped if a collection is in progress 277}; 278 279/* 280 auto_zone_collect() is the entry point to request a collection. 281 282 Normally AUTO_ZONE_COLLECT_NO_OPTIONS should be passed for options. This indicates the call is an advisory 283 collection request and the collector is free to perform any action it deems fit (including none). This is 284 the only option that should be used in shipping production code. The other options provide fine grained control of 285 the collector intended for debugging and unit tests. Misuse of these options can degrade performance. 286 */ 287typedef intptr_t auto_zone_options_t; 288AUTO_EXPORT void auto_zone_collect(auto_zone_t *zone, auto_zone_options_t options) 289 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 290#ifdef __BLOCKS__ 291AUTO_EXPORT void auto_zone_collect_and_notify(auto_zone_t *zone, auto_zone_options_t options, dispatch_queue_t callback_queue, dispatch_block_t completion_callback) 292 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 293#endif 294 295/* 296 auto_zone_compact() is the entry point to request a stop-the-world compaction of the heap. This can only be called from binaries 297 which are marked by the linker (see <rdar://problem/7421695>) as supporting compaction. Currently there are no options to control 298 compaction, but you can pass a queue/block callback pair that will be invoked after compaction finishes. 299 */ 300 301enum { 302 AUTO_ZONE_COMPACT_NO_OPTIONS = 0, 303 AUTO_ZONE_COMPACT_IF_IDLE = 1, /* primes compaction to start after delay, if no dispatch threads intervene. */ 304 AUTO_ZONE_COMPACT_ANALYZE = 2, /* runs a compaction analysis to file specified by environment variable. */ 305}; 306 307typedef uintptr_t auto_zone_compact_options_t; 308 309#ifdef __BLOCKS__ 310AUTO_EXPORT void auto_zone_compact(auto_zone_t *zone, auto_zone_compact_options_t options, dispatch_queue_t callback_queue, dispatch_block_t completion_callback) 311 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 312#endif 313 314/* 315 Compaction is enabled by default. The client runtime should call auto_zone_disable_compaction() when it detects that code that 316 is incompatible with compaction has been loaded. This is safe to call immediately after auto_zone_create(). 317 */ 318AUTO_EXPORT void auto_zone_disable_compaction(auto_zone_t *zone) 319 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 320 321/* 322 External resource tracking. 323 324 The garbage collector tracks use of collectable memory. But it may be necessary to trigger garbage collections 325 based on use of other resources not tracked by the garbage collector, such as file descriptors. The garbage 326 collector provides this interface to register other resources tracking systems so the collector can query 327 if collection is needed. The garbage collector will periodically call all registered should_collect() blocks 328 and if any of them return true a collection cycle will execute. (However, the collector stops querying 329 external resource trackers once it has determined that a collection is necessary. In many cases the collector 330 will collect due to memory use without querying any external resource trackers at all.) 331 332 Resource tracking implementations should take care to avoid running collections continuously based on high 333 resource use when no resources are recovered. One strategy is to track resources allocated since the last 334 triggered collection instead of a total allocation count. 335 */ 336 337/* 338 Register should_collect() as an external resource tracker. The string passed in description is used 339 as a descriptive name for the resource tracker. When an external resource tracker triggers a collection the 340 description string appears in the log if AUTO_LOG_COLLECTIONS is enabled. The description string is copied. 341 */ 342#ifdef __BLOCKS__ 343AUTO_EXPORT void auto_zone_register_resource_tracker(auto_zone_t *zone, const char *description, boolean_t (^should_collect)(void)) 344 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 345#endif 346 347/* 348 Unregister a should_collect() block that was previously registered with auto_zone_register_resource_tracker(). 349 The garbage collector will no longer query the resource tracker. 350 */ 351AUTO_EXPORT void auto_zone_unregister_resource_tracker(auto_zone_t *zone, const char *description) 352 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 353 354 355/* 356 auto_zone_reap_all_local_blocks() will immediately finalize and reclaim all blocks which are thread local to the calling thread. 357 No scanning or other liveness analysis will be performed. This function can be called as an optimization in the very specific 358 case where it is known that the stack cannot be rooting any blocks, such as a pthread event loop. (Note that this cannot be called 359 from a thread created by NSThread.) 360 */ 361AUTO_EXPORT void auto_zone_reap_all_local_blocks(auto_zone_t *zone) 362 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 363 364// Block Memory Type Flags 365// ======================= 366// Blocks of memory allocated by auto_zone_allocate_object() are broadly classified as scanned/unscanned 367// and object/non-object. When objects become garbage, they are finalized by calling the batch_invalidate() callback. 368// For scanned objects, the collector uses the layout_for_address callback, to obtain a layout map that describes which 369// pointer sized words should be scanned, and which should be ignored. Scanned objects may also contain weak references 370// which are created via auto_assign_weak_reference(). The weak_layout_for_address callback is used to automatically 371// unregister non-NULL weak references in weak_unregister_with_layout(). Finally, the pointers_only bit applies only for 372// scanned memory and indicates that all otherwise unspecified fields are pointers, the most interesting consequence is that 373// they can be relocated during compaction. 374// 375// These flags are represented by auto_memory_type_t. see the comments below for the legal flag combinations. Once allocated, 376// SPI is provided to change the bits in only proscribed ways; to turn off "object" treatment; to turn off scanning; 377// to turn on all-pointers. 378 379enum { 380 AUTO_TYPE_UNKNOWN = -1, // this is an error value 381 // memory type bits. 382 AUTO_UNSCANNED = (1 << 0), 383 AUTO_OBJECT = (1 << 1), 384 AUTO_POINTERS_ONLY = (1 << 2), 385 // allowed combinations of flags. 386 AUTO_MEMORY_SCANNED = !AUTO_UNSCANNED, // conservatively scanned memory 387 AUTO_MEMORY_UNSCANNED = AUTO_UNSCANNED, // unscanned memory (bits) 388 AUTO_MEMORY_ALL_POINTERS = AUTO_POINTERS_ONLY, // scanned array of pointers 389 AUTO_MEMORY_ALL_WEAK_POINTERS = (AUTO_UNSCANNED | AUTO_POINTERS_ONLY), // unscanned, weak array of pointers 390 AUTO_OBJECT_SCANNED = AUTO_OBJECT, // object memory, exactly scanned with layout maps, conservatively scanned remainder, will be finalized 391 AUTO_OBJECT_UNSCANNED = AUTO_OBJECT | AUTO_UNSCANNED, // unscanned object memory, will be finalized 392 AUTO_OBJECT_ALL_POINTERS = AUTO_OBJECT | AUTO_POINTERS_ONLY // object memory, exactly scanned with layout maps, all-pointers scanned remainder, will be finalized 393}; 394typedef int32_t auto_memory_type_t; 395 396AUTO_EXPORT auto_memory_type_t auto_zone_get_layout_type(auto_zone_t *zone, void *ptr) 397 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 398 399AUTO_EXPORT void* auto_zone_allocate_object(auto_zone_t *zone, size_t size, auto_memory_type_t type, boolean_t initial_refcount_to_one, boolean_t clear) 400 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 401 402/* Batch allocator. Returns number of blocks allocated, which may be 0. */ 403/* All blocks have the given memory type and initial reference count, and all blocks are zeroed. */ 404AUTO_EXPORT unsigned auto_zone_batch_allocate(auto_zone_t *zone, size_t size, auto_memory_type_t type, boolean_t initial_refcount_to_one, boolean_t clear, void **results, unsigned num_requested) 405 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 406 407// Create copy of AUTO_MEMORY object preserving "scanned" attribute 408// If not auto memory then create unscanned memory copy 409AUTO_EXPORT void *auto_zone_create_copy(auto_zone_t *zone, void *ptr) 410 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 411 412 413AUTO_EXPORT void auto_zone_register_thread(auto_zone_t *zone) 414 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 415 416AUTO_EXPORT void auto_zone_unregister_thread(auto_zone_t *zone) 417 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 418 419AUTO_EXPORT void auto_zone_assert_thread_registered(auto_zone_t *zone) 420 __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0); 421 422AUTO_EXPORT void auto_zone_register_datasegment(auto_zone_t *zone, void *address, size_t size) 423 __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0); 424AUTO_EXPORT void auto_zone_unregister_datasegment(auto_zone_t *zone, void *address, size_t size) 425 __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0); 426 427 428// Weak references 429 430// The collector maintains a weak reference system. 431// Essentially, locations in which references are stored are registered along with the reference itself. 432// The location should not be within scanned GC memory. 433// After a collection, before finalization, all registered locations are examined and any containing references to 434// newly discovered garbage will be "zeroed" and the registration cancelled. 435// 436// Reading values from locations must be done through the weak read function because there is a race with such 437// reads and the collector having just determined that that value read is in fact otherwise garbage. 438// 439// The address of a callback block may be supplied optionally. If supplied, if the location is zeroed, the callback 440// block is queued to be called later with the arguments supplied in the callback block. The same callback block both 441// can and should be used as an aggregation point. A table of weak locations could supply each registration with the 442// same pointer to a callback block that will call that table if items are zerod. The callbacks are made before 443// finalization. Note that only thread-safe operations may be performed by this callback. 444// 445// It is important to cancel all registrations before deallocating the memory containing locations or callback blocks. 446// Cancellation is done by calling the registration function with a NULL "reference" parameter for that location. 447 448#if defined(AUTO_USE_NEW_WEAK_CALLBACK) 449typedef struct new_auto_weak_callback_block auto_weak_callback_block_t; 450#else 451typedef struct old_auto_weak_callback_block auto_weak_callback_block_t; 452#endif 453 454struct new_auto_weak_callback_block { 455 void *isa; // provides layout for exact scanning. 456 auto_weak_callback_block_t *next; // must be set to zero before first use. 457 void (*callback_function)(void *__strong target); 458 void *__strong target; 459}; 460 461struct old_auto_weak_callback_block { 462 auto_weak_callback_block_t *next; // must be set to zero before first use. 463 void (*callback_function)(void *arg1, void *arg2); 464 void *arg1; 465 void *arg2; 466} DEPRECATED_ATTRIBUTE; 467 468AUTO_EXPORT void auto_assign_weak_reference(auto_zone_t *zone, const void *value, const void **location, auto_weak_callback_block_t *block) 469 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 470 471// Read a weak-reference, informing the collector that it is now strongly referenced. 472AUTO_EXPORT void* auto_read_weak_reference(auto_zone_t *zone, void **referrer) 473 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 474 475// Compaction notification 476 477// Registers an observer that gets called whenever pointers are updated (by compaction) inside a block. 478// This could be used to trigger rehashing a hash table. The implementation isn't particularly efficient. 479#ifdef __BLOCKS__ 480AUTO_EXPORT void auto_zone_set_compaction_observer(auto_zone_t *zone, void *block, void (^observer) (void)) 481 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 482#endif 483 484// Global references 485 486AUTO_EXPORT void auto_zone_add_root(auto_zone_t *zone, void *address_of_root_ptr, void *value) 487 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 488AUTO_EXPORT void auto_zone_remove_root(auto_zone_t *zone, void *address_of_root_ptr) 489 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 490 491AUTO_EXPORT void auto_zone_root_write_barrier(auto_zone_t *zone, void *address_of_possible_root_ptr, void *value) 492 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 493 494 495// Associative references. 496 497// This informs the collector that an object A wishes to associate one or more secondary objects with object A's lifetime. 498// This can be used to implement GC-safe associations that will neither cause uncollectable cycles, nor suffer the limitations 499// of weak references. 500 501AUTO_EXPORT void auto_zone_set_associative_ref(auto_zone_t *zone, void *object, void *key, void *value) 502 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 503AUTO_EXPORT void *auto_zone_get_associative_ref(auto_zone_t *zone, void *object, void *key) 504 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 505AUTO_EXPORT void auto_zone_erase_associative_refs(auto_zone_t *zone, void *object) 506 __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0); 507 508AUTO_EXPORT size_t auto_zone_get_associative_hash(auto_zone_t *zone, void *object) 509 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 510 511// Enumerates all known object, value pairs associated with the key parameter. Calls the specified block while the 512// assocations table locks are held, therefore adding/removing assocations will likely crash. 513#ifdef __BLOCKS__ 514AUTO_EXPORT void auto_zone_enumerate_associative_refs(auto_zone_t *zone, void *key, boolean_t (^block) (void *object, void *value)) 515 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 516#endif 517 518// Collection Checking 519 520// Collection checking is a debugging tool by which developers can verify that blocks are collecting as expected. 521// When collection checking is enabled the program can report memory blocks to the collector 522// that are expected to collect soon using auto_zone_track_pointer(). 523// The program can detect which of these blocks were not collected by calling auto_zone_enumerate_uncollected(). 524// Pointers that survive more than a few collections can be investigated as leaks. 525// While collection checking is enabled collector performance is degraded and memory use is increased. 526// While most garbage objects are detected and collected in just one collection attempt, there are 527// cases where several collections are required to reclaim a memory block even though it has no references. 528// Note also that a conservative stack reference is never cleared by running more collections. 529 530// Enable/disable collection checking. An "enabled" counter is maintained, so calls should be paried if desired. 531// Disabling collection checking and causes all previously tracked blocks to be unregistered (no longer tracked). 532AUTO_EXPORT boolean_t auto_zone_enable_collection_checking(auto_zone_t *zone) 533 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 534AUTO_EXPORT void auto_zone_disable_collection_checking(auto_zone_t *zone) 535 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 536 537// Inform the collector that the pointer is expected to collect soon. pointer will subsequently be reported by 538// auto_zone_enumerate_uncollected() until it is collected. 539// Note that pointer is still rooted on the stack in the scope where auto_zone_block_should_collect() is called. 540AUTO_EXPORT void auto_zone_track_pointer(auto_zone_t *zone, void *pointer) 541 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 542 543#ifdef __BLOCKS__ 544typedef struct { 545 boolean_t is_object; 546 size_t survived_count; 547} auto_zone_collection_checking_info; 548 549// Typedef for a handler block used to report uncollected memory. The collector provides: 550// pointer - the memory block in question, which was previously passed to auto_zone_track_pointer() 551// info - a pointer to a auto_zone_collection_checking_info struct containing: 552// is_object - true if the block was allocated as an object, false if it is not an object 553// survived_count - a minimum count of collections the block has survived (the actual count may be higher) 554typedef void (^auto_zone_collection_checking_callback_t)(void *pointer, auto_zone_collection_checking_info *info); 555 556// Enumerate the memory blocks that were previously passed to auto_zone_track_pointer(). 557// Any which have not been collected are reported using the callback. 558// The callback may be NULL, in which case the uncollected blocks are simply logged. 559AUTO_EXPORT void auto_zone_enumerate_uncollected(auto_zone_t *zone, auto_zone_collection_checking_callback_t callback) 560 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 561#endif 562 563 564 565/***** SPI ******/ 566 567AUTO_EXPORT boolean_t auto_zone_is_finalized(auto_zone_t *zone, const void *ptr) 568 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 569AUTO_EXPORT void auto_zone_set_nofinalize(auto_zone_t *zone, void *ptr) 570 __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0); 571AUTO_EXPORT void auto_zone_set_unscanned(auto_zone_t *zone, void *ptr) 572 __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0); 573AUTO_EXPORT void auto_zone_set_scan_exactly(auto_zone_t *zone, void *ptr) 574 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 575AUTO_EXPORT void auto_zone_clear_stack(auto_zone_t *zone, unsigned long options) 576 __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0); 577 578// Reference count logging support for ObjectAlloc et. al. 579 580enum { 581 AUTO_RETAIN_EVENT = 14, 582 AUTO_RELEASE_EVENT = 15 583}; 584AUTO_EXPORT void (*__auto_reference_logger)(uint32_t eventtype, void *ptr, uintptr_t data) 585 __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0); 586 587 588// Reference tracing 589 590// referrer_base[referrer_offset] -> referent 591typedef struct 592{ 593 vm_address_t referent; 594 vm_address_t referrer_base; 595 intptr_t referrer_offset; 596} auto_reference_t; 597 598typedef void (*auto_reference_recorder_t)(auto_zone_t *zone, void *ctx, 599 auto_reference_t reference); 600 601AUTO_EXPORT void auto_enumerate_references(auto_zone_t *zone, void *referent, 602 auto_reference_recorder_t callback, 603 void *stack_bottom, void *ctx) 604 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 605 606 607AUTO_EXPORT void **auto_weak_find_first_referrer(auto_zone_t *zone, void **location, unsigned long count) 608 __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_5_0); 609 610 611/************ DEPRECATED ***********/ 612 613AUTO_EXPORT auto_zone_t *auto_zone(void) 614 __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_5,__MAC_10_7, __IPHONE_5_0,__IPHONE_5_0); 615 // returns a pointer to the first garbage collected zone created. 616 617 618/************ DELETED ***********/ 619 620AUTO_EXPORT void auto_zone_stats(void) 621 UNAVAILABLE_ATTRIBUTE; 622AUTO_EXPORT void auto_zone_start_monitor(boolean_t force) 623 UNAVAILABLE_ATTRIBUTE; 624AUTO_EXPORT void auto_zone_set_class_list(int (*get_class_list)(void **buffer, int count)) 625 UNAVAILABLE_ATTRIBUTE; 626AUTO_EXPORT void auto_zone_write_stats(FILE *f) 627 UNAVAILABLE_ATTRIBUTE; 628AUTO_EXPORT char *auto_zone_stats_string() 629 UNAVAILABLE_ATTRIBUTE; 630AUTO_EXPORT double auto_zone_utilization(auto_zone_t *zone) 631 UNAVAILABLE_ATTRIBUTE; 632AUTO_EXPORT unsigned auto_zone_touched_size(auto_zone_t *zone) 633 UNAVAILABLE_ATTRIBUTE; 634 635 636/************* EXPERIMENTAL *********/ 637#ifdef __BLOCKS__ 638 639typedef void (^auto_zone_stack_dump)(const void *base, unsigned long byte_size); 640typedef void (^auto_zone_register_dump)(const void *base, unsigned long byte_size); 641typedef void (^auto_zone_node_dump)(const void *address, unsigned long size, unsigned int layout, unsigned long refcount); 642typedef void (^auto_zone_root_dump)(const void **address); 643typedef void (^auto_zone_weak_dump)(const void **address, const void *item); 644 645// Instruments.app utility; causes significant disruption. 646// This is SPI for Apple's use only. Can and likely will change without regard to 3rd party use. 647AUTO_EXPORT void auto_zone_dump(auto_zone_t *zone, 648 auto_zone_stack_dump stack_dump, 649 auto_zone_register_dump register_dump, 650 auto_zone_node_dump thread_local_node_dump, // unsupported 651 auto_zone_root_dump root_dump, 652 auto_zone_node_dump global_node_dump, 653 auto_zone_weak_dump weak_dump) 654 __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_5,__MAC_10_7, __IPHONE_5_0,__IPHONE_5_0); 655 656// auto_zone_dump() is now deprecated, use auto_zone_visit() instead. 657 658typedef struct { 659 void *begin; 660 void *end; 661} auto_address_range_t; 662 663typedef struct { 664 uint32_t version; // sizeof(auto_zone_visitor_t) 665 void (^visit_thread)(pthread_t thread, auto_address_range_t stack_range, auto_address_range_t registers); 666 void (^visit_node)(const void *address, size_t size, auto_memory_type_t type, uint32_t refcount, boolean_t is_thread_local); 667 void (^visit_root)(const void **address); 668 void (^visit_weak)(const void *value, void *const*location, auto_weak_callback_block_t *callback); 669 void (^visit_association)(const void *object, const void *key, const void *value); 670} auto_zone_visitor_t; 671 672AUTO_EXPORT void auto_zone_visit(auto_zone_t *zone, auto_zone_visitor_t *visitor) 673 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 674 675enum { 676 auto_is_not_auto = 0, 677 auto_is_auto = (1 << 1), // always on for a start of a node 678 auto_is_local = (1 << 2), // is/was node local 679}; 680 681typedef int auto_probe_results_t; 682 683// Instruments.app utility; causes significant disruption. 684// This is SPI for Apple's use only. Can and likely will change without regard to 3rd party use. 685AUTO_EXPORT auto_probe_results_t auto_zone_probe_unlocked(auto_zone_t *zone, void *address) 686 __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0); 687AUTO_EXPORT void auto_zone_scan_exact(auto_zone_t *zone, void *address, void (^callback)(void *base, unsigned long byte_offset, void *candidate)) 688 __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0); 689 690#endif 691 692__END_DECLS 693 694#endif /* __AUTO_ZONE__ */ 695