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