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