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
empty(const char * str)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
item_uint_process(const umem_env_item_t * item,const char * item_arg)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
item_size_process(const umem_env_item_t * item,const char * item_arg)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
umem_log_process(const umem_env_item_t * item,const char * item_arg)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
umem_size_process(const umem_env_item_t * item,const char * item_arg)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
umem_backend_process(const umem_env_item_t * item,const char * item_arg)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
umem_allocator_process(const umem_env_item_t * item,const char * item_arg)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
process_item(const umem_env_item_t * item,const char * item_arg)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
umem_process_value(umem_env_item_t * item_list,const char * beg,const char * end)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
umem_setup_envvars(int invalid)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
umem_process_envvars(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