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 5*004388ebScasper * Common Development and Distribution License (the "License"). 6*004388ebScasper * 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 */ 217c478bd9Sstevel@tonic-gate /* 22*004388ebScasper * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <stdio.h> 297c478bd9Sstevel@tonic-gate #include <stdlib.h> 307c478bd9Sstevel@tonic-gate #include <strings.h> 317c478bd9Sstevel@tonic-gate #include <sys/shm.h> 327c478bd9Sstevel@tonic-gate #include <sys/mman.h> 337c478bd9Sstevel@tonic-gate #include <fcntl.h> 347c478bd9Sstevel@tonic-gate #include <stdlib.h> 357c478bd9Sstevel@tonic-gate #include <unistd.h> 367c478bd9Sstevel@tonic-gate #include <errno.h> 377c478bd9Sstevel@tonic-gate #include <sys/types.h> 387c478bd9Sstevel@tonic-gate #include <sys/stat.h> 397c478bd9Sstevel@tonic-gate #include <sys/auxv.h> 407c478bd9Sstevel@tonic-gate #include <stdarg.h> 417c478bd9Sstevel@tonic-gate #include <syslog.h> 427c478bd9Sstevel@tonic-gate #include <sys/param.h> 437c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 447c478bd9Sstevel@tonic-gate #include <procfs.h> 457c478bd9Sstevel@tonic-gate #include <dlfcn.h> 467c478bd9Sstevel@tonic-gate #include <assert.h> 477c478bd9Sstevel@tonic-gate #include <libintl.h> 487c478bd9Sstevel@tonic-gate #include <locale.h> 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate extern int gmatch(const char *s, const char *p); 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate #pragma init(__madvmain) 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate static FILE *errfp = NULL; 557c478bd9Sstevel@tonic-gate static const char *madvident = "madv.so.1"; 567c478bd9Sstevel@tonic-gate static int pagesize; 577c478bd9Sstevel@tonic-gate static int advice_all = -1; 587c478bd9Sstevel@tonic-gate static int advice_heap = -1; 597c478bd9Sstevel@tonic-gate static int advice_shm = -1; 607c478bd9Sstevel@tonic-gate static int advice_ism = -1; 617c478bd9Sstevel@tonic-gate static int advice_dism = -1; 627c478bd9Sstevel@tonic-gate static int advice_map = -1; 637c478bd9Sstevel@tonic-gate static int advice_mapshared = -1; 647c478bd9Sstevel@tonic-gate static int advice_mapprivate = -1; 657c478bd9Sstevel@tonic-gate static int advice_mapanon = -1; 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate /* environment variables */ 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate #define ENV_MADV "MADV" 707c478bd9Sstevel@tonic-gate #define ENV_MADVCFGFILE "MADVCFGFILE" 717c478bd9Sstevel@tonic-gate #define ENV_MADVERRFILE "MADVERRFILE" 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate /* config file */ 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate #define DEF_MADVCFGFILE "/etc/madv.conf" 767c478bd9Sstevel@tonic-gate #define MAXLINELEN MAXPATHLEN + 64 777c478bd9Sstevel@tonic-gate #define CFGDELIMITER ':' 787c478bd9Sstevel@tonic-gate #define ARGDELIMITER ' ' 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate /* 817c478bd9Sstevel@tonic-gate * avoid malloc which causes certain applications to crash 827c478bd9Sstevel@tonic-gate */ 837c478bd9Sstevel@tonic-gate static char lbuf[MAXLINELEN]; 847c478bd9Sstevel@tonic-gate static char pbuf[MAXPATHLEN]; 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate #ifdef MADVDEBUG 877c478bd9Sstevel@tonic-gate #define ENV_MADVDEBUG "MADVDEBUG" 887c478bd9Sstevel@tonic-gate #define MADVPRINT(x, y) if (madvdebug & x) (void) fprintf y; 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate static int madvdebug = 0; 917c478bd9Sstevel@tonic-gate #else 927c478bd9Sstevel@tonic-gate #define MADVPRINT(x, y) 937c478bd9Sstevel@tonic-gate #endif 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate /* 967c478bd9Sstevel@tonic-gate * advice options 977c478bd9Sstevel@tonic-gate */ 987c478bd9Sstevel@tonic-gate static char *legal_optstr[] = { 997c478bd9Sstevel@tonic-gate "madv", 1007c478bd9Sstevel@tonic-gate "heap", 1017c478bd9Sstevel@tonic-gate "shm", 1027c478bd9Sstevel@tonic-gate "ism", 1037c478bd9Sstevel@tonic-gate "dism", 1047c478bd9Sstevel@tonic-gate "map", 1057c478bd9Sstevel@tonic-gate "mapshared", 1067c478bd9Sstevel@tonic-gate "mapprivate", 1077c478bd9Sstevel@tonic-gate "mapanon", 1087c478bd9Sstevel@tonic-gate NULL 1097c478bd9Sstevel@tonic-gate }; 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate enum optenum { 1127c478bd9Sstevel@tonic-gate OPT_MADV, 1137c478bd9Sstevel@tonic-gate OPT_HEAP, 1147c478bd9Sstevel@tonic-gate OPT_SHM, 1157c478bd9Sstevel@tonic-gate OPT_ISM, 1167c478bd9Sstevel@tonic-gate OPT_DISM, 1177c478bd9Sstevel@tonic-gate OPT_MAP, 1187c478bd9Sstevel@tonic-gate OPT_MAPSHARED, 1197c478bd9Sstevel@tonic-gate OPT_MAPPRIVATE, 1207c478bd9Sstevel@tonic-gate OPT_MAPANON 1217c478bd9Sstevel@tonic-gate }; 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate /* 1247c478bd9Sstevel@tonic-gate * Advice values 1257c478bd9Sstevel@tonic-gate * These need to correspond to the order of the MADV_ flags in mman.h 1267c478bd9Sstevel@tonic-gate * since the position infers the value for the flag. 1277c478bd9Sstevel@tonic-gate */ 1287c478bd9Sstevel@tonic-gate static char *legal_madvice[] = { 1297c478bd9Sstevel@tonic-gate "normal", 1307c478bd9Sstevel@tonic-gate "random", 1317c478bd9Sstevel@tonic-gate "sequential", 1327c478bd9Sstevel@tonic-gate "willneed_NOT_SUPPORTED!", 1337c478bd9Sstevel@tonic-gate "dontneed_NOT_SUPPORTED!", 1347c478bd9Sstevel@tonic-gate "free_NOT_SUPPORTED!", 1357c478bd9Sstevel@tonic-gate "access_default", 1367c478bd9Sstevel@tonic-gate "access_lwp", 1377c478bd9Sstevel@tonic-gate "access_many", 1387c478bd9Sstevel@tonic-gate NULL 1397c478bd9Sstevel@tonic-gate }; 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 1427c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 1437c478bd9Sstevel@tonic-gate #endif 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/ 1467c478bd9Sstevel@tonic-gate static void 1477c478bd9Sstevel@tonic-gate madverr(FILE *fp, char *fmt, ...) 1487c478bd9Sstevel@tonic-gate { 1497c478bd9Sstevel@tonic-gate va_list ap; 1507c478bd9Sstevel@tonic-gate va_start(ap, fmt); 1517c478bd9Sstevel@tonic-gate if (fp) 1527c478bd9Sstevel@tonic-gate (void) vfprintf(fp, fmt, ap); 1537c478bd9Sstevel@tonic-gate else 1547c478bd9Sstevel@tonic-gate vsyslog(LOG_ERR, fmt, ap); 1557c478bd9Sstevel@tonic-gate va_end(ap); 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate /* 1597c478bd9Sstevel@tonic-gate * Return the pointer to the fully-resolved path name of the process's 1607c478bd9Sstevel@tonic-gate * executable file obtained from the AT_SUN_EXECNAME aux vector entry. 1617c478bd9Sstevel@tonic-gate */ 1627c478bd9Sstevel@tonic-gate static const char * 1637c478bd9Sstevel@tonic-gate mygetexecname(void) 1647c478bd9Sstevel@tonic-gate { 1657c478bd9Sstevel@tonic-gate const char *execname = NULL; 1667c478bd9Sstevel@tonic-gate static auxv_t auxb; 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate /* 1697c478bd9Sstevel@tonic-gate * The first time through, read the initial aux vector that was 1707c478bd9Sstevel@tonic-gate * passed to the process at exec(2). Only do this once. 1717c478bd9Sstevel@tonic-gate */ 1727c478bd9Sstevel@tonic-gate int fd = open("/proc/self/auxv", O_RDONLY); 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate if (fd >= 0) { 1757c478bd9Sstevel@tonic-gate while (read(fd, &auxb, sizeof (auxv_t)) == sizeof (auxv_t)) { 1767c478bd9Sstevel@tonic-gate if (auxb.a_type == AT_SUN_EXECNAME) { 1777c478bd9Sstevel@tonic-gate execname = auxb.a_un.a_ptr; 1787c478bd9Sstevel@tonic-gate break; 1797c478bd9Sstevel@tonic-gate } 1807c478bd9Sstevel@tonic-gate } 1817c478bd9Sstevel@tonic-gate (void) close(fd); 1827c478bd9Sstevel@tonic-gate } 1837c478bd9Sstevel@tonic-gate return (execname); 1847c478bd9Sstevel@tonic-gate } 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate /* 1877c478bd9Sstevel@tonic-gate * Return the process's current brk base and size. 1887c478bd9Sstevel@tonic-gate */ 1897c478bd9Sstevel@tonic-gate static int 1907c478bd9Sstevel@tonic-gate mygetbrk(uintptr_t *base, size_t *size) 1917c478bd9Sstevel@tonic-gate { 1927c478bd9Sstevel@tonic-gate int fd; 1937c478bd9Sstevel@tonic-gate pstatus_t ps; 1947c478bd9Sstevel@tonic-gate int rc; 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate fd = open("/proc/self/status", O_RDONLY); 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate if (fd >= 0) { 1997c478bd9Sstevel@tonic-gate if (read(fd, &ps, sizeof (ps)) == sizeof (ps)) { 2007c478bd9Sstevel@tonic-gate *base = ps.pr_brkbase; 2017c478bd9Sstevel@tonic-gate *size = ps.pr_brksize; 2027c478bd9Sstevel@tonic-gate rc = 0; 2037c478bd9Sstevel@tonic-gate } else { 2047c478bd9Sstevel@tonic-gate rc = errno; 2057c478bd9Sstevel@tonic-gate } 2067c478bd9Sstevel@tonic-gate (void) close(fd); 2077c478bd9Sstevel@tonic-gate } else { 2087c478bd9Sstevel@tonic-gate rc = errno; 2097c478bd9Sstevel@tonic-gate } 2107c478bd9Sstevel@tonic-gate return (rc); 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate /* 2147c478bd9Sstevel@tonic-gate * Check if exec name matches cfgname found in madv cfg file. 2157c478bd9Sstevel@tonic-gate */ 2167c478bd9Sstevel@tonic-gate static int 2177c478bd9Sstevel@tonic-gate fnmatch(const char *execname, char *cfgname, char *cwd) 2187c478bd9Sstevel@tonic-gate { 2197c478bd9Sstevel@tonic-gate const char *ename; 2207c478bd9Sstevel@tonic-gate int rc; 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate /* cfgname should not have a '/' unless it begins with one */ 2237c478bd9Sstevel@tonic-gate if (cfgname[0] == '/') { 2247c478bd9Sstevel@tonic-gate /* 2257c478bd9Sstevel@tonic-gate * if execname does not begin with a '/', prepend the 2267c478bd9Sstevel@tonic-gate * current directory. 2277c478bd9Sstevel@tonic-gate */ 2287c478bd9Sstevel@tonic-gate if (execname[0] != '/') { 2297c478bd9Sstevel@tonic-gate ename = (const char *)strcat(cwd, execname); 2307c478bd9Sstevel@tonic-gate } else 2317c478bd9Sstevel@tonic-gate ename = execname; 2327c478bd9Sstevel@tonic-gate } else { /* simple cfg name */ 2337c478bd9Sstevel@tonic-gate if (ename = strrchr(execname, '/')) 2347c478bd9Sstevel@tonic-gate /* execname is a path name - get the base name */ 2357c478bd9Sstevel@tonic-gate ename++; 2367c478bd9Sstevel@tonic-gate else 2377c478bd9Sstevel@tonic-gate ename = execname; 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate rc = gmatch(ename, cfgname); 2407c478bd9Sstevel@tonic-gate MADVPRINT(2, (stderr, "gmatch: %s %s %s %d\n", 2417c478bd9Sstevel@tonic-gate cfgname, ename, execname, rc)); 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate return (rc); 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate /* 2477c478bd9Sstevel@tonic-gate * Check if string matches any of exec arguments. 2487c478bd9Sstevel@tonic-gate */ 2497c478bd9Sstevel@tonic-gate static int 2507c478bd9Sstevel@tonic-gate argmatch(char *str) 2517c478bd9Sstevel@tonic-gate { 2527c478bd9Sstevel@tonic-gate int fd; 2537c478bd9Sstevel@tonic-gate psinfo_t pi; 2547c478bd9Sstevel@tonic-gate int rc = 0; 2557c478bd9Sstevel@tonic-gate int arg; 2567c478bd9Sstevel@tonic-gate char **argv; 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate fd = open("/proc/self/psinfo", O_RDONLY); 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate if (fd >= 0) { 2617c478bd9Sstevel@tonic-gate if (read(fd, &pi, sizeof (pi)) == sizeof (pi)) { 2627c478bd9Sstevel@tonic-gate argv = (char **)pi.pr_argv; 2637c478bd9Sstevel@tonic-gate argv++; 2647c478bd9Sstevel@tonic-gate MADVPRINT(2, (stderr, "argmatch: %s ", str)); 2657c478bd9Sstevel@tonic-gate for (arg = 1; arg < pi.pr_argc; arg++, argv++) { 2667c478bd9Sstevel@tonic-gate if (rc = gmatch(*argv, str)) { 2677c478bd9Sstevel@tonic-gate MADVPRINT(2, (stderr, "%s ", *argv)); 2687c478bd9Sstevel@tonic-gate break; 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate MADVPRINT(2, (stderr, "%d\n", rc)); 2727c478bd9Sstevel@tonic-gate } else { 2737c478bd9Sstevel@tonic-gate madverr(errfp, dgettext(TEXT_DOMAIN, 2747c478bd9Sstevel@tonic-gate "%s: /proc/self/psinfo read failed [%s]\n"), 2757c478bd9Sstevel@tonic-gate madvident, strerror(errno)); 2767c478bd9Sstevel@tonic-gate } 2777c478bd9Sstevel@tonic-gate (void) close(fd); 2787c478bd9Sstevel@tonic-gate } else { 2797c478bd9Sstevel@tonic-gate madverr(errfp, dgettext(TEXT_DOMAIN, 2807c478bd9Sstevel@tonic-gate "%s: /proc/self/psinfo open failed [%s]\n"), 2817c478bd9Sstevel@tonic-gate madvident, strerror(errno)); 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate return (rc); 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate static int 2877c478bd9Sstevel@tonic-gate empty(char *str) 2887c478bd9Sstevel@tonic-gate { 2897c478bd9Sstevel@tonic-gate char c; 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate while ((c = *str) == '\n' || c == ' ' || c == '\t') 2927c478bd9Sstevel@tonic-gate str++; 2937c478bd9Sstevel@tonic-gate return (*str == '\0'); 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate static int 2977c478bd9Sstevel@tonic-gate strtoadv(char *advstr) 2987c478bd9Sstevel@tonic-gate { 2997c478bd9Sstevel@tonic-gate char *dummy, *locstr = advstr; 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate return (getsubopt(&locstr, legal_madvice, &dummy)); 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate static void 3057c478bd9Sstevel@tonic-gate advice_opts(char *optstr, const char *execname, char *cfgfile, int lineno) 3067c478bd9Sstevel@tonic-gate { 3077c478bd9Sstevel@tonic-gate char *value; 3087c478bd9Sstevel@tonic-gate int opt; 3097c478bd9Sstevel@tonic-gate int advice = 0; 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate while (*optstr != '\0') { 3127c478bd9Sstevel@tonic-gate opt = getsubopt(&optstr, legal_optstr, &value); 3137c478bd9Sstevel@tonic-gate if (opt < 0) { 3147c478bd9Sstevel@tonic-gate madverr(errfp, dgettext(TEXT_DOMAIN, 3157c478bd9Sstevel@tonic-gate "%s: invalid advice option (%s)" 3167c478bd9Sstevel@tonic-gate " for %s - cfgfile: %s, line: %d\n"), 3177c478bd9Sstevel@tonic-gate madvident, value, execname, cfgfile, lineno); 3187c478bd9Sstevel@tonic-gate break; 3197c478bd9Sstevel@tonic-gate } else if (!value) { 3207c478bd9Sstevel@tonic-gate madverr(errfp, dgettext(TEXT_DOMAIN, 3217c478bd9Sstevel@tonic-gate "%s: option missing advice" 3227c478bd9Sstevel@tonic-gate " for %s - cfgfile: %s, line: %d\n"), 3237c478bd9Sstevel@tonic-gate madvident, execname, cfgfile, lineno); 3247c478bd9Sstevel@tonic-gate break; 3257c478bd9Sstevel@tonic-gate } 3267c478bd9Sstevel@tonic-gate advice = strtoadv(value); 3277c478bd9Sstevel@tonic-gate if (advice < 0) { 3287c478bd9Sstevel@tonic-gate madverr(errfp, dgettext(TEXT_DOMAIN, 3297c478bd9Sstevel@tonic-gate "%s: invalid advice specified (%s)" 3307c478bd9Sstevel@tonic-gate " for %s - cfgfile: %s, line: %d\n"), 3317c478bd9Sstevel@tonic-gate madvident, value, execname, cfgfile, lineno); 3327c478bd9Sstevel@tonic-gate break; 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate switch (opt) { 3357c478bd9Sstevel@tonic-gate case OPT_MADV: 3367c478bd9Sstevel@tonic-gate advice_all = advice; 3377c478bd9Sstevel@tonic-gate break; 3387c478bd9Sstevel@tonic-gate case OPT_HEAP: 3397c478bd9Sstevel@tonic-gate if (advice_heap < 0) { 3407c478bd9Sstevel@tonic-gate advice_heap = advice; 3417c478bd9Sstevel@tonic-gate } else { 3427c478bd9Sstevel@tonic-gate madverr(errfp, dgettext(TEXT_DOMAIN, 3437c478bd9Sstevel@tonic-gate "%s: duplicate advice specified " 3447c478bd9Sstevel@tonic-gate "(%s) for %s - cfgfile: %s, line: %d\n"), 3457c478bd9Sstevel@tonic-gate madvident, value, execname, cfgfile, 3467c478bd9Sstevel@tonic-gate lineno); 3477c478bd9Sstevel@tonic-gate } 3487c478bd9Sstevel@tonic-gate break; 3497c478bd9Sstevel@tonic-gate case OPT_SHM: 3507c478bd9Sstevel@tonic-gate if (advice_shm < 0) { 3517c478bd9Sstevel@tonic-gate advice_shm = advice; 3527c478bd9Sstevel@tonic-gate } else { 3537c478bd9Sstevel@tonic-gate madverr(errfp, dgettext(TEXT_DOMAIN, 3547c478bd9Sstevel@tonic-gate "%s: duplicate advice specified " 3557c478bd9Sstevel@tonic-gate "(%s) for %s - cfgfile: %s, line: %d\n"), 3567c478bd9Sstevel@tonic-gate madvident, value, execname, cfgfile, 3577c478bd9Sstevel@tonic-gate lineno); 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate break; 3607c478bd9Sstevel@tonic-gate case OPT_ISM: 3617c478bd9Sstevel@tonic-gate if (advice_ism < 0) { 3627c478bd9Sstevel@tonic-gate advice_ism = advice; 3637c478bd9Sstevel@tonic-gate } else { 3647c478bd9Sstevel@tonic-gate madverr(errfp, dgettext(TEXT_DOMAIN, 3657c478bd9Sstevel@tonic-gate "%s: duplicate advice specified " 3667c478bd9Sstevel@tonic-gate "(%s) for %s - cfgfile: %s, line: %d\n"), 3677c478bd9Sstevel@tonic-gate madvident, value, execname, cfgfile, 3687c478bd9Sstevel@tonic-gate lineno); 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate break; 3717c478bd9Sstevel@tonic-gate case OPT_DISM: 3727c478bd9Sstevel@tonic-gate if (advice_dism < 0) { 3737c478bd9Sstevel@tonic-gate advice_dism = advice; 3747c478bd9Sstevel@tonic-gate } else { 3757c478bd9Sstevel@tonic-gate madverr(errfp, dgettext(TEXT_DOMAIN, 3767c478bd9Sstevel@tonic-gate "%s: duplicate advice specified " 3777c478bd9Sstevel@tonic-gate "(%s) for %s - cfgfile: %s, line: %d\n"), 3787c478bd9Sstevel@tonic-gate madvident, value, execname, cfgfile, 3797c478bd9Sstevel@tonic-gate lineno); 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate break; 3827c478bd9Sstevel@tonic-gate case OPT_MAP: 3837c478bd9Sstevel@tonic-gate if (advice_map < 0) { 3847c478bd9Sstevel@tonic-gate advice_map = advice; 3857c478bd9Sstevel@tonic-gate } else { 3867c478bd9Sstevel@tonic-gate madverr(errfp, dgettext(TEXT_DOMAIN, 3877c478bd9Sstevel@tonic-gate "%s: duplicate advice specified " 3887c478bd9Sstevel@tonic-gate "(%s) for %s - cfgfile: %s, line: %d\n"), 3897c478bd9Sstevel@tonic-gate madvident, value, execname, cfgfile, 3907c478bd9Sstevel@tonic-gate lineno); 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate break; 3937c478bd9Sstevel@tonic-gate case OPT_MAPSHARED: 3947c478bd9Sstevel@tonic-gate if (advice_mapshared < 0) { 3957c478bd9Sstevel@tonic-gate advice_mapshared = advice; 3967c478bd9Sstevel@tonic-gate } else { 3977c478bd9Sstevel@tonic-gate madverr(errfp, dgettext(TEXT_DOMAIN, 3987c478bd9Sstevel@tonic-gate "%s: duplicate advice specified " 3997c478bd9Sstevel@tonic-gate "(%s) for %s - cfgfile: %s, line: %d\n"), 4007c478bd9Sstevel@tonic-gate madvident, value, execname, cfgfile, 4017c478bd9Sstevel@tonic-gate lineno); 4027c478bd9Sstevel@tonic-gate } 4037c478bd9Sstevel@tonic-gate break; 4047c478bd9Sstevel@tonic-gate case OPT_MAPPRIVATE: 4057c478bd9Sstevel@tonic-gate if (advice_mapprivate < 0) { 4067c478bd9Sstevel@tonic-gate advice_mapprivate = advice; 4077c478bd9Sstevel@tonic-gate } else { 4087c478bd9Sstevel@tonic-gate madverr(errfp, dgettext(TEXT_DOMAIN, 4097c478bd9Sstevel@tonic-gate "%s: duplicate advice specified " 4107c478bd9Sstevel@tonic-gate "(%s) for %s - cfgfile: %s, line: %d\n"), 4117c478bd9Sstevel@tonic-gate madvident, value, execname, cfgfile, 4127c478bd9Sstevel@tonic-gate lineno); 4137c478bd9Sstevel@tonic-gate } 4147c478bd9Sstevel@tonic-gate break; 4157c478bd9Sstevel@tonic-gate case OPT_MAPANON: 4167c478bd9Sstevel@tonic-gate if (advice_mapanon < 0) { 4177c478bd9Sstevel@tonic-gate advice_mapanon = advice; 4187c478bd9Sstevel@tonic-gate } else { 4197c478bd9Sstevel@tonic-gate madverr(errfp, dgettext(TEXT_DOMAIN, 4207c478bd9Sstevel@tonic-gate "%s: duplicate advice specified " 4217c478bd9Sstevel@tonic-gate "(%s) for %s - cfgfile: %s, line: %d\n"), 4227c478bd9Sstevel@tonic-gate madvident, value, execname, cfgfile, 4237c478bd9Sstevel@tonic-gate lineno); 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate break; 4267c478bd9Sstevel@tonic-gate default: 4277c478bd9Sstevel@tonic-gate madverr(errfp, dgettext(TEXT_DOMAIN, 4287c478bd9Sstevel@tonic-gate "%s: invalid advice option (%s)" 4297c478bd9Sstevel@tonic-gate " for %s - cfgfile: %s, line: %d\n"), 4307c478bd9Sstevel@tonic-gate madvident, value, execname, cfgfile, lineno); 4317c478bd9Sstevel@tonic-gate break; 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate } 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate static void 4377c478bd9Sstevel@tonic-gate __madvmain() 4387c478bd9Sstevel@tonic-gate { 4397c478bd9Sstevel@tonic-gate char *cfgfile, *errfile; 4407c478bd9Sstevel@tonic-gate FILE *fp = NULL; 4417c478bd9Sstevel@tonic-gate const char *execname; 4427c478bd9Sstevel@tonic-gate char *cwd; 4437c478bd9Sstevel@tonic-gate int cwdlen; 4447c478bd9Sstevel@tonic-gate char *tok, *tokadv, *tokarg; 4457c478bd9Sstevel@tonic-gate char *str, *envadv; 4467c478bd9Sstevel@tonic-gate int lineno = 0; 4477c478bd9Sstevel@tonic-gate int advice; 4487c478bd9Sstevel@tonic-gate uintptr_t brkbase, brkend; 4497c478bd9Sstevel@tonic-gate size_t brksize; 4507c478bd9Sstevel@tonic-gate int rc; 4517c478bd9Sstevel@tonic-gate char *locale; 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate /* 4547c478bd9Sstevel@tonic-gate * If a private error file is indicated then set the locale 4557c478bd9Sstevel@tonic-gate * for error messages for the duration of this routine. 4567c478bd9Sstevel@tonic-gate * Error messages destined for syslog should not be translated 4577c478bd9Sstevel@tonic-gate * and thus come from the default C locale. 4587c478bd9Sstevel@tonic-gate */ 4597c478bd9Sstevel@tonic-gate if ((errfile = getenv(ENV_MADVERRFILE)) != NULL) { 460*004388ebScasper errfp = fopen(errfile, "aF"); 4617c478bd9Sstevel@tonic-gate if (errfp) { 4627c478bd9Sstevel@tonic-gate locale = setlocale(LC_MESSAGES, ""); 4637c478bd9Sstevel@tonic-gate } else { 4647c478bd9Sstevel@tonic-gate madverr(NULL, dgettext(TEXT_DOMAIN, 4657c478bd9Sstevel@tonic-gate "%s: cannot open error file: %s [%s]\n"), 4667c478bd9Sstevel@tonic-gate madvident, errfile, strerror(errno)); 4677c478bd9Sstevel@tonic-gate } 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate #ifdef MADVDEBUG 4717c478bd9Sstevel@tonic-gate if (str = getenv(ENV_MADVDEBUG)) 4727c478bd9Sstevel@tonic-gate madvdebug = atoi(str); 4737c478bd9Sstevel@tonic-gate #endif 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate if (envadv = getenv(ENV_MADV)) { 4767c478bd9Sstevel@tonic-gate if ((advice = strtoadv(envadv)) >= 0) 4777c478bd9Sstevel@tonic-gate advice_all = advice; 4787c478bd9Sstevel@tonic-gate else 4797c478bd9Sstevel@tonic-gate madverr(errfp, dgettext(TEXT_DOMAIN, 4807c478bd9Sstevel@tonic-gate "%s: invalid advice specified: MADV=%s\n"), 4817c478bd9Sstevel@tonic-gate madvident, envadv); 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate /* 4857c478bd9Sstevel@tonic-gate * Open specified cfg file or default one. 4867c478bd9Sstevel@tonic-gate */ 4877c478bd9Sstevel@tonic-gate if (cfgfile = getenv(ENV_MADVCFGFILE)) { 488*004388ebScasper fp = fopen(cfgfile, "rF"); 4897c478bd9Sstevel@tonic-gate if (!fp) { 4907c478bd9Sstevel@tonic-gate madverr(errfp, dgettext(TEXT_DOMAIN, 4917c478bd9Sstevel@tonic-gate "%s: cannot open configuration file: %s [%s]\n"), 4927c478bd9Sstevel@tonic-gate madvident, cfgfile, strerror(errno)); 4937c478bd9Sstevel@tonic-gate } 4947c478bd9Sstevel@tonic-gate } else { 4957c478bd9Sstevel@tonic-gate cfgfile = DEF_MADVCFGFILE; 496*004388ebScasper fp = fopen(cfgfile, "rF"); 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate if (fp) { 5007c478bd9Sstevel@tonic-gate execname = mygetexecname(); 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate cwd = getcwd(pbuf, MAXPATHLEN); 5037c478bd9Sstevel@tonic-gate if (!cwd) 5047c478bd9Sstevel@tonic-gate return; 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate cwd = strcat(cwd, "/"); 5077c478bd9Sstevel@tonic-gate cwdlen = strlen(cwd); 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate while (fgets(lbuf, MAXLINELEN, fp)) { 5107c478bd9Sstevel@tonic-gate lineno++; 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate /* 5137c478bd9Sstevel@tonic-gate * Make sure line wasn't truncated. 5147c478bd9Sstevel@tonic-gate */ 5157c478bd9Sstevel@tonic-gate if (strlen(lbuf) >= MAXLINELEN - 1) { 5167c478bd9Sstevel@tonic-gate madverr(errfp, dgettext(TEXT_DOMAIN, 5177c478bd9Sstevel@tonic-gate "%s: invalid entry, " 5187c478bd9Sstevel@tonic-gate "line too long - cfgfile:" 5197c478bd9Sstevel@tonic-gate " %s, line: %d\n"), 5207c478bd9Sstevel@tonic-gate madvident, cfgfile, lineno); 5217c478bd9Sstevel@tonic-gate continue; 5227c478bd9Sstevel@tonic-gate } 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate if (empty(lbuf)) 5257c478bd9Sstevel@tonic-gate continue; 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate /* 5287c478bd9Sstevel@tonic-gate * Get advice options. 5297c478bd9Sstevel@tonic-gate * Parse right to left in case delimiter is in name. 5307c478bd9Sstevel@tonic-gate */ 5317c478bd9Sstevel@tonic-gate if (!(tokadv = strrchr(lbuf, CFGDELIMITER))) { 5327c478bd9Sstevel@tonic-gate madverr(errfp, dgettext(TEXT_DOMAIN, 5337c478bd9Sstevel@tonic-gate "%s: no delimiter specified - cfgfile:" 5347c478bd9Sstevel@tonic-gate " %s, line: %d\n"), 5357c478bd9Sstevel@tonic-gate madvident, cfgfile, lineno); 5367c478bd9Sstevel@tonic-gate continue; 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate *tokadv++ = '\0'; 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate /* 5417c478bd9Sstevel@tonic-gate * Remove newline from end of advice options. 5427c478bd9Sstevel@tonic-gate */ 5437c478bd9Sstevel@tonic-gate if (str = strrchr(tokadv, '\n')) 5447c478bd9Sstevel@tonic-gate *str = '\0'; 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate /* 5477c478bd9Sstevel@tonic-gate * Get optional argument string. 5487c478bd9Sstevel@tonic-gate */ 5497c478bd9Sstevel@tonic-gate if (tokarg = strrchr(lbuf, ARGDELIMITER)) { 5507c478bd9Sstevel@tonic-gate *tokarg++ = '\0'; 5517c478bd9Sstevel@tonic-gate } 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate /* 5547c478bd9Sstevel@tonic-gate * Compare exec name. 5557c478bd9Sstevel@tonic-gate */ 5567c478bd9Sstevel@tonic-gate tok = lbuf; 5577c478bd9Sstevel@tonic-gate if (!fnmatch(execname, tok, cwd)) { 5587c478bd9Sstevel@tonic-gate tokadv = tokarg = NULL; 5597c478bd9Sstevel@tonic-gate cwd[cwdlen] = '\0'; 5607c478bd9Sstevel@tonic-gate continue; 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate /* 5647c478bd9Sstevel@tonic-gate * Compare arguments if argument string specified. 5657c478bd9Sstevel@tonic-gate */ 5667c478bd9Sstevel@tonic-gate if (tokarg && 5677c478bd9Sstevel@tonic-gate !empty(tokarg) && 5687c478bd9Sstevel@tonic-gate !argmatch(tokarg)) { 5697c478bd9Sstevel@tonic-gate tokadv = tokarg = NULL; 5707c478bd9Sstevel@tonic-gate cwd[cwdlen] = '\0'; 5717c478bd9Sstevel@tonic-gate continue; 5727c478bd9Sstevel@tonic-gate } 5737c478bd9Sstevel@tonic-gate 5747c478bd9Sstevel@tonic-gate /* 5757c478bd9Sstevel@tonic-gate * Parse advice options. 5767c478bd9Sstevel@tonic-gate * If empty, any advice from ENV_MADV is reset. 5777c478bd9Sstevel@tonic-gate */ 5787c478bd9Sstevel@tonic-gate if (empty(tokadv)) { 5797c478bd9Sstevel@tonic-gate advice_all = -1; 5807c478bd9Sstevel@tonic-gate } else { 5817c478bd9Sstevel@tonic-gate advice_opts(tokadv, execname, cfgfile, lineno); 5827c478bd9Sstevel@tonic-gate } 5837c478bd9Sstevel@tonic-gate break; 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate (void) fclose(fp); 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate /* 5897c478bd9Sstevel@tonic-gate * Pagesize needed for proper aligning by brk interpose. 5907c478bd9Sstevel@tonic-gate */ 5917c478bd9Sstevel@tonic-gate pagesize = sysconf(_SC_PAGESIZE); 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate /* 5947c478bd9Sstevel@tonic-gate * Apply global advice if set. 5957c478bd9Sstevel@tonic-gate * Specific options in the cfgfile take precedence. 5967c478bd9Sstevel@tonic-gate */ 5977c478bd9Sstevel@tonic-gate if (advice_all >= 0) { 5987c478bd9Sstevel@tonic-gate if (advice_heap < 0) 5997c478bd9Sstevel@tonic-gate advice_heap = advice_all; 6007c478bd9Sstevel@tonic-gate if (advice_shm < 0) 6017c478bd9Sstevel@tonic-gate advice_shm = advice_all; 6027c478bd9Sstevel@tonic-gate if (advice_map < 0) 6037c478bd9Sstevel@tonic-gate advice_map = advice_all; 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate MADVPRINT(2, (stderr, "advice_all %d\n", advice_all)); 6077c478bd9Sstevel@tonic-gate MADVPRINT(2, (stderr, "advice_heap %d\n", advice_heap)); 6087c478bd9Sstevel@tonic-gate MADVPRINT(2, (stderr, "advice_shm %d\n", advice_shm)); 6097c478bd9Sstevel@tonic-gate MADVPRINT(2, (stderr, "advice_ism %d\n", advice_ism)); 6107c478bd9Sstevel@tonic-gate MADVPRINT(2, (stderr, "advice_dism %d\n", advice_dism)); 6117c478bd9Sstevel@tonic-gate MADVPRINT(2, (stderr, "advice_map %d\n", advice_map)); 6127c478bd9Sstevel@tonic-gate MADVPRINT(2, (stderr, "advice_mapshared %d\n", advice_mapshared)); 6137c478bd9Sstevel@tonic-gate MADVPRINT(2, (stderr, "advice_mapprivate %d\n", advice_mapprivate)); 6147c478bd9Sstevel@tonic-gate MADVPRINT(2, (stderr, "advice_mapanon %d\n", advice_mapanon)); 6157c478bd9Sstevel@tonic-gate 6167c478bd9Sstevel@tonic-gate /* 6177c478bd9Sstevel@tonic-gate * If heap advice is specified, apply it to the existing heap. 6187c478bd9Sstevel@tonic-gate * As the heap grows the kernel applies the advice automatically 6197c478bd9Sstevel@tonic-gate * to new portions of the heap. 6207c478bd9Sstevel@tonic-gate */ 6217c478bd9Sstevel@tonic-gate if (advice_heap >= 0) { 6227c478bd9Sstevel@tonic-gate if (rc = mygetbrk(&brkbase, &brksize)) { 6237c478bd9Sstevel@tonic-gate madverr(errfp, dgettext(TEXT_DOMAIN, 6247c478bd9Sstevel@tonic-gate "%s: /proc/self/status read failed [%s]\n"), 6257c478bd9Sstevel@tonic-gate madvident, strerror(rc)); 6267c478bd9Sstevel@tonic-gate } else { 6277c478bd9Sstevel@tonic-gate MADVPRINT(4, (stderr, "brkbase 0x%x brksize 0x%x\n", 6287c478bd9Sstevel@tonic-gate brkbase, brksize)); 6297c478bd9Sstevel@tonic-gate /* 6307c478bd9Sstevel@tonic-gate * Align start address for memcntl and apply advice 6317c478bd9Sstevel@tonic-gate * on full pages of heap. Create a page of heap if 6327c478bd9Sstevel@tonic-gate * it does not already exist. 6337c478bd9Sstevel@tonic-gate */ 6347c478bd9Sstevel@tonic-gate brkend = roundup(brkbase+brksize, pagesize); 6357c478bd9Sstevel@tonic-gate brkbase = roundup(brkbase, pagesize); 6367c478bd9Sstevel@tonic-gate brksize = brkend - brkbase; 6377c478bd9Sstevel@tonic-gate if (brksize < pagesize) { 6387c478bd9Sstevel@tonic-gate if (sbrk(pagesize) == (void *)-1) { 6397c478bd9Sstevel@tonic-gate madverr(errfp, dgettext(TEXT_DOMAIN, 6407c478bd9Sstevel@tonic-gate "%s: sbrk failed [%s]\n"), 6417c478bd9Sstevel@tonic-gate madvident, strerror(errno)); 6427c478bd9Sstevel@tonic-gate goto out; 6437c478bd9Sstevel@tonic-gate } 6447c478bd9Sstevel@tonic-gate brksize = pagesize; 6457c478bd9Sstevel@tonic-gate } 6467c478bd9Sstevel@tonic-gate MADVPRINT(1, (stderr, "heap advice: 0x%x 0x%x %d\n", 6477c478bd9Sstevel@tonic-gate brkbase, brksize, advice_heap)); 6487c478bd9Sstevel@tonic-gate if (memcntl((caddr_t)brkbase, brksize, MC_ADVISE, 6497c478bd9Sstevel@tonic-gate (caddr_t)(intptr_t)advice_heap, 0, 0) < 0) { 6507c478bd9Sstevel@tonic-gate madverr(errfp, dgettext(TEXT_DOMAIN, 6517c478bd9Sstevel@tonic-gate "%s: memcntl() failed [%s]: heap advice\n"), 6527c478bd9Sstevel@tonic-gate madvident, strerror(errno)); 6537c478bd9Sstevel@tonic-gate } 6547c478bd9Sstevel@tonic-gate } 6557c478bd9Sstevel@tonic-gate } 6567c478bd9Sstevel@tonic-gate out: 6577c478bd9Sstevel@tonic-gate if (errfp) { 6587c478bd9Sstevel@tonic-gate (void) fclose(errfp); 6597c478bd9Sstevel@tonic-gate (void) setlocale(LC_MESSAGES, locale); 6607c478bd9Sstevel@tonic-gate } else { 6617c478bd9Sstevel@tonic-gate /* close log file: no-op if nothing logged to syslog */ 6627c478bd9Sstevel@tonic-gate closelog(); 6637c478bd9Sstevel@tonic-gate } 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate } 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate /* 6687c478bd9Sstevel@tonic-gate * shmat interpose 6697c478bd9Sstevel@tonic-gate */ 6707c478bd9Sstevel@tonic-gate void * 6717c478bd9Sstevel@tonic-gate shmat(int shmid, const void *shmaddr, int shmflag) 6727c478bd9Sstevel@tonic-gate { 6737c478bd9Sstevel@tonic-gate static caddr_t (*shmatfunc)() = NULL; 6747c478bd9Sstevel@tonic-gate void *result; 6757c478bd9Sstevel@tonic-gate int advice = -1; 6767c478bd9Sstevel@tonic-gate struct shmid_ds mds; 6777c478bd9Sstevel@tonic-gate #ifdef MADVDEBUG 6787c478bd9Sstevel@tonic-gate int rc; 6797c478bd9Sstevel@tonic-gate #else 6807c478bd9Sstevel@tonic-gate /* LINTED */ 6817c478bd9Sstevel@tonic-gate int rc; 6827c478bd9Sstevel@tonic-gate #endif 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate if (!shmatfunc) { 6857c478bd9Sstevel@tonic-gate shmatfunc = (caddr_t (*)()) dlsym(RTLD_NEXT, "shmat"); 6867c478bd9Sstevel@tonic-gate assert(shmatfunc); 6877c478bd9Sstevel@tonic-gate } 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate result = shmatfunc(shmid, shmaddr, shmflag); 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate /* 6927c478bd9Sstevel@tonic-gate * Options ism, dism take precedence over option shm. 6937c478bd9Sstevel@tonic-gate */ 6947c478bd9Sstevel@tonic-gate if (advice_ism >= 0 && (shmflag & SHM_SHARE_MMU)) { 6957c478bd9Sstevel@tonic-gate advice = advice_ism; 6967c478bd9Sstevel@tonic-gate } else if (advice_dism >= 0 && (shmflag & SHM_PAGEABLE)) { 6977c478bd9Sstevel@tonic-gate advice = advice_dism; 6987c478bd9Sstevel@tonic-gate } else if (advice_shm >= 0) { 6997c478bd9Sstevel@tonic-gate advice = advice_shm; 7007c478bd9Sstevel@tonic-gate } 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate /* 7037c478bd9Sstevel@tonic-gate * Apply advice if specified and shmat succeeded. 7047c478bd9Sstevel@tonic-gate */ 7057c478bd9Sstevel@tonic-gate if (advice >= 0 && result != (void *)-1) { 7067c478bd9Sstevel@tonic-gate /* First determine segment size */ 7077c478bd9Sstevel@tonic-gate rc = shmctl(shmid, IPC_STAT, &mds); 7087c478bd9Sstevel@tonic-gate MADVPRINT(4, (stderr, "shmctl rc %d errno %d\n", 7097c478bd9Sstevel@tonic-gate strerror(errno))); 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate rc = memcntl(result, mds.shm_segsz, MC_ADVISE, 7127c478bd9Sstevel@tonic-gate (caddr_t)(intptr_t)advice, 0, 0); 7137c478bd9Sstevel@tonic-gate MADVPRINT(1, (stderr, 7147c478bd9Sstevel@tonic-gate "shmat advice: 0x%x 0x%x %d, rc %d errno %d\n", 7157c478bd9Sstevel@tonic-gate result, mds.shm_segsz, advice, rc, errno)); 7167c478bd9Sstevel@tonic-gate } 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate return (result); 7197c478bd9Sstevel@tonic-gate } 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate /* 7227c478bd9Sstevel@tonic-gate * mmap interpose 7237c478bd9Sstevel@tonic-gate */ 7247c478bd9Sstevel@tonic-gate caddr_t 7257c478bd9Sstevel@tonic-gate mmap(caddr_t addr, size_t len, int prot, int flags, int fd, off_t pos) 7267c478bd9Sstevel@tonic-gate { 7277c478bd9Sstevel@tonic-gate static caddr_t (*mmapfunc)() = NULL; 7287c478bd9Sstevel@tonic-gate caddr_t result; 7297c478bd9Sstevel@tonic-gate int advice = -1; 7307c478bd9Sstevel@tonic-gate #ifdef MADVDEBUG 7317c478bd9Sstevel@tonic-gate int rc; 7327c478bd9Sstevel@tonic-gate #else 7337c478bd9Sstevel@tonic-gate /* LINTED */ 7347c478bd9Sstevel@tonic-gate int rc; 7357c478bd9Sstevel@tonic-gate #endif 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate if (!mmapfunc) { 7387c478bd9Sstevel@tonic-gate mmapfunc = (caddr_t (*)()) dlsym(RTLD_NEXT, "mmap"); 7397c478bd9Sstevel@tonic-gate assert(mmapfunc); 7407c478bd9Sstevel@tonic-gate } 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate result = mmapfunc(addr, len, prot, flags, fd, pos); 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate /* 7457c478bd9Sstevel@tonic-gate * Option mapanon has highest precedence while option map 7467c478bd9Sstevel@tonic-gate * has lowest precedence. 7477c478bd9Sstevel@tonic-gate */ 7487c478bd9Sstevel@tonic-gate if (advice_mapanon >= 0 && (flags & MAP_ANON)) { 7497c478bd9Sstevel@tonic-gate advice = advice_mapanon; 7507c478bd9Sstevel@tonic-gate } else if (advice_mapshared >= 0 && (flags & MAP_SHARED)) { 7517c478bd9Sstevel@tonic-gate advice = advice_mapshared; 7527c478bd9Sstevel@tonic-gate } else if (advice_mapprivate >= 0 && (flags & MAP_PRIVATE)) { 7537c478bd9Sstevel@tonic-gate advice = advice_mapprivate; 7547c478bd9Sstevel@tonic-gate } else if (advice_map >= 0) { 7557c478bd9Sstevel@tonic-gate advice = advice_map; 7567c478bd9Sstevel@tonic-gate } 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate /* 7597c478bd9Sstevel@tonic-gate * Apply advice if specified and mmap succeeded. 7607c478bd9Sstevel@tonic-gate */ 7617c478bd9Sstevel@tonic-gate if (advice >= 0 && result != MAP_FAILED) { 7627c478bd9Sstevel@tonic-gate rc = memcntl(result, len, MC_ADVISE, 7637c478bd9Sstevel@tonic-gate (caddr_t)(intptr_t)advice, 0, 0); 7647c478bd9Sstevel@tonic-gate MADVPRINT(1, (stderr, 7657c478bd9Sstevel@tonic-gate "mmap advice: 0x%x 0x%x %d, rc %d errno %d\n", 7667c478bd9Sstevel@tonic-gate result, len, advice, rc, errno)); 7677c478bd9Sstevel@tonic-gate } 7687c478bd9Sstevel@tonic-gate 7697c478bd9Sstevel@tonic-gate return (result); 7707c478bd9Sstevel@tonic-gate } 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate #if !defined(_LP64) 7737c478bd9Sstevel@tonic-gate /* 7747c478bd9Sstevel@tonic-gate * mmap64 interpose 7757c478bd9Sstevel@tonic-gate */ 7767c478bd9Sstevel@tonic-gate caddr_t 7777c478bd9Sstevel@tonic-gate mmap64(caddr_t addr, size_t len, int prot, int flags, int fd, off64_t pos) 7787c478bd9Sstevel@tonic-gate { 7797c478bd9Sstevel@tonic-gate static caddr_t (*mmap64func)(); 7807c478bd9Sstevel@tonic-gate caddr_t result; 7817c478bd9Sstevel@tonic-gate int advice = -1; 7827c478bd9Sstevel@tonic-gate #ifdef MADVDEBUG 7837c478bd9Sstevel@tonic-gate int rc; 7847c478bd9Sstevel@tonic-gate #else 7857c478bd9Sstevel@tonic-gate /* LINTED */ 7867c478bd9Sstevel@tonic-gate int rc; 7877c478bd9Sstevel@tonic-gate #endif 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate if (!mmap64func) { 7907c478bd9Sstevel@tonic-gate mmap64func = (caddr_t (*)()) dlsym(RTLD_NEXT, "mmap64"); 7917c478bd9Sstevel@tonic-gate assert(mmap64func); 7927c478bd9Sstevel@tonic-gate } 7937c478bd9Sstevel@tonic-gate 7947c478bd9Sstevel@tonic-gate result = mmap64func(addr, len, prot, flags, fd, pos); 7957c478bd9Sstevel@tonic-gate 7967c478bd9Sstevel@tonic-gate /* 7977c478bd9Sstevel@tonic-gate * Option mapanon has highest precedence while option map 7987c478bd9Sstevel@tonic-gate * has lowest precedence. 7997c478bd9Sstevel@tonic-gate */ 8007c478bd9Sstevel@tonic-gate if (advice_mapanon >= 0 && (flags & MAP_ANON)) { 8017c478bd9Sstevel@tonic-gate advice = advice_mapanon; 8027c478bd9Sstevel@tonic-gate } else if (advice_mapshared >= 0 && (flags & MAP_SHARED)) { 8037c478bd9Sstevel@tonic-gate advice = advice_mapshared; 8047c478bd9Sstevel@tonic-gate } else if (advice_mapprivate >= 0 && (flags & MAP_PRIVATE)) { 8057c478bd9Sstevel@tonic-gate advice = advice_mapprivate; 8067c478bd9Sstevel@tonic-gate } else if (advice_map >= 0) { 8077c478bd9Sstevel@tonic-gate advice = advice_map; 8087c478bd9Sstevel@tonic-gate } 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate /* 8117c478bd9Sstevel@tonic-gate * Apply advice if specified and mmap succeeded. 8127c478bd9Sstevel@tonic-gate */ 8137c478bd9Sstevel@tonic-gate if (advice >= 0 && result != MAP_FAILED) { 8147c478bd9Sstevel@tonic-gate rc = memcntl(result, len, MC_ADVISE, (caddr_t)advice, 0, 0); 8157c478bd9Sstevel@tonic-gate MADVPRINT(1, (stderr, 8167c478bd9Sstevel@tonic-gate "mmap64 advice: 0x%x 0x%x %d, rc %d errno %d\n", 8177c478bd9Sstevel@tonic-gate result, len, advice, rc, errno)); 8187c478bd9Sstevel@tonic-gate } 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate return (result); 8217c478bd9Sstevel@tonic-gate } 8227c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 823