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_impl_utilities.h
22    Implementation Utilities
23    Copyright (c) 2002-2011 Apple Inc. All rights reserved.
24*/
25
26#ifndef __AUTO_IMPL_UTILITIES__
27#define __AUTO_IMPL_UTILITIES__
28
29#include <stdlib.h>
30#include <stdbool.h>
31#include <stdio.h>
32#include <pthread.h>
33#include <sys/time.h>
34#include <sys/resource.h>
35#include <libkern/OSAtomic.h>
36
37#include <mach/mach_time.h>
38#include <mach/mach_init.h>
39#include <mach/mach_port.h>
40#include <mach/task.h>
41#include <mach/thread_act.h>
42#include <mach/vm_map.h>
43
44#include <AvailabilityMacros.h>
45
46#include "auto_zone.h"
47
48__BEGIN_DECLS
49
50/*********  Debug options   ************/
51
52#define DEBUG_IMPL  1
53#if DEBUG_IMPL
54#define INLINE
55#else
56#define INLINE inline
57#endif
58
59
60/* clang allows always_inline on template functions; gcc does not */
61#if DEBUG_IMPL
62#   define TEMPLATE_INLINE
63#elif __clang__
64#   define TEMPLATE_INLINE __attribute__((always_inline))
65#else
66#   define TEMPLATE_INLINE
67#endif
68
69/*********  Various types   ************/
70
71typedef OSSpinLock spin_lock_t;
72
73/*********  ptr set utilities ************/
74//
75// Pointer sets are used to track the use of allocated objects.
76//
77
78typedef struct ptr_set ptr_set;
79
80extern ptr_set *ptr_set_new();
81extern void ptr_set_dispose(ptr_set *set);
82extern void ptr_set_add(ptr_set *set, void *ptr);
83extern int ptr_set_is_member_no_lock(ptr_set *set, void *ptr);
84extern int ptr_set_is_member(ptr_set *set, void *ptr);
85extern void ptr_set_remove(ptr_set *set, void *ptr);
86
87typedef struct ptr_map ptr_map;
88
89extern ptr_map *ptr_map_new();
90extern void ptr_map_set(ptr_map *map, void *key, void *value);
91extern void *ptr_map_get(ptr_map *map, void *key);
92extern void *ptr_map_remove(ptr_map *map, void *key);
93
94
95/*********  zone definition ************/
96
97#define AUTO_ZONE_VERSION           7                                       // stored in malloc_zone_t version field, so that
98                                                                            // zone enumeration can validate the data structures.
99
100/*********  Malloc Logging (see Libc/gen/malloc.c) ************/
101
102typedef void (malloc_logger_t)(uint32_t type_flags, uintptr_t zone_ptr, uintptr_t size, uintptr_t ptr_arg, uintptr_t return_val, uint32_t num_hot_to_skip);
103extern malloc_logger_t *malloc_logger;
104
105#define MALLOC_LOG_TYPE_ALLOCATE        2
106#define MALLOC_LOG_TYPE_DEALLOCATE      4
107#define MALLOC_LOG_TYPE_HAS_ZONE        8
108#define MALLOC_LOG_TYPE_CLEARED         64
109
110/*********  Locking ************/
111
112inline void spin_lock(spin_lock_t *lockp) { OSSpinLockLock(lockp); }
113inline bool spin_lock_try(spin_lock_t *lockp) { return OSSpinLockTry(lockp); }
114inline void spin_unlock(spin_lock_t *lockp) { OSSpinLockUnlock(lockp); }
115
116/*********  Implementation utilities    ************/
117
118#define auto_expect_true(expression) __builtin_expect((expression)?1:0, 1)
119#define auto_expect_false(expression) __builtin_expect((expression)?1:0, 0)
120
121extern int auto_ncpus();
122
123extern vm_address_t auto_get_sp();
124
125size_t auto_round_page(size_t size);
126    // rounds up to an integer page size
127
128extern const char *auto_prelude(void);
129    // returns the prelude string, that contains the pid, to be logged in every log
130
131extern void auto_error(void *azone, const char *msg, const void *ptr);
132extern void auto_fatal(const char *format, ...);
133
134inline bool is_scanned(auto_memory_type_t layout) { return (layout & AUTO_UNSCANNED) != AUTO_UNSCANNED; }
135inline bool is_object(auto_memory_type_t layout) { return (layout & AUTO_OBJECT) != 0; }
136inline bool is_allocated_cleared(auto_memory_type_t layout) { return is_scanned(layout) || (layout == AUTO_MEMORY_ALL_WEAK_POINTERS); }
137
138/*********  Dealing with time   ************/
139
140static inline auto_date_t auto_date_now(void) {
141#if 0
142    return mach_absolute_time();
143#elif 0
144    struct rusage usage;
145    getrusage(RUSAGE_SELF, &usage);
146    return ((auto_date_t)usage.ru_utime.tv_sec * (auto_date_t)1000000) + (auto_date_t)usage.ru_utime.tv_usec +
147           ((auto_date_t)usage.ru_stime.tv_sec * (auto_date_t)1000000) + (auto_date_t)usage.ru_stime.tv_usec;
148#else
149    thread_basic_info_data_t myinfo;
150    unsigned int count = sizeof(myinfo);
151    thread_info(pthread_mach_thread_np(pthread_self()), THREAD_BASIC_INFO, (thread_info_t)&myinfo, &count);
152/*
153struct thread_basic_info
154{
155       time_value_t     user_time;
156       time_value_t   system_time;
157       integer_t        cpu_usage;
158       policy_t            policy;
159       integer_t        run_state;
160       integer_t            flags;
161       integer_t    suspend_count;
162       integer_t       sleep_time;
163};
164struct time_value {
165        integer_t seconds;
166        integer_t microseconds;
167};
168
169*/
170
171   return ((auto_date_t)myinfo.user_time.seconds*(auto_date_t)1000000) + (auto_date_t)myinfo.user_time.microseconds +
172          ((auto_date_t)myinfo.system_time.seconds*(auto_date_t)1000000) + (auto_date_t)myinfo.system_time.microseconds;
173#endif
174}
175
176extern double auto_time_interval(auto_date_t after, auto_date_t before);
177    // returns duration in seconds
178    // use auto_time_interval(duration, 0) if already a duration
179
180/*********  Collection definition   ************/
181
182/*
183static inline auto_date_t auto_collection_time() {
184  struct timeval tv;
185  gettimeofday(&tv, NULL);
186  return (tv.tv_sec * (auto_date_t)1000000) + (auto_date_t)tv.tv_usec;
187}
188*/
189
190enum {
191    AUTO_COLLECTION_STATUS_INTERRUPT = -1,
192    AUTO_COLLECTION_STATUS_ERROR = 0,
193    AUTO_COLLECTION_STATUS_OK = 1
194};
195
196/*********  Internal allocation ************/
197
198extern malloc_zone_t *aux_zone;
199
200extern void aux_init(void);
201
202static inline void *aux_malloc(size_t size) {
203    return malloc_zone_malloc(aux_zone, size);
204}
205
206static inline void *aux_calloc(size_t count, size_t size) {
207    return malloc_zone_calloc(aux_zone, count, size);
208}
209
210static inline void *aux_valloc(size_t size) {
211    return malloc_zone_valloc(aux_zone, size);
212}
213
214static inline void *aux_realloc(void *ptr, size_t size) {
215    return malloc_zone_realloc(aux_zone, ptr, size);
216}
217
218static inline void aux_free(void *ptr) {
219    return malloc_zone_free(aux_zone, ptr);
220}
221
222static inline size_t aux_malloc_size(const void *ptr) {
223    return aux_zone->size(aux_zone, ptr);
224}
225
226/*********  debug utilities ************/
227
228extern void auto_collect_print_trace_stats(void);
229
230extern void auto_record_refcount_stack(auto_zone_t *azone, void *ptr, int delta);
231extern void auto_print_refcount_stacks(void *ptr);
232
233extern void auto_refcount_underflow_error(void *);
234extern void auto_zone_resurrection_error();
235extern void auto_zone_thread_local_error(void);
236extern void auto_zone_thread_registration_error(void);
237extern void auto_zone_global_data_memmove_error(void);
238extern void auto_zone_association_error(void *address);
239extern void auto_zone_unscanned_store_error(const void *destination, const void *value);
240
241extern auto_zone_t *auto_zone_from_pointer(void *pointer);
242
243typedef void (^watch_block_t) (void);
244
245extern void auto_zone_watch(const void *ptr);
246extern void auto_zone_watch_free(const void *ptr, watch_block_t block);
247extern void auto_zone_watch_apply(void *ptr, watch_block_t block);
248
249
250__END_DECLS
251
252#endif /* __AUTO_IMPL_UTILITIES__ */
253