1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <strings.h> 32 #include <sys/shm.h> 33 #include <sys/mman.h> 34 #include <fcntl.h> 35 #include <stdlib.h> 36 #include <unistd.h> 37 #include <errno.h> 38 #include <sys/types.h> 39 #include <sys/stat.h> 40 #include <sys/auxv.h> 41 #include <stdarg.h> 42 #include <syslog.h> 43 #include <sys/param.h> 44 #include <sys/sysmacros.h> 45 #include <procfs.h> 46 #include <dlfcn.h> 47 #include <assert.h> 48 #include <libintl.h> 49 #include <locale.h> 50 51 extern int gmatch(const char *s, const char *p); 52 53 #pragma init(__madvmain) 54 55 static FILE *errfp = NULL; 56 static const char *madvident = "madv.so.1"; 57 static int pagesize; 58 static int advice_all = -1; 59 static int advice_heap = -1; 60 static int advice_shm = -1; 61 static int advice_ism = -1; 62 static int advice_dism = -1; 63 static int advice_map = -1; 64 static int advice_mapshared = -1; 65 static int advice_mapprivate = -1; 66 static int advice_mapanon = -1; 67 68 /* environment variables */ 69 70 #define ENV_MADV "MADV" 71 #define ENV_MADVCFGFILE "MADVCFGFILE" 72 #define ENV_MADVERRFILE "MADVERRFILE" 73 74 /* config file */ 75 76 #define DEF_MADVCFGFILE "/etc/madv.conf" 77 #define MAXLINELEN MAXPATHLEN + 64 78 #define CFGDELIMITER ':' 79 #define ARGDELIMITER ' ' 80 81 /* 82 * avoid malloc which causes certain applications to crash 83 */ 84 static char lbuf[MAXLINELEN]; 85 static char pbuf[MAXPATHLEN]; 86 87 #ifdef MADVDEBUG 88 #define ENV_MADVDEBUG "MADVDEBUG" 89 #define MADVPRINT(x, y) if (madvdebug & x) (void) fprintf y; 90 91 static int madvdebug = 0; 92 #else 93 #define MADVPRINT(x, y) 94 #endif 95 96 /* 97 * advice options 98 */ 99 static char *legal_optstr[] = { 100 "madv", 101 "heap", 102 "shm", 103 "ism", 104 "dism", 105 "map", 106 "mapshared", 107 "mapprivate", 108 "mapanon", 109 NULL 110 }; 111 112 enum optenum { 113 OPT_MADV, 114 OPT_HEAP, 115 OPT_SHM, 116 OPT_ISM, 117 OPT_DISM, 118 OPT_MAP, 119 OPT_MAPSHARED, 120 OPT_MAPPRIVATE, 121 OPT_MAPANON 122 }; 123 124 /* 125 * Advice values 126 * These need to correspond to the order of the MADV_ flags in mman.h 127 * since the position infers the value for the flag. 128 */ 129 static char *legal_madvice[] = { 130 "normal", 131 "random", 132 "sequential", 133 "willneed_NOT_SUPPORTED!", 134 "dontneed_NOT_SUPPORTED!", 135 "free_NOT_SUPPORTED!", 136 "access_default", 137 "access_lwp", 138 "access_many", 139 NULL 140 }; 141 142 #if !defined(TEXT_DOMAIN) 143 #define TEXT_DOMAIN "SYS_TEST" 144 #endif 145 146 /*PRINTFLIKE2*/ 147 static void 148 madverr(FILE *fp, char *fmt, ...) 149 { 150 va_list ap; 151 va_start(ap, fmt); 152 if (fp) 153 (void) vfprintf(fp, fmt, ap); 154 else 155 vsyslog(LOG_ERR, fmt, ap); 156 va_end(ap); 157 } 158 159 /* 160 * Return the pointer to the fully-resolved path name of the process's 161 * executable file obtained from the AT_SUN_EXECNAME aux vector entry. 162 */ 163 static const char * 164 mygetexecname(void) 165 { 166 const char *execname = NULL; 167 static auxv_t auxb; 168 169 /* 170 * The first time through, read the initial aux vector that was 171 * passed to the process at exec(2). Only do this once. 172 */ 173 int fd = open("/proc/self/auxv", O_RDONLY); 174 175 if (fd >= 0) { 176 while (read(fd, &auxb, sizeof (auxv_t)) == sizeof (auxv_t)) { 177 if (auxb.a_type == AT_SUN_EXECNAME) { 178 execname = auxb.a_un.a_ptr; 179 break; 180 } 181 } 182 (void) close(fd); 183 } 184 return (execname); 185 } 186 187 /* 188 * Return the process's current brk base and size. 189 */ 190 static int 191 mygetbrk(uintptr_t *base, size_t *size) 192 { 193 int fd; 194 pstatus_t ps; 195 int rc; 196 197 fd = open("/proc/self/status", O_RDONLY); 198 199 if (fd >= 0) { 200 if (read(fd, &ps, sizeof (ps)) == sizeof (ps)) { 201 *base = ps.pr_brkbase; 202 *size = ps.pr_brksize; 203 rc = 0; 204 } else { 205 rc = errno; 206 } 207 (void) close(fd); 208 } else { 209 rc = errno; 210 } 211 return (rc); 212 } 213 214 /* 215 * Check if exec name matches cfgname found in madv cfg file. 216 */ 217 static int 218 fnmatch(const char *execname, char *cfgname, char *cwd) 219 { 220 const char *ename; 221 int rc; 222 223 /* cfgname should not have a '/' unless it begins with one */ 224 if (cfgname[0] == '/') { 225 /* 226 * if execname does not begin with a '/', prepend the 227 * current directory. 228 */ 229 if (execname[0] != '/') { 230 ename = (const char *)strcat(cwd, execname); 231 } else 232 ename = execname; 233 } else { /* simple cfg name */ 234 if (ename = strrchr(execname, '/')) 235 /* execname is a path name - get the base name */ 236 ename++; 237 else 238 ename = execname; 239 } 240 rc = gmatch(ename, cfgname); 241 MADVPRINT(2, (stderr, "gmatch: %s %s %s %d\n", 242 cfgname, ename, execname, rc)); 243 244 return (rc); 245 } 246 247 /* 248 * Check if string matches any of exec arguments. 249 */ 250 static int 251 argmatch(char *str) 252 { 253 int fd; 254 psinfo_t pi; 255 int rc = 0; 256 int arg; 257 char **argv; 258 259 fd = open("/proc/self/psinfo", O_RDONLY); 260 261 if (fd >= 0) { 262 if (read(fd, &pi, sizeof (pi)) == sizeof (pi)) { 263 argv = (char **)pi.pr_argv; 264 argv++; 265 MADVPRINT(2, (stderr, "argmatch: %s ", str)); 266 for (arg = 1; arg < pi.pr_argc; arg++, argv++) { 267 if (rc = gmatch(*argv, str)) { 268 MADVPRINT(2, (stderr, "%s ", *argv)); 269 break; 270 } 271 } 272 MADVPRINT(2, (stderr, "%d\n", rc)); 273 } else { 274 madverr(errfp, dgettext(TEXT_DOMAIN, 275 "%s: /proc/self/psinfo read failed [%s]\n"), 276 madvident, strerror(errno)); 277 } 278 (void) close(fd); 279 } else { 280 madverr(errfp, dgettext(TEXT_DOMAIN, 281 "%s: /proc/self/psinfo open failed [%s]\n"), 282 madvident, strerror(errno)); 283 } 284 return (rc); 285 } 286 287 static int 288 empty(char *str) 289 { 290 char c; 291 292 while ((c = *str) == '\n' || c == ' ' || c == '\t') 293 str++; 294 return (*str == '\0'); 295 } 296 297 static int 298 strtoadv(char *advstr) 299 { 300 char *dummy, *locstr = advstr; 301 302 return (getsubopt(&locstr, legal_madvice, &dummy)); 303 } 304 305 static void 306 advice_opts(char *optstr, const char *execname, char *cfgfile, int lineno) 307 { 308 char *value; 309 int opt; 310 int advice = 0; 311 312 while (*optstr != '\0') { 313 opt = getsubopt(&optstr, legal_optstr, &value); 314 if (opt < 0) { 315 madverr(errfp, dgettext(TEXT_DOMAIN, 316 "%s: invalid advice option (%s)" 317 " for %s - cfgfile: %s, line: %d\n"), 318 madvident, value, execname, cfgfile, lineno); 319 break; 320 } else if (!value) { 321 madverr(errfp, dgettext(TEXT_DOMAIN, 322 "%s: option missing advice" 323 " for %s - cfgfile: %s, line: %d\n"), 324 madvident, execname, cfgfile, lineno); 325 break; 326 } 327 advice = strtoadv(value); 328 if (advice < 0) { 329 madverr(errfp, dgettext(TEXT_DOMAIN, 330 "%s: invalid advice specified (%s)" 331 " for %s - cfgfile: %s, line: %d\n"), 332 madvident, value, execname, cfgfile, lineno); 333 break; 334 } 335 switch (opt) { 336 case OPT_MADV: 337 advice_all = advice; 338 break; 339 case OPT_HEAP: 340 if (advice_heap < 0) { 341 advice_heap = advice; 342 } else { 343 madverr(errfp, dgettext(TEXT_DOMAIN, 344 "%s: duplicate advice specified " 345 "(%s) for %s - cfgfile: %s, line: %d\n"), 346 madvident, value, execname, cfgfile, 347 lineno); 348 } 349 break; 350 case OPT_SHM: 351 if (advice_shm < 0) { 352 advice_shm = advice; 353 } else { 354 madverr(errfp, dgettext(TEXT_DOMAIN, 355 "%s: duplicate advice specified " 356 "(%s) for %s - cfgfile: %s, line: %d\n"), 357 madvident, value, execname, cfgfile, 358 lineno); 359 } 360 break; 361 case OPT_ISM: 362 if (advice_ism < 0) { 363 advice_ism = advice; 364 } else { 365 madverr(errfp, dgettext(TEXT_DOMAIN, 366 "%s: duplicate advice specified " 367 "(%s) for %s - cfgfile: %s, line: %d\n"), 368 madvident, value, execname, cfgfile, 369 lineno); 370 } 371 break; 372 case OPT_DISM: 373 if (advice_dism < 0) { 374 advice_dism = advice; 375 } else { 376 madverr(errfp, dgettext(TEXT_DOMAIN, 377 "%s: duplicate advice specified " 378 "(%s) for %s - cfgfile: %s, line: %d\n"), 379 madvident, value, execname, cfgfile, 380 lineno); 381 } 382 break; 383 case OPT_MAP: 384 if (advice_map < 0) { 385 advice_map = advice; 386 } else { 387 madverr(errfp, dgettext(TEXT_DOMAIN, 388 "%s: duplicate advice specified " 389 "(%s) for %s - cfgfile: %s, line: %d\n"), 390 madvident, value, execname, cfgfile, 391 lineno); 392 } 393 break; 394 case OPT_MAPSHARED: 395 if (advice_mapshared < 0) { 396 advice_mapshared = advice; 397 } else { 398 madverr(errfp, dgettext(TEXT_DOMAIN, 399 "%s: duplicate advice specified " 400 "(%s) for %s - cfgfile: %s, line: %d\n"), 401 madvident, value, execname, cfgfile, 402 lineno); 403 } 404 break; 405 case OPT_MAPPRIVATE: 406 if (advice_mapprivate < 0) { 407 advice_mapprivate = advice; 408 } else { 409 madverr(errfp, dgettext(TEXT_DOMAIN, 410 "%s: duplicate advice specified " 411 "(%s) for %s - cfgfile: %s, line: %d\n"), 412 madvident, value, execname, cfgfile, 413 lineno); 414 } 415 break; 416 case OPT_MAPANON: 417 if (advice_mapanon < 0) { 418 advice_mapanon = advice; 419 } else { 420 madverr(errfp, dgettext(TEXT_DOMAIN, 421 "%s: duplicate advice specified " 422 "(%s) for %s - cfgfile: %s, line: %d\n"), 423 madvident, value, execname, cfgfile, 424 lineno); 425 } 426 break; 427 default: 428 madverr(errfp, dgettext(TEXT_DOMAIN, 429 "%s: invalid advice option (%s)" 430 " for %s - cfgfile: %s, line: %d\n"), 431 madvident, value, execname, cfgfile, lineno); 432 break; 433 } 434 } 435 } 436 437 static void 438 __madvmain() 439 { 440 char *cfgfile, *errfile; 441 FILE *fp = NULL; 442 const char *execname; 443 char *cwd; 444 int cwdlen; 445 char *tok, *tokadv, *tokarg; 446 char *str, *envadv; 447 int lineno = 0; 448 int advice; 449 uintptr_t brkbase, brkend; 450 size_t brksize; 451 int rc; 452 char *locale; 453 454 /* 455 * If a private error file is indicated then set the locale 456 * for error messages for the duration of this routine. 457 * Error messages destined for syslog should not be translated 458 * and thus come from the default C locale. 459 */ 460 if ((errfile = getenv(ENV_MADVERRFILE)) != NULL) { 461 errfp = fopen(errfile, "a"); 462 if (errfp) { 463 locale = setlocale(LC_MESSAGES, ""); 464 } else { 465 madverr(NULL, dgettext(TEXT_DOMAIN, 466 "%s: cannot open error file: %s [%s]\n"), 467 madvident, errfile, strerror(errno)); 468 } 469 } 470 471 #ifdef MADVDEBUG 472 if (str = getenv(ENV_MADVDEBUG)) 473 madvdebug = atoi(str); 474 #endif 475 476 if (envadv = getenv(ENV_MADV)) { 477 if ((advice = strtoadv(envadv)) >= 0) 478 advice_all = advice; 479 else 480 madverr(errfp, dgettext(TEXT_DOMAIN, 481 "%s: invalid advice specified: MADV=%s\n"), 482 madvident, envadv); 483 } 484 485 /* 486 * Open specified cfg file or default one. 487 */ 488 if (cfgfile = getenv(ENV_MADVCFGFILE)) { 489 fp = fopen(cfgfile, "r"); 490 if (!fp) { 491 madverr(errfp, dgettext(TEXT_DOMAIN, 492 "%s: cannot open configuration file: %s [%s]\n"), 493 madvident, cfgfile, strerror(errno)); 494 } 495 } else { 496 cfgfile = DEF_MADVCFGFILE; 497 fp = fopen(cfgfile, "r"); 498 } 499 500 if (fp) { 501 execname = mygetexecname(); 502 503 cwd = getcwd(pbuf, MAXPATHLEN); 504 if (!cwd) 505 return; 506 507 cwd = strcat(cwd, "/"); 508 cwdlen = strlen(cwd); 509 510 while (fgets(lbuf, MAXLINELEN, fp)) { 511 lineno++; 512 513 /* 514 * Make sure line wasn't truncated. 515 */ 516 if (strlen(lbuf) >= MAXLINELEN - 1) { 517 madverr(errfp, dgettext(TEXT_DOMAIN, 518 "%s: invalid entry, " 519 "line too long - cfgfile:" 520 " %s, line: %d\n"), 521 madvident, cfgfile, lineno); 522 continue; 523 } 524 525 if (empty(lbuf)) 526 continue; 527 528 /* 529 * Get advice options. 530 * Parse right to left in case delimiter is in name. 531 */ 532 if (!(tokadv = strrchr(lbuf, CFGDELIMITER))) { 533 madverr(errfp, dgettext(TEXT_DOMAIN, 534 "%s: no delimiter specified - cfgfile:" 535 " %s, line: %d\n"), 536 madvident, cfgfile, lineno); 537 continue; 538 } 539 *tokadv++ = '\0'; 540 541 /* 542 * Remove newline from end of advice options. 543 */ 544 if (str = strrchr(tokadv, '\n')) 545 *str = '\0'; 546 547 /* 548 * Get optional argument string. 549 */ 550 if (tokarg = strrchr(lbuf, ARGDELIMITER)) { 551 *tokarg++ = '\0'; 552 } 553 554 /* 555 * Compare exec name. 556 */ 557 tok = lbuf; 558 if (!fnmatch(execname, tok, cwd)) { 559 tokadv = tokarg = NULL; 560 cwd[cwdlen] = '\0'; 561 continue; 562 } 563 564 /* 565 * Compare arguments if argument string specified. 566 */ 567 if (tokarg && 568 !empty(tokarg) && 569 !argmatch(tokarg)) { 570 tokadv = tokarg = NULL; 571 cwd[cwdlen] = '\0'; 572 continue; 573 } 574 575 /* 576 * Parse advice options. 577 * If empty, any advice from ENV_MADV is reset. 578 */ 579 if (empty(tokadv)) { 580 advice_all = -1; 581 } else { 582 advice_opts(tokadv, execname, cfgfile, lineno); 583 } 584 break; 585 } 586 (void) fclose(fp); 587 } 588 589 /* 590 * Pagesize needed for proper aligning by brk interpose. 591 */ 592 pagesize = sysconf(_SC_PAGESIZE); 593 594 /* 595 * Apply global advice if set. 596 * Specific options in the cfgfile take precedence. 597 */ 598 if (advice_all >= 0) { 599 if (advice_heap < 0) 600 advice_heap = advice_all; 601 if (advice_shm < 0) 602 advice_shm = advice_all; 603 if (advice_map < 0) 604 advice_map = advice_all; 605 } 606 607 MADVPRINT(2, (stderr, "advice_all %d\n", advice_all)); 608 MADVPRINT(2, (stderr, "advice_heap %d\n", advice_heap)); 609 MADVPRINT(2, (stderr, "advice_shm %d\n", advice_shm)); 610 MADVPRINT(2, (stderr, "advice_ism %d\n", advice_ism)); 611 MADVPRINT(2, (stderr, "advice_dism %d\n", advice_dism)); 612 MADVPRINT(2, (stderr, "advice_map %d\n", advice_map)); 613 MADVPRINT(2, (stderr, "advice_mapshared %d\n", advice_mapshared)); 614 MADVPRINT(2, (stderr, "advice_mapprivate %d\n", advice_mapprivate)); 615 MADVPRINT(2, (stderr, "advice_mapanon %d\n", advice_mapanon)); 616 617 /* 618 * If heap advice is specified, apply it to the existing heap. 619 * As the heap grows the kernel applies the advice automatically 620 * to new portions of the heap. 621 */ 622 if (advice_heap >= 0) { 623 if (rc = mygetbrk(&brkbase, &brksize)) { 624 madverr(errfp, dgettext(TEXT_DOMAIN, 625 "%s: /proc/self/status read failed [%s]\n"), 626 madvident, strerror(rc)); 627 } else { 628 MADVPRINT(4, (stderr, "brkbase 0x%x brksize 0x%x\n", 629 brkbase, brksize)); 630 /* 631 * Align start address for memcntl and apply advice 632 * on full pages of heap. Create a page of heap if 633 * it does not already exist. 634 */ 635 brkend = roundup(brkbase+brksize, pagesize); 636 brkbase = roundup(brkbase, pagesize); 637 brksize = brkend - brkbase; 638 if (brksize < pagesize) { 639 if (sbrk(pagesize) == (void *)-1) { 640 madverr(errfp, dgettext(TEXT_DOMAIN, 641 "%s: sbrk failed [%s]\n"), 642 madvident, strerror(errno)); 643 goto out; 644 } 645 brksize = pagesize; 646 } 647 MADVPRINT(1, (stderr, "heap advice: 0x%x 0x%x %d\n", 648 brkbase, brksize, advice_heap)); 649 if (memcntl((caddr_t)brkbase, brksize, MC_ADVISE, 650 (caddr_t)(intptr_t)advice_heap, 0, 0) < 0) { 651 madverr(errfp, dgettext(TEXT_DOMAIN, 652 "%s: memcntl() failed [%s]: heap advice\n"), 653 madvident, strerror(errno)); 654 } 655 } 656 } 657 out: 658 if (errfp) { 659 (void) fclose(errfp); 660 (void) setlocale(LC_MESSAGES, locale); 661 } else { 662 /* close log file: no-op if nothing logged to syslog */ 663 closelog(); 664 } 665 666 } 667 668 /* 669 * shmat interpose 670 */ 671 void * 672 shmat(int shmid, const void *shmaddr, int shmflag) 673 { 674 static caddr_t (*shmatfunc)() = NULL; 675 void *result; 676 int advice = -1; 677 struct shmid_ds mds; 678 #ifdef MADVDEBUG 679 int rc; 680 #else 681 /* LINTED */ 682 int rc; 683 #endif 684 685 if (!shmatfunc) { 686 shmatfunc = (caddr_t (*)()) dlsym(RTLD_NEXT, "shmat"); 687 assert(shmatfunc); 688 } 689 690 result = shmatfunc(shmid, shmaddr, shmflag); 691 692 /* 693 * Options ism, dism take precedence over option shm. 694 */ 695 if (advice_ism >= 0 && (shmflag & SHM_SHARE_MMU)) { 696 advice = advice_ism; 697 } else if (advice_dism >= 0 && (shmflag & SHM_PAGEABLE)) { 698 advice = advice_dism; 699 } else if (advice_shm >= 0) { 700 advice = advice_shm; 701 } 702 703 /* 704 * Apply advice if specified and shmat succeeded. 705 */ 706 if (advice >= 0 && result != (void *)-1) { 707 /* First determine segment size */ 708 rc = shmctl(shmid, IPC_STAT, &mds); 709 MADVPRINT(4, (stderr, "shmctl rc %d errno %d\n", 710 strerror(errno))); 711 712 rc = memcntl(result, mds.shm_segsz, MC_ADVISE, 713 (caddr_t)(intptr_t)advice, 0, 0); 714 MADVPRINT(1, (stderr, 715 "shmat advice: 0x%x 0x%x %d, rc %d errno %d\n", 716 result, mds.shm_segsz, advice, rc, errno)); 717 } 718 719 return (result); 720 } 721 722 /* 723 * mmap interpose 724 */ 725 caddr_t 726 mmap(caddr_t addr, size_t len, int prot, int flags, int fd, off_t pos) 727 { 728 static caddr_t (*mmapfunc)() = NULL; 729 caddr_t result; 730 int advice = -1; 731 #ifdef MADVDEBUG 732 int rc; 733 #else 734 /* LINTED */ 735 int rc; 736 #endif 737 738 if (!mmapfunc) { 739 mmapfunc = (caddr_t (*)()) dlsym(RTLD_NEXT, "mmap"); 740 assert(mmapfunc); 741 } 742 743 result = mmapfunc(addr, len, prot, flags, fd, pos); 744 745 /* 746 * Option mapanon has highest precedence while option map 747 * has lowest precedence. 748 */ 749 if (advice_mapanon >= 0 && (flags & MAP_ANON)) { 750 advice = advice_mapanon; 751 } else if (advice_mapshared >= 0 && (flags & MAP_SHARED)) { 752 advice = advice_mapshared; 753 } else if (advice_mapprivate >= 0 && (flags & MAP_PRIVATE)) { 754 advice = advice_mapprivate; 755 } else if (advice_map >= 0) { 756 advice = advice_map; 757 } 758 759 /* 760 * Apply advice if specified and mmap succeeded. 761 */ 762 if (advice >= 0 && result != MAP_FAILED) { 763 rc = memcntl(result, len, MC_ADVISE, 764 (caddr_t)(intptr_t)advice, 0, 0); 765 MADVPRINT(1, (stderr, 766 "mmap advice: 0x%x 0x%x %d, rc %d errno %d\n", 767 result, len, advice, rc, errno)); 768 } 769 770 return (result); 771 } 772 773 #if !defined(_LP64) 774 /* 775 * mmap64 interpose 776 */ 777 caddr_t 778 mmap64(caddr_t addr, size_t len, int prot, int flags, int fd, off64_t pos) 779 { 780 static caddr_t (*mmap64func)(); 781 caddr_t result; 782 int advice = -1; 783 #ifdef MADVDEBUG 784 int rc; 785 #else 786 /* LINTED */ 787 int rc; 788 #endif 789 790 if (!mmap64func) { 791 mmap64func = (caddr_t (*)()) dlsym(RTLD_NEXT, "mmap64"); 792 assert(mmap64func); 793 } 794 795 result = mmap64func(addr, len, prot, flags, fd, pos); 796 797 /* 798 * Option mapanon has highest precedence while option map 799 * has lowest precedence. 800 */ 801 if (advice_mapanon >= 0 && (flags & MAP_ANON)) { 802 advice = advice_mapanon; 803 } else if (advice_mapshared >= 0 && (flags & MAP_SHARED)) { 804 advice = advice_mapshared; 805 } else if (advice_mapprivate >= 0 && (flags & MAP_PRIVATE)) { 806 advice = advice_mapprivate; 807 } else if (advice_map >= 0) { 808 advice = advice_map; 809 } 810 811 /* 812 * Apply advice if specified and mmap succeeded. 813 */ 814 if (advice >= 0 && result != MAP_FAILED) { 815 rc = memcntl(result, len, MC_ADVISE, (caddr_t)advice, 0, 0); 816 MADVPRINT(1, (stderr, 817 "mmap64 advice: 0x%x 0x%x %d, rc %d errno %d\n", 818 result, len, advice, rc, errno)); 819 } 820 821 return (result); 822 } 823 #endif /* !_LP64 */ 824