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