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 Environment.cpp 22 Environment Variables 23 Copyright (c) 2004-2011 Apple Inc. All rights reserved. 24 */ 25 26#include <errno.h> 27#include <crt_externs.h> 28 29#include "Definitions.h" 30#include "Environment.h" 31#ifndef AUTO_TESTER 32#include "auto_impl_utilities.h" 33#endif 34 35namespace Auto { 36#if defined(DEBUG) 37 bool Environment::clear_all_new; // clear all new blocks 38 bool Environment::dirty_all_new; // dirty all new blocks 39 bool Environment::print_stats; // print statistics after collection 40 bool Environment::print_scan_stats; // print scanning statistics 41 bool Environment::print_allocs; // print vm and malloc allocations and deallocations 42 bool Environment::unscanned_store_warning; // warn when GC-managed pointers stored in unscanned memory. 43#endif 44 45 bool Environment::guard_pages; // create guard pages for all small/medium blocks. 46 bool Environment::dirty_all_deleted; // dirty all deleted blocks 47 bool Environment::thread_collections; // enable thread local collections 48 bool Environment::log_reference_counting; // log reference counting activity 49 bool Environment::log_compactions; // log compaction activity 50 bool Environment::scramble_heap; // move all possible objects during compaction 51 uint32_t Environment::exhaustive_collection_limit; // max # of full collections in an exhaustive collection 52 bool Environment::resurrection_is_fatal; // true if resurrection is a fatal error 53 bool Environment::environ_has_auto_prefix; // true if any strings in environ have the AUTO_ prefix. 54 bool Environment::environ_has_malloc_prefix; // true if any strings in environ have the Malloc prefix. 55 double Environment::default_duty_cycle; // default collector duty cycle. 56 57 58 const char *Environment::get(const char *name) { 59 if ((environ_has_auto_prefix && strncmp(name, "AUTO_", 5) == 0) || 60 (environ_has_malloc_prefix && strncmp(name, "Malloc", 5) == 0)) { 61 return ::getenv(name); 62 } 63 return NULL; 64 } 65 66 // 67 // read_long 68 // 69 // Read a long (integer) value from the environment variable given by var. 70 // Return the value, or returns default_value if var is unset. 71 // msg is an optional descriptive message indicating the effect of a non-default value for var 72 // 73 long Environment::read_long(const char *var, long default_value, const char *msg) { 74 long result = default_value; 75 const char *s = Environment::get(var); 76 if (s) { 77 long parsed = strtol(s, NULL, 10); 78 if (parsed != 0 || errno != EINVAL) { 79 result = parsed; 80#ifndef AUTO_TESTER 81 if (result != default_value) 82 malloc_printf("%s: %s = \"%s\" in environment. %s\n", auto_prelude(), var, s, msg ?: ""); 83#endif 84 } 85 } 86 return result; 87 } 88 89 // 90 // read_bool 91 // 92 // Read a boolean value from the environment variable given by var. 93 // Returns default_value if var is not set in the environment. 94 // Returns true if var is set to an empty string 95 // Returns true if var is set to "yes" or "true" (case insensitive). 96 // Returns false if var is set to "no" or "false". 97 // msg is an optional descriptive message indicating the effect of a non-default value for var 98 // 99 bool Environment::read_bool(const char *var, bool default_value, const char *msg) { 100 bool result = default_value; 101 const char *s = Environment::get(var); 102 if (s) { 103 if (strlen(s) == 0) 104 result = true; 105 else if (strcasecmp(s, "yes") == 0 || strcasecmp(s, "true") == 0 || strcmp(s, "1") == 0) 106 result = true; 107 else if (strcasecmp(s, "no") == 0 || strcasecmp(s, "false") == 0 || strcmp(s, "0") == 0) 108 result = false; 109#ifndef AUTO_TESTER 110 if (result != default_value) 111 malloc_printf("%s: %s = \"%s\" in environment. %s\n", auto_prelude(), var, s, msg ?: ""); 112#endif 113 } 114 return result; 115 } 116 117 static void prescan_environment() { 118 for (char **env = *_NSGetEnviron(); *env != NULL; ++env) { 119 if (strncmp(*env, "AUTO_", 5) == 0) 120 Environment::environ_has_auto_prefix = true; 121 else if (strncmp(*env, "Malloc", 6) == 0) 122 Environment::environ_has_malloc_prefix = true; 123 } 124 } 125 126 // 127 // initialize 128 // 129 // Reads the environment variables values. 130 // 131 void Environment::initialize() { 132 prescan_environment(); 133 134#if defined(DEBUG) 135 clear_all_new = read_bool("AUTO_CLEAR_ALL_NEW", false); 136 dirty_all_new = read_bool("AUTO_DIRTY_ALL_NEW", false); 137 print_stats = read_bool("AUTO_PRINT_STATS", false); 138 print_scan_stats = read_bool("AUTO_SCAN_PRINT_STATS", false); 139 unscanned_store_warning = read_bool("AUTO_UNSCANNED_STORE_WARNING", false, "Unscanned store warnings enabled."); 140#endif 141 guard_pages = read_bool("AUTO_USE_GUARDS", false, "Guard pages are enabled. Application will be slower and use more memory. Buffer overruns in the Auto zone will be caught."); 142 dirty_all_deleted = read_bool("AUTO_DIRTY_ALL_DELETED", false, "Deleted objects will be dirtied by the collector (similar to MallocScribble).") || read_long("MallocScribble", false, "Deleted objects will be dirtied by the collector."); 143 thread_collections = read_bool("AUTO_USE_TLC", true, "Thread local collector [TLC] disabled."); 144 log_reference_counting = read_bool("AUTO_REFERENCE_COUNT_LOGGING", false, "Reference count logging enabled."); 145 log_compactions = read_bool("AUTO_COMPACTION_LOGGING", false, "Compaction logging enabled."); 146 scramble_heap = read_bool("AUTO_COMPACTION_SCRAMBLE", false, "Heap scrambling enabled."); 147 exhaustive_collection_limit = read_long("AUTO_EXHAUSTIVE_COLLECTION_LIMIT", 8); 148 resurrection_is_fatal = read_bool("AUTO_RESURRECTION_ABORT", true, "Resurrections errors will not be treated as fatal. This may lead to heap inconsistencies and crashes, possibly long after the resurrection occurs."); 149 default_duty_cycle = (double)read_long("AUTO_DUTY_CYCLE", 25) / 100.0; 150 if (default_duty_cycle < 0.0001 || default_duty_cycle > 1.0) { 151 default_duty_cycle = 0.25; 152#ifndef AUTO_TESTER 153 malloc_printf("%s: Invalid value for AUTO_DUTY_CYCLE. Using default.\n", auto_prelude()); 154#endif 155 } 156 } 157} 158