17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5789d94c2Sjwadams * Common Development and Distribution License (the "License"). 6789d94c2Sjwadams * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21a574db85Sraf 227c478bd9Sstevel@tonic-gate /* 23a574db85Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*4f364e7cSRobert Mustacchi */ 26*4f364e7cSRobert Mustacchi 27*4f364e7cSRobert Mustacchi /* 28*4f364e7cSRobert Mustacchi * Copyright (c) 2012 Joyent, Inc. All rights reserved. 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #include <ctype.h> 327c478bd9Sstevel@tonic-gate #include <errno.h> 337c478bd9Sstevel@tonic-gate #include <limits.h> 347c478bd9Sstevel@tonic-gate #include <stdlib.h> 357c478bd9Sstevel@tonic-gate #include <string.h> 367c478bd9Sstevel@tonic-gate #include <dlfcn.h> 377c478bd9Sstevel@tonic-gate #include "umem_base.h" 387c478bd9Sstevel@tonic-gate #include "vmem_base.h" 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate /* 417c478bd9Sstevel@tonic-gate * A umem environment variable, like UMEM_DEBUG, is set to a series 427c478bd9Sstevel@tonic-gate * of items, seperated by ',': 437c478bd9Sstevel@tonic-gate * 447c478bd9Sstevel@tonic-gate * UMEM_DEBUG="audit=10,guards,firewall=512" 457c478bd9Sstevel@tonic-gate * 467c478bd9Sstevel@tonic-gate * This structure describes items. Each item has a name, type, and 477c478bd9Sstevel@tonic-gate * description. During processing, an item read from the user may 487c478bd9Sstevel@tonic-gate * be either "valid" or "invalid". 497c478bd9Sstevel@tonic-gate * 507c478bd9Sstevel@tonic-gate * A valid item has an argument, if required, and it is of the right 517c478bd9Sstevel@tonic-gate * form (doesn't overflow, doesn't contain any unexpected characters). 527c478bd9Sstevel@tonic-gate * 537c478bd9Sstevel@tonic-gate * If the item is valid, item_flag_target != NULL, and: 547c478bd9Sstevel@tonic-gate * type is not CLEARFLAG, then (*item_flag_target) |= item_flag_value 557c478bd9Sstevel@tonic-gate * type is CLEARFLAG, then (*item_flag_target) &= ~item_flag_value 567c478bd9Sstevel@tonic-gate */ 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate #define UMEM_ENV_ITEM_MAX 512 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate struct umem_env_item; 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate typedef int arg_process_t(const struct umem_env_item *item, const char *value); 637c478bd9Sstevel@tonic-gate #define ARG_SUCCESS 0 /* processing successful */ 647c478bd9Sstevel@tonic-gate #define ARG_BAD 1 /* argument had a bad value */ 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate typedef struct umem_env_item { 677c478bd9Sstevel@tonic-gate const char *item_name; /* tag in environment variable */ 687c478bd9Sstevel@tonic-gate const char *item_interface_stability; 697c478bd9Sstevel@tonic-gate enum { 707c478bd9Sstevel@tonic-gate ITEM_INVALID, 717c478bd9Sstevel@tonic-gate ITEM_FLAG, /* only a flag. No argument allowed */ 727c478bd9Sstevel@tonic-gate ITEM_CLEARFLAG, /* only a flag, but clear instead of set */ 737c478bd9Sstevel@tonic-gate ITEM_OPTUINT, /* optional integer argument */ 747c478bd9Sstevel@tonic-gate ITEM_UINT, /* required integer argument */ 757c478bd9Sstevel@tonic-gate ITEM_OPTSIZE, /* optional size_t argument */ 767c478bd9Sstevel@tonic-gate ITEM_SIZE, /* required size_t argument */ 777c478bd9Sstevel@tonic-gate ITEM_SPECIAL /* special argument processing */ 787c478bd9Sstevel@tonic-gate } item_type; 797c478bd9Sstevel@tonic-gate const char *item_description; 807c478bd9Sstevel@tonic-gate uint_t *item_flag_target; /* the variable containing the flag */ 817c478bd9Sstevel@tonic-gate uint_t item_flag_value; /* the value to OR in */ 827c478bd9Sstevel@tonic-gate uint_t *item_uint_target; /* the variable to hold the integer */ 837c478bd9Sstevel@tonic-gate size_t *item_size_target; 847c478bd9Sstevel@tonic-gate arg_process_t *item_special; /* callback for special handling */ 857c478bd9Sstevel@tonic-gate } umem_env_item_t; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate #ifndef UMEM_STANDALONE 887c478bd9Sstevel@tonic-gate static arg_process_t umem_backend_process; 89aaf809d7SRobert Mustacchi static arg_process_t umem_allocator_process; 907c478bd9Sstevel@tonic-gate #endif 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate static arg_process_t umem_log_process; 937c478bd9Sstevel@tonic-gate 94789d94c2Sjwadams static size_t umem_size_tempval; 95789d94c2Sjwadams static arg_process_t umem_size_process; 96789d94c2Sjwadams 977c478bd9Sstevel@tonic-gate const char *____umem_environ_msg_options = "-- UMEM_OPTIONS --"; 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate static umem_env_item_t umem_options_items[] = { 1007c478bd9Sstevel@tonic-gate #ifndef UMEM_STANDALONE 1017c478bd9Sstevel@tonic-gate { "backend", "Evolving", ITEM_SPECIAL, 1027c478bd9Sstevel@tonic-gate "=sbrk for sbrk(2), =mmap for mmap(2)", 1037c478bd9Sstevel@tonic-gate NULL, 0, NULL, NULL, 1047c478bd9Sstevel@tonic-gate &umem_backend_process 1057c478bd9Sstevel@tonic-gate }, 106aaf809d7SRobert Mustacchi { "allocator", "Evolving", ITEM_SPECIAL, 107aaf809d7SRobert Mustacchi "=best, =first, =next, or =instant", 108aaf809d7SRobert Mustacchi NULL, 0, NULL, NULL, 109aaf809d7SRobert Mustacchi &umem_allocator_process 110aaf809d7SRobert Mustacchi }, 1117c478bd9Sstevel@tonic-gate #endif 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate { "concurrency", "Private", ITEM_UINT, 1147c478bd9Sstevel@tonic-gate "Max concurrency", 1157c478bd9Sstevel@tonic-gate NULL, 0, &umem_max_ncpus 1167c478bd9Sstevel@tonic-gate }, 1177c478bd9Sstevel@tonic-gate { "max_contention", "Private", ITEM_UINT, 1187c478bd9Sstevel@tonic-gate "Maximum contention in a reap interval before the depot is " 1197c478bd9Sstevel@tonic-gate "resized.", 1207c478bd9Sstevel@tonic-gate NULL, 0, &umem_depot_contention 1217c478bd9Sstevel@tonic-gate }, 1227c478bd9Sstevel@tonic-gate { "nomagazines", "Private", ITEM_FLAG, 1237c478bd9Sstevel@tonic-gate "no caches will be multithreaded, and no caching will occur.", 1247c478bd9Sstevel@tonic-gate &umem_flags, UMF_NOMAGAZINE 1257c478bd9Sstevel@tonic-gate }, 1267c478bd9Sstevel@tonic-gate { "reap_interval", "Private", ITEM_UINT, 1277c478bd9Sstevel@tonic-gate "Minimum time between reaps and updates, in seconds.", 1287c478bd9Sstevel@tonic-gate NULL, 0, &umem_reap_interval 1297c478bd9Sstevel@tonic-gate }, 1307c478bd9Sstevel@tonic-gate 131789d94c2Sjwadams { "size_add", "Private", ITEM_SPECIAL, 132789d94c2Sjwadams "add a size to the cache size table", 133789d94c2Sjwadams NULL, 0, NULL, 134789d94c2Sjwadams &umem_size_tempval, &umem_size_process 135789d94c2Sjwadams }, 136789d94c2Sjwadams { "size_clear", "Private", ITEM_SPECIAL, 137789d94c2Sjwadams "clear all but the largest size from the cache size table", 138789d94c2Sjwadams NULL, 0, NULL, 139789d94c2Sjwadams &umem_size_tempval, &umem_size_process 140789d94c2Sjwadams }, 141789d94c2Sjwadams { "size_remove", "Private", ITEM_SPECIAL, 142789d94c2Sjwadams "remove a size from the cache size table", 143789d94c2Sjwadams NULL, 0, NULL, 144789d94c2Sjwadams &umem_size_tempval, &umem_size_process 145789d94c2Sjwadams }, 146789d94c2Sjwadams 1477c478bd9Sstevel@tonic-gate #ifndef UMEM_STANDALONE 148789d94c2Sjwadams { "sbrk_minalloc", "Private", ITEM_SIZE, 149789d94c2Sjwadams "The minimum allocation chunk for the sbrk(2) heap.", 150789d94c2Sjwadams NULL, 0, NULL, &vmem_sbrk_minalloc 151789d94c2Sjwadams }, 1527c478bd9Sstevel@tonic-gate { "sbrk_pagesize", "Private", ITEM_SIZE, 1537c478bd9Sstevel@tonic-gate "The preferred page size for the sbrk(2) heap.", 1547c478bd9Sstevel@tonic-gate NULL, 0, NULL, &vmem_sbrk_pagesize 1557c478bd9Sstevel@tonic-gate }, 1567c478bd9Sstevel@tonic-gate #endif 157*4f364e7cSRobert Mustacchi { "perthread_cache", "Evolving", ITEM_SIZE, 158*4f364e7cSRobert Mustacchi "Size (in bytes) of per-thread allocation cache", 159*4f364e7cSRobert Mustacchi NULL, 0, NULL, &umem_ptc_size 160*4f364e7cSRobert Mustacchi }, 1617c478bd9Sstevel@tonic-gate { NULL, "-- end of UMEM_OPTIONS --", ITEM_INVALID } 1627c478bd9Sstevel@tonic-gate }; 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate const char *____umem_environ_msg_debug = "-- UMEM_DEBUG --"; 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate static umem_env_item_t umem_debug_items[] = { 1677c478bd9Sstevel@tonic-gate { "default", "Unstable", ITEM_FLAG, 1687c478bd9Sstevel@tonic-gate "audit,contents,guards", 1697c478bd9Sstevel@tonic-gate &umem_flags, 1707c478bd9Sstevel@tonic-gate UMF_AUDIT | UMF_CONTENTS | UMF_DEADBEEF | UMF_REDZONE 1717c478bd9Sstevel@tonic-gate }, 1727c478bd9Sstevel@tonic-gate { "audit", "Unstable", ITEM_OPTUINT, 1737c478bd9Sstevel@tonic-gate "Enable auditing. optionally =frames to set the number of " 1747c478bd9Sstevel@tonic-gate "stored stack frames", 1757c478bd9Sstevel@tonic-gate &umem_flags, UMF_AUDIT, &umem_stack_depth 1767c478bd9Sstevel@tonic-gate }, 1777c478bd9Sstevel@tonic-gate { "contents", "Unstable", ITEM_OPTSIZE, 1787c478bd9Sstevel@tonic-gate "Enable contents storing. UMEM_LOGGING=contents also " 1797c478bd9Sstevel@tonic-gate "required. optionally =bytes to set the number of stored " 1807c478bd9Sstevel@tonic-gate "bytes", 1817c478bd9Sstevel@tonic-gate &umem_flags, UMF_CONTENTS, NULL, &umem_content_maxsave 1827c478bd9Sstevel@tonic-gate }, 1837c478bd9Sstevel@tonic-gate { "guards", "Unstable", ITEM_FLAG, 1847c478bd9Sstevel@tonic-gate "Enables guards and special patterns", 1857c478bd9Sstevel@tonic-gate &umem_flags, UMF_DEADBEEF | UMF_REDZONE 1867c478bd9Sstevel@tonic-gate }, 1877c478bd9Sstevel@tonic-gate { "verbose", "Unstable", ITEM_FLAG, 1887c478bd9Sstevel@tonic-gate "Enables writing error messages to stderr", 1897c478bd9Sstevel@tonic-gate &umem_output, 1 1907c478bd9Sstevel@tonic-gate }, 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate { "nosignal", "Private", ITEM_FLAG, 1937c478bd9Sstevel@tonic-gate "Abort if called from a signal handler. Turns on 'audit'. " 1947c478bd9Sstevel@tonic-gate "Note that this is not always a bug.", 1957c478bd9Sstevel@tonic-gate &umem_flags, UMF_AUDIT | UMF_CHECKSIGNAL 1967c478bd9Sstevel@tonic-gate }, 1977c478bd9Sstevel@tonic-gate { "firewall", "Private", ITEM_SIZE, 1987c478bd9Sstevel@tonic-gate "=minbytes. Every object >= minbytes in size will have its " 1997c478bd9Sstevel@tonic-gate "end against an unmapped page", 2007c478bd9Sstevel@tonic-gate &umem_flags, UMF_FIREWALL, NULL, &umem_minfirewall 2017c478bd9Sstevel@tonic-gate }, 2027c478bd9Sstevel@tonic-gate { "lite", "Private", ITEM_FLAG, 2037c478bd9Sstevel@tonic-gate "debugging-lite", 2047c478bd9Sstevel@tonic-gate &umem_flags, UMF_LITE 2057c478bd9Sstevel@tonic-gate }, 2067c478bd9Sstevel@tonic-gate { "maxverify", "Private", ITEM_SIZE, 2077c478bd9Sstevel@tonic-gate "=maxbytes, Maximum bytes to check when 'guards' is active. " 2087c478bd9Sstevel@tonic-gate "Normally all bytes are checked.", 2097c478bd9Sstevel@tonic-gate NULL, 0, NULL, &umem_maxverify 2107c478bd9Sstevel@tonic-gate }, 2117c478bd9Sstevel@tonic-gate { "noabort", "Private", ITEM_CLEARFLAG, 2127c478bd9Sstevel@tonic-gate "umem will not abort when a recoverable error occurs " 2137c478bd9Sstevel@tonic-gate "(i.e. double frees, certain kinds of corruption)", 2147c478bd9Sstevel@tonic-gate &umem_abort, 1 2157c478bd9Sstevel@tonic-gate }, 2167c478bd9Sstevel@tonic-gate { "mtbf", "Private", ITEM_UINT, 2177c478bd9Sstevel@tonic-gate "=mtbf, the mean time between injected failures. Works best " 2187c478bd9Sstevel@tonic-gate "if prime.\n", 2197c478bd9Sstevel@tonic-gate NULL, 0, &umem_mtbf 2207c478bd9Sstevel@tonic-gate }, 2217c478bd9Sstevel@tonic-gate { "random", "Private", ITEM_FLAG, 2227c478bd9Sstevel@tonic-gate "randomize flags on a per-cache basis", 2237c478bd9Sstevel@tonic-gate &umem_flags, UMF_RANDOMIZE 2247c478bd9Sstevel@tonic-gate }, 2257c478bd9Sstevel@tonic-gate { "allverbose", "Private", ITEM_FLAG, 2267c478bd9Sstevel@tonic-gate "Enables writing all logged messages to stderr", 2277c478bd9Sstevel@tonic-gate &umem_output, 2 2287c478bd9Sstevel@tonic-gate }, 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate { NULL, "-- end of UMEM_DEBUG --", ITEM_INVALID } 2317c478bd9Sstevel@tonic-gate }; 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate const char *____umem_environ_msg_logging = "-- UMEM_LOGGING --"; 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate static umem_env_item_t umem_logging_items[] = { 2367c478bd9Sstevel@tonic-gate { "transaction", "Unstable", ITEM_SPECIAL, 2377c478bd9Sstevel@tonic-gate "If 'audit' is set in UMEM_DEBUG, the audit structures " 2387c478bd9Sstevel@tonic-gate "from previous transactions are entered into this log.", 2397c478bd9Sstevel@tonic-gate NULL, 0, NULL, 2407c478bd9Sstevel@tonic-gate &umem_transaction_log_size, &umem_log_process 2417c478bd9Sstevel@tonic-gate }, 2427c478bd9Sstevel@tonic-gate { "contents", "Unstable", ITEM_SPECIAL, 2437c478bd9Sstevel@tonic-gate "If 'audit' is set in UMEM_DEBUG, the contents of objects " 2447c478bd9Sstevel@tonic-gate "are recorded in this log as they are freed. If the " 2457c478bd9Sstevel@tonic-gate "'contents' option is not set in UMEM_DEBUG, the first " 2467c478bd9Sstevel@tonic-gate "256 bytes of each freed buffer will be saved.", 2477c478bd9Sstevel@tonic-gate &umem_flags, UMF_CONTENTS, NULL, 2487c478bd9Sstevel@tonic-gate &umem_content_log_size, &umem_log_process 2497c478bd9Sstevel@tonic-gate }, 2507c478bd9Sstevel@tonic-gate { "fail", "Unstable", ITEM_SPECIAL, 2517c478bd9Sstevel@tonic-gate "Records are entered into this log for every failed " 2527c478bd9Sstevel@tonic-gate "allocation.", 2537c478bd9Sstevel@tonic-gate NULL, 0, NULL, 2547c478bd9Sstevel@tonic-gate &umem_failure_log_size, &umem_log_process 2557c478bd9Sstevel@tonic-gate }, 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate { "slab", "Private", ITEM_SPECIAL, 2587c478bd9Sstevel@tonic-gate "Every slab created will be entered into this log.", 2597c478bd9Sstevel@tonic-gate NULL, 0, NULL, 2607c478bd9Sstevel@tonic-gate &umem_slab_log_size, &umem_log_process 2617c478bd9Sstevel@tonic-gate }, 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate { NULL, "-- end of UMEM_LOGGING --", ITEM_INVALID } 2647c478bd9Sstevel@tonic-gate }; 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate typedef struct umem_envvar { 2677c478bd9Sstevel@tonic-gate const char *env_name; 2687c478bd9Sstevel@tonic-gate const char *env_func; 2697c478bd9Sstevel@tonic-gate umem_env_item_t *env_item_list; 2707c478bd9Sstevel@tonic-gate const char *env_getenv_result; 2717c478bd9Sstevel@tonic-gate const char *env_func_result; 2727c478bd9Sstevel@tonic-gate } umem_envvar_t; 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate static umem_envvar_t umem_envvars[] = { 2757c478bd9Sstevel@tonic-gate { "UMEM_DEBUG", "_umem_debug_init", umem_debug_items }, 2767c478bd9Sstevel@tonic-gate { "UMEM_OPTIONS", "_umem_options_init", umem_options_items }, 2777c478bd9Sstevel@tonic-gate { "UMEM_LOGGING", "_umem_logging_init", umem_logging_items }, 2787c478bd9Sstevel@tonic-gate { NULL, NULL, NULL } 2797c478bd9Sstevel@tonic-gate }; 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate static umem_envvar_t *env_current; 2827c478bd9Sstevel@tonic-gate #define CURRENT (env_current->env_name) 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate static int 2857c478bd9Sstevel@tonic-gate empty(const char *str) 2867c478bd9Sstevel@tonic-gate { 2877c478bd9Sstevel@tonic-gate char c; 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate while ((c = *str) != '\0' && isspace(c)) 2907c478bd9Sstevel@tonic-gate str++; 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate return (*str == '\0'); 2937c478bd9Sstevel@tonic-gate } 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate static int 2967c478bd9Sstevel@tonic-gate item_uint_process(const umem_env_item_t *item, const char *item_arg) 2977c478bd9Sstevel@tonic-gate { 2987c478bd9Sstevel@tonic-gate ulong_t result; 2997c478bd9Sstevel@tonic-gate char *endptr = ""; 3007c478bd9Sstevel@tonic-gate int olderrno; 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate olderrno = errno; 3037c478bd9Sstevel@tonic-gate errno = 0; 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate if (empty(item_arg)) { 3067c478bd9Sstevel@tonic-gate goto badnumber; 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate result = strtoul(item_arg, &endptr, 10); 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate if (result == ULONG_MAX && errno == ERANGE) { 3127c478bd9Sstevel@tonic-gate errno = olderrno; 3137c478bd9Sstevel@tonic-gate goto overflow; 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate errno = olderrno; 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate if (*endptr != '\0') 3187c478bd9Sstevel@tonic-gate goto badnumber; 3197c478bd9Sstevel@tonic-gate if ((uint_t)result != result) 3207c478bd9Sstevel@tonic-gate goto overflow; 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate (*item->item_uint_target) = (uint_t)result; 3237c478bd9Sstevel@tonic-gate return (ARG_SUCCESS); 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate badnumber: 3267c478bd9Sstevel@tonic-gate log_message("%s: %s: not a number\n", CURRENT, item->item_name); 3277c478bd9Sstevel@tonic-gate return (ARG_BAD); 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate overflow: 3307c478bd9Sstevel@tonic-gate log_message("%s: %s: overflowed\n", CURRENT, item->item_name); 3317c478bd9Sstevel@tonic-gate return (ARG_BAD); 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate static int 3357c478bd9Sstevel@tonic-gate item_size_process(const umem_env_item_t *item, const char *item_arg) 3367c478bd9Sstevel@tonic-gate { 3377c478bd9Sstevel@tonic-gate ulong_t result; 3387c478bd9Sstevel@tonic-gate ulong_t result_arg; 3397c478bd9Sstevel@tonic-gate char *endptr = ""; 3407c478bd9Sstevel@tonic-gate int olderrno; 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate if (empty(item_arg)) 3437c478bd9Sstevel@tonic-gate goto badnumber; 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate olderrno = errno; 3467c478bd9Sstevel@tonic-gate errno = 0; 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate result_arg = strtoul(item_arg, &endptr, 10); 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate if (result_arg == ULONG_MAX && errno == ERANGE) { 3517c478bd9Sstevel@tonic-gate errno = olderrno; 3527c478bd9Sstevel@tonic-gate goto overflow; 3537c478bd9Sstevel@tonic-gate } 3547c478bd9Sstevel@tonic-gate errno = olderrno; 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate result = result_arg; 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate switch (*endptr) { 3597c478bd9Sstevel@tonic-gate case 't': 3607c478bd9Sstevel@tonic-gate case 'T': 3617c478bd9Sstevel@tonic-gate result *= 1024; 3627c478bd9Sstevel@tonic-gate if (result < result_arg) 3637c478bd9Sstevel@tonic-gate goto overflow; 3647c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 3657c478bd9Sstevel@tonic-gate case 'g': 3667c478bd9Sstevel@tonic-gate case 'G': 3677c478bd9Sstevel@tonic-gate result *= 1024; 3687c478bd9Sstevel@tonic-gate if (result < result_arg) 3697c478bd9Sstevel@tonic-gate goto overflow; 3707c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 3717c478bd9Sstevel@tonic-gate case 'm': 3727c478bd9Sstevel@tonic-gate case 'M': 3737c478bd9Sstevel@tonic-gate result *= 1024; 3747c478bd9Sstevel@tonic-gate if (result < result_arg) 3757c478bd9Sstevel@tonic-gate goto overflow; 3767c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 3777c478bd9Sstevel@tonic-gate case 'k': 3787c478bd9Sstevel@tonic-gate case 'K': 3797c478bd9Sstevel@tonic-gate result *= 1024; 3807c478bd9Sstevel@tonic-gate if (result < result_arg) 3817c478bd9Sstevel@tonic-gate goto overflow; 3827c478bd9Sstevel@tonic-gate endptr++; /* skip over the size character */ 3837c478bd9Sstevel@tonic-gate break; 3847c478bd9Sstevel@tonic-gate default: 3857c478bd9Sstevel@tonic-gate break; /* handled later */ 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate if (*endptr != '\0') 3897c478bd9Sstevel@tonic-gate goto badnumber; 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate (*item->item_size_target) = result; 3927c478bd9Sstevel@tonic-gate return (ARG_SUCCESS); 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate badnumber: 3957c478bd9Sstevel@tonic-gate log_message("%s: %s: not a number\n", CURRENT, item->item_name); 3967c478bd9Sstevel@tonic-gate return (ARG_BAD); 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate overflow: 3997c478bd9Sstevel@tonic-gate log_message("%s: %s: overflowed\n", CURRENT, item->item_name); 4007c478bd9Sstevel@tonic-gate return (ARG_BAD); 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate static int 4047c478bd9Sstevel@tonic-gate umem_log_process(const umem_env_item_t *item, const char *item_arg) 4057c478bd9Sstevel@tonic-gate { 4067c478bd9Sstevel@tonic-gate if (item_arg != NULL) { 4077c478bd9Sstevel@tonic-gate int ret; 4087c478bd9Sstevel@tonic-gate ret = item_size_process(item, item_arg); 4097c478bd9Sstevel@tonic-gate if (ret != ARG_SUCCESS) 4107c478bd9Sstevel@tonic-gate return (ret); 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate if (*item->item_size_target == 0) 4137c478bd9Sstevel@tonic-gate return (ARG_SUCCESS); 4147c478bd9Sstevel@tonic-gate } else 4157c478bd9Sstevel@tonic-gate *item->item_size_target = 64*1024; 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate umem_logging = 1; 4187c478bd9Sstevel@tonic-gate return (ARG_SUCCESS); 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate 421789d94c2Sjwadams static int 422789d94c2Sjwadams umem_size_process(const umem_env_item_t *item, const char *item_arg) 423789d94c2Sjwadams { 424789d94c2Sjwadams const char *name = item->item_name; 425789d94c2Sjwadams void (*action_func)(size_t); 426789d94c2Sjwadams 427789d94c2Sjwadams size_t result; 428789d94c2Sjwadams 429789d94c2Sjwadams int ret; 430789d94c2Sjwadams 431789d94c2Sjwadams if (strcmp(name, "size_clear") == 0) { 432789d94c2Sjwadams if (item_arg != NULL) { 433789d94c2Sjwadams log_message("%s: %s: does not take a value. ignored\n", 434789d94c2Sjwadams CURRENT, name); 435789d94c2Sjwadams return (ARG_BAD); 436789d94c2Sjwadams } 437789d94c2Sjwadams umem_alloc_sizes_clear(); 438789d94c2Sjwadams return (ARG_SUCCESS); 439789d94c2Sjwadams } else if (strcmp(name, "size_add") == 0) { 440789d94c2Sjwadams action_func = umem_alloc_sizes_add; 441789d94c2Sjwadams } else if (strcmp(name, "size_remove") == 0) { 442789d94c2Sjwadams action_func = umem_alloc_sizes_remove; 443789d94c2Sjwadams } else { 444789d94c2Sjwadams log_message("%s: %s: internally unrecognized\n", 445789d94c2Sjwadams CURRENT, name, name, name); 446789d94c2Sjwadams return (ARG_BAD); 447789d94c2Sjwadams } 448789d94c2Sjwadams 449789d94c2Sjwadams if (item_arg == NULL) { 450789d94c2Sjwadams log_message("%s: %s: requires a value. ignored\n", 451789d94c2Sjwadams CURRENT, name); 452789d94c2Sjwadams return (ARG_BAD); 453789d94c2Sjwadams } 454789d94c2Sjwadams 455789d94c2Sjwadams ret = item_size_process(item, item_arg); 456789d94c2Sjwadams if (ret != ARG_SUCCESS) 457789d94c2Sjwadams return (ret); 458789d94c2Sjwadams 459789d94c2Sjwadams result = *item->item_size_target; 460789d94c2Sjwadams action_func(result); 461789d94c2Sjwadams return (ARG_SUCCESS); 462789d94c2Sjwadams } 463789d94c2Sjwadams 4647c478bd9Sstevel@tonic-gate #ifndef UMEM_STANDALONE 4657c478bd9Sstevel@tonic-gate static int 4667c478bd9Sstevel@tonic-gate umem_backend_process(const umem_env_item_t *item, const char *item_arg) 4677c478bd9Sstevel@tonic-gate { 4687c478bd9Sstevel@tonic-gate const char *name = item->item_name; 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate if (item_arg == NULL) 4717c478bd9Sstevel@tonic-gate goto fail; 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate if (strcmp(item_arg, "sbrk") == 0) 4747c478bd9Sstevel@tonic-gate vmem_backend |= VMEM_BACKEND_SBRK; 4757c478bd9Sstevel@tonic-gate else if (strcmp(item_arg, "mmap") == 0) 4767c478bd9Sstevel@tonic-gate vmem_backend |= VMEM_BACKEND_MMAP; 4777c478bd9Sstevel@tonic-gate else 4787c478bd9Sstevel@tonic-gate goto fail; 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate return (ARG_SUCCESS); 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate fail: 4837c478bd9Sstevel@tonic-gate log_message("%s: %s: must be %s=sbrk or %s=mmap\n", 4847c478bd9Sstevel@tonic-gate CURRENT, name, name, name); 4857c478bd9Sstevel@tonic-gate return (ARG_BAD); 4867c478bd9Sstevel@tonic-gate } 487aaf809d7SRobert Mustacchi 488aaf809d7SRobert Mustacchi 489aaf809d7SRobert Mustacchi static int 490aaf809d7SRobert Mustacchi umem_allocator_process(const umem_env_item_t *item, const char *item_arg) 491aaf809d7SRobert Mustacchi { 492aaf809d7SRobert Mustacchi const char *name = item->item_name; 493aaf809d7SRobert Mustacchi 494aaf809d7SRobert Mustacchi if (item_arg == NULL) 495aaf809d7SRobert Mustacchi goto fail; 496aaf809d7SRobert Mustacchi 497aaf809d7SRobert Mustacchi if (strcmp(item_arg, "best") == 0) 498aaf809d7SRobert Mustacchi vmem_allocator = VM_BESTFIT; 499aaf809d7SRobert Mustacchi else if (strcmp(item_arg, "next") == 0) 500aaf809d7SRobert Mustacchi vmem_allocator = VM_NEXTFIT; 501aaf809d7SRobert Mustacchi else if (strcmp(item_arg, "first") == 0) 502aaf809d7SRobert Mustacchi vmem_allocator = VM_FIRSTFIT; 503aaf809d7SRobert Mustacchi else if (strcmp(item_arg, "instant") == 0) 504aaf809d7SRobert Mustacchi vmem_allocator = 0; 505aaf809d7SRobert Mustacchi else 506aaf809d7SRobert Mustacchi goto fail; 507aaf809d7SRobert Mustacchi 508aaf809d7SRobert Mustacchi return (ARG_SUCCESS); 509aaf809d7SRobert Mustacchi 510aaf809d7SRobert Mustacchi fail: 511aaf809d7SRobert Mustacchi log_message("%s: %s: must be %s=best, %s=next or %s=first\n", 512aaf809d7SRobert Mustacchi CURRENT, name, name, name, name); 513aaf809d7SRobert Mustacchi return (ARG_BAD); 514aaf809d7SRobert Mustacchi 515aaf809d7SRobert Mustacchi } 5167c478bd9Sstevel@tonic-gate #endif 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate static int 5197c478bd9Sstevel@tonic-gate process_item(const umem_env_item_t *item, const char *item_arg) 5207c478bd9Sstevel@tonic-gate { 5217c478bd9Sstevel@tonic-gate int arg_required = 0; 5227c478bd9Sstevel@tonic-gate arg_process_t *processor; 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate switch (item->item_type) { 5257c478bd9Sstevel@tonic-gate case ITEM_FLAG: 5267c478bd9Sstevel@tonic-gate case ITEM_CLEARFLAG: 5277c478bd9Sstevel@tonic-gate case ITEM_OPTUINT: 5287c478bd9Sstevel@tonic-gate case ITEM_OPTSIZE: 5297c478bd9Sstevel@tonic-gate case ITEM_SPECIAL: 5307c478bd9Sstevel@tonic-gate arg_required = 0; 5317c478bd9Sstevel@tonic-gate break; 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate case ITEM_UINT: 5347c478bd9Sstevel@tonic-gate case ITEM_SIZE: 5357c478bd9Sstevel@tonic-gate arg_required = 1; 5367c478bd9Sstevel@tonic-gate break; 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate switch (item->item_type) { 5407c478bd9Sstevel@tonic-gate case ITEM_FLAG: 5417c478bd9Sstevel@tonic-gate case ITEM_CLEARFLAG: 5427c478bd9Sstevel@tonic-gate if (item_arg != NULL) { 5437c478bd9Sstevel@tonic-gate log_message("%s: %s: does not take a value. ignored\n", 5447c478bd9Sstevel@tonic-gate CURRENT, item->item_name); 5457c478bd9Sstevel@tonic-gate return (1); 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate processor = NULL; 5487c478bd9Sstevel@tonic-gate break; 5497c478bd9Sstevel@tonic-gate 5507c478bd9Sstevel@tonic-gate case ITEM_UINT: 5517c478bd9Sstevel@tonic-gate case ITEM_OPTUINT: 5527c478bd9Sstevel@tonic-gate processor = item_uint_process; 5537c478bd9Sstevel@tonic-gate break; 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate case ITEM_SIZE: 5567c478bd9Sstevel@tonic-gate case ITEM_OPTSIZE: 5577c478bd9Sstevel@tonic-gate processor = item_size_process; 5587c478bd9Sstevel@tonic-gate break; 5597c478bd9Sstevel@tonic-gate 5607c478bd9Sstevel@tonic-gate case ITEM_SPECIAL: 5617c478bd9Sstevel@tonic-gate processor = item->item_special; 5627c478bd9Sstevel@tonic-gate break; 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate default: 5657c478bd9Sstevel@tonic-gate log_message("%s: %s: Invalid type. Ignored\n", 5667c478bd9Sstevel@tonic-gate CURRENT, item->item_name); 5677c478bd9Sstevel@tonic-gate return (1); 5687c478bd9Sstevel@tonic-gate } 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate if (arg_required && item_arg == NULL) { 5717c478bd9Sstevel@tonic-gate log_message("%s: %s: Required value missing\n", 5727c478bd9Sstevel@tonic-gate CURRENT, item->item_name); 5737c478bd9Sstevel@tonic-gate goto invalid; 5747c478bd9Sstevel@tonic-gate } 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate if (item_arg != NULL || item->item_type == ITEM_SPECIAL) { 5777c478bd9Sstevel@tonic-gate if (processor(item, item_arg) != ARG_SUCCESS) 5787c478bd9Sstevel@tonic-gate goto invalid; 5797c478bd9Sstevel@tonic-gate } 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate if (item->item_flag_target) { 5827c478bd9Sstevel@tonic-gate if (item->item_type == ITEM_CLEARFLAG) 5837c478bd9Sstevel@tonic-gate (*item->item_flag_target) &= ~item->item_flag_value; 5847c478bd9Sstevel@tonic-gate else 5857c478bd9Sstevel@tonic-gate (*item->item_flag_target) |= item->item_flag_value; 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate return (0); 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate invalid: 5907c478bd9Sstevel@tonic-gate return (1); 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate #define ENV_SHORT_BYTES 10 /* bytes to print on error */ 5947c478bd9Sstevel@tonic-gate void 5957c478bd9Sstevel@tonic-gate umem_process_value(umem_env_item_t *item_list, const char *beg, const char *end) 5967c478bd9Sstevel@tonic-gate { 5977c478bd9Sstevel@tonic-gate char buf[UMEM_ENV_ITEM_MAX]; 5987c478bd9Sstevel@tonic-gate char *argptr; 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate size_t count; 6017c478bd9Sstevel@tonic-gate 6027c478bd9Sstevel@tonic-gate while (beg < end && isspace(*beg)) 6037c478bd9Sstevel@tonic-gate beg++; 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate while (beg < end && isspace(*(end - 1))) 6067c478bd9Sstevel@tonic-gate end--; 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate if (beg >= end) { 6097c478bd9Sstevel@tonic-gate log_message("%s: empty option\n", CURRENT); 6107c478bd9Sstevel@tonic-gate return; 6117c478bd9Sstevel@tonic-gate } 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate count = end - beg; 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate if (count + 1 > sizeof (buf)) { 6167c478bd9Sstevel@tonic-gate char outbuf[ENV_SHORT_BYTES + 1]; 6177c478bd9Sstevel@tonic-gate /* 6187c478bd9Sstevel@tonic-gate * Have to do this, since sprintf("%10s",...) calls malloc() 6197c478bd9Sstevel@tonic-gate */ 6207c478bd9Sstevel@tonic-gate (void) strncpy(outbuf, beg, ENV_SHORT_BYTES); 6217c478bd9Sstevel@tonic-gate outbuf[ENV_SHORT_BYTES] = 0; 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate log_message("%s: argument \"%s...\" too long\n", CURRENT, 6247c478bd9Sstevel@tonic-gate outbuf); 6257c478bd9Sstevel@tonic-gate return; 6267c478bd9Sstevel@tonic-gate } 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate (void) strncpy(buf, beg, count); 6297c478bd9Sstevel@tonic-gate buf[count] = 0; 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate argptr = strchr(buf, '='); 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate if (argptr != NULL) 6347c478bd9Sstevel@tonic-gate *argptr++ = 0; 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate for (; item_list->item_name != NULL; item_list++) { 6377c478bd9Sstevel@tonic-gate if (strcmp(buf, item_list->item_name) == 0) { 6387c478bd9Sstevel@tonic-gate (void) process_item(item_list, argptr); 6397c478bd9Sstevel@tonic-gate return; 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate } 6427c478bd9Sstevel@tonic-gate log_message("%s: '%s' not recognized\n", CURRENT, buf); 6437c478bd9Sstevel@tonic-gate } 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 6467c478bd9Sstevel@tonic-gate void 6477c478bd9Sstevel@tonic-gate umem_setup_envvars(int invalid) 6487c478bd9Sstevel@tonic-gate { 6497c478bd9Sstevel@tonic-gate umem_envvar_t *cur_env; 6507c478bd9Sstevel@tonic-gate static volatile enum { 6517c478bd9Sstevel@tonic-gate STATE_START, 6527c478bd9Sstevel@tonic-gate STATE_GETENV, 6532d9e8f45Sjwadams STATE_DLOPEN, 6547c478bd9Sstevel@tonic-gate STATE_DLSYM, 6557c478bd9Sstevel@tonic-gate STATE_FUNC, 6567c478bd9Sstevel@tonic-gate STATE_DONE 6577c478bd9Sstevel@tonic-gate } state = STATE_START; 6587c478bd9Sstevel@tonic-gate #ifndef UMEM_STANDALONE 6597c478bd9Sstevel@tonic-gate void *h; 6607c478bd9Sstevel@tonic-gate #endif 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate if (invalid) { 6637c478bd9Sstevel@tonic-gate const char *where; 6647c478bd9Sstevel@tonic-gate /* 6657c478bd9Sstevel@tonic-gate * One of the calls below invoked malloc() recursively. We 6667c478bd9Sstevel@tonic-gate * remove any partial results and return. 6677c478bd9Sstevel@tonic-gate */ 6687c478bd9Sstevel@tonic-gate 6697c478bd9Sstevel@tonic-gate switch (state) { 6707c478bd9Sstevel@tonic-gate case STATE_START: 6717c478bd9Sstevel@tonic-gate where = "before getenv(3C) calls -- " 6727c478bd9Sstevel@tonic-gate "getenv(3C) results ignored."; 6737c478bd9Sstevel@tonic-gate break; 6747c478bd9Sstevel@tonic-gate case STATE_GETENV: 6757c478bd9Sstevel@tonic-gate where = "during getenv(3C) calls -- " 6767c478bd9Sstevel@tonic-gate "getenv(3C) results ignored."; 6777c478bd9Sstevel@tonic-gate break; 6782d9e8f45Sjwadams case STATE_DLOPEN: 6792d9e8f45Sjwadams where = "during dlopen(3C) call -- " 6802d9e8f45Sjwadams "_umem_*() results ignored."; 6812d9e8f45Sjwadams break; 6827c478bd9Sstevel@tonic-gate case STATE_DLSYM: 6837c478bd9Sstevel@tonic-gate where = "during dlsym(3C) call -- " 6847c478bd9Sstevel@tonic-gate "_umem_*() results ignored."; 6857c478bd9Sstevel@tonic-gate break; 6867c478bd9Sstevel@tonic-gate case STATE_FUNC: 6877c478bd9Sstevel@tonic-gate where = "during _umem_*() call -- " 6887c478bd9Sstevel@tonic-gate "_umem_*() results ignored."; 6897c478bd9Sstevel@tonic-gate break; 6907c478bd9Sstevel@tonic-gate case STATE_DONE: 6917c478bd9Sstevel@tonic-gate where = "after dlsym() or _umem_*() calls."; 6927c478bd9Sstevel@tonic-gate break; 6937c478bd9Sstevel@tonic-gate default: 6947c478bd9Sstevel@tonic-gate where = "at unknown point -- " 6957c478bd9Sstevel@tonic-gate "_umem_*() results ignored."; 6967c478bd9Sstevel@tonic-gate break; 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate 6997c478bd9Sstevel@tonic-gate log_message("recursive allocation %s\n", where); 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate for (cur_env = umem_envvars; cur_env->env_name != NULL; 7027c478bd9Sstevel@tonic-gate cur_env++) { 7037c478bd9Sstevel@tonic-gate if (state == STATE_GETENV) 7047c478bd9Sstevel@tonic-gate cur_env->env_getenv_result = NULL; 7057c478bd9Sstevel@tonic-gate if (state != STATE_DONE) 7067c478bd9Sstevel@tonic-gate cur_env->env_func_result = NULL; 7077c478bd9Sstevel@tonic-gate } 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate state = STATE_DONE; 7107c478bd9Sstevel@tonic-gate return; 7117c478bd9Sstevel@tonic-gate } 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate state = STATE_GETENV; 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate for (cur_env = umem_envvars; cur_env->env_name != NULL; cur_env++) { 7167c478bd9Sstevel@tonic-gate cur_env->env_getenv_result = getenv(cur_env->env_name); 7177c478bd9Sstevel@tonic-gate if (state == STATE_DONE) 7187c478bd9Sstevel@tonic-gate return; /* recursed */ 7197c478bd9Sstevel@tonic-gate } 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate #ifndef UMEM_STANDALONE 7222d9e8f45Sjwadams state = STATE_DLOPEN; 7232d9e8f45Sjwadams 7247c478bd9Sstevel@tonic-gate /* get a handle to the "a.out" object */ 7257c478bd9Sstevel@tonic-gate if ((h = dlopen(0, RTLD_FIRST | RTLD_LAZY)) != NULL) { 7267c478bd9Sstevel@tonic-gate for (cur_env = umem_envvars; cur_env->env_name != NULL; 7277c478bd9Sstevel@tonic-gate cur_env++) { 7287c478bd9Sstevel@tonic-gate const char *(*func)(void); 7297c478bd9Sstevel@tonic-gate const char *value; 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate state = STATE_DLSYM; 7327c478bd9Sstevel@tonic-gate func = (const char *(*)(void))dlsym(h, 7337c478bd9Sstevel@tonic-gate cur_env->env_func); 7347c478bd9Sstevel@tonic-gate 7357c478bd9Sstevel@tonic-gate if (state == STATE_DONE) 7367c478bd9Sstevel@tonic-gate break; /* recursed */ 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate state = STATE_FUNC; 7397c478bd9Sstevel@tonic-gate if (func != NULL) { 7407c478bd9Sstevel@tonic-gate value = func(); 7417c478bd9Sstevel@tonic-gate if (state == STATE_DONE) 7427c478bd9Sstevel@tonic-gate break; /* recursed */ 7437c478bd9Sstevel@tonic-gate cur_env->env_func_result = value; 7447c478bd9Sstevel@tonic-gate } 7457c478bd9Sstevel@tonic-gate } 7467c478bd9Sstevel@tonic-gate (void) dlclose(h); 7477c478bd9Sstevel@tonic-gate } else { 7487c478bd9Sstevel@tonic-gate (void) dlerror(); /* snarf dlerror() */ 7497c478bd9Sstevel@tonic-gate } 7507c478bd9Sstevel@tonic-gate #endif /* UMEM_STANDALONE */ 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate state = STATE_DONE; 7537c478bd9Sstevel@tonic-gate } 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate /* 7567c478bd9Sstevel@tonic-gate * Process the environment variables. 7577c478bd9Sstevel@tonic-gate */ 7587c478bd9Sstevel@tonic-gate void 7597c478bd9Sstevel@tonic-gate umem_process_envvars(void) 7607c478bd9Sstevel@tonic-gate { 7617c478bd9Sstevel@tonic-gate const char *value; 7627c478bd9Sstevel@tonic-gate const char *end, *next; 7637c478bd9Sstevel@tonic-gate umem_envvar_t *cur_env; 7647c478bd9Sstevel@tonic-gate 7657c478bd9Sstevel@tonic-gate for (cur_env = umem_envvars; cur_env->env_name != NULL; cur_env++) { 7667c478bd9Sstevel@tonic-gate env_current = cur_env; 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate value = cur_env->env_getenv_result; 7697c478bd9Sstevel@tonic-gate if (value == NULL) 7707c478bd9Sstevel@tonic-gate value = cur_env->env_func_result; 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate /* ignore if missing or empty */ 7737c478bd9Sstevel@tonic-gate if (value == NULL) 7747c478bd9Sstevel@tonic-gate continue; 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate for (end = value; *end != '\0'; value = next) { 7777c478bd9Sstevel@tonic-gate end = strchr(value, ','); 7787c478bd9Sstevel@tonic-gate if (end != NULL) 7797c478bd9Sstevel@tonic-gate next = end + 1; /* skip the comma */ 7807c478bd9Sstevel@tonic-gate else 7817c478bd9Sstevel@tonic-gate next = end = value + strlen(value); 7827c478bd9Sstevel@tonic-gate 7837c478bd9Sstevel@tonic-gate umem_process_value(cur_env->env_item_list, value, end); 7847c478bd9Sstevel@tonic-gate } 7857c478bd9Sstevel@tonic-gate } 7867c478bd9Sstevel@tonic-gate } 787