static void __madvmain() { char *cfgfile, *errfile; FILE *fp = NULL; const char *execname; char *cwd; int cwdlen; char *tok, *tokadv, *tokarg; char *str, *envadv; int lineno = 0; int advice; uintptr_t brkbase, brkend; size_t brksize; int rc; char *locale; /* * If a private error file is indicated then set the locale * for error messages for the duration of this routine. * Error messages destined for syslog should not be translated * and thus come from the default C locale. */ if ((errfile = getenv(ENV_MADVERRFILE)) != NULL) { errfp = fopen(errfile, "aF"); if (errfp) { locale = setlocale(LC_MESSAGES, ""); } else { madverr(NULL, dgettext(TEXT_DOMAIN, "%s: cannot open error file: %s [%s]\n"), madvident, errfile, strerror(errno)); } } #ifdef MADVDEBUG if (str = getenv(ENV_MADVDEBUG)) madvdebug = atoi(str); #endif if (envadv = getenv(ENV_MADV)) { if ((advice = strtoadv(envadv)) >= 0) advice_all = advice; else madverr(errfp, dgettext(TEXT_DOMAIN, "%s: invalid advice specified: MADV=%s\n"), madvident, envadv); } /* * Open specified cfg file or default one. */ if (cfgfile = getenv(ENV_MADVCFGFILE)) { fp = fopen(cfgfile, "rF"); if (!fp) { madverr(errfp, dgettext(TEXT_DOMAIN, "%s: cannot open configuration file: %s [%s]\n"), madvident, cfgfile, strerror(errno)); } } else { cfgfile = DEF_MADVCFGFILE; fp = fopen(cfgfile, "rF"); } if (fp) { execname = mygetexecname(); cwd = getcwd(pbuf, MAXPATHLEN); if (!cwd) return; cwd = strcat(cwd, "/"); cwdlen = strlen(cwd); while (fgets(lbuf, MAXLINELEN, fp)) { lineno++; /* * Make sure line wasn't truncated. */ if (strlen(lbuf) >= MAXLINELEN - 1) { madverr(errfp, dgettext(TEXT_DOMAIN, "%s: invalid entry, " "line too long - cfgfile:" " %s, line: %d\n"), madvident, cfgfile, lineno); continue; } if (empty(lbuf)) continue; /* * Get advice options. * Parse right to left in case delimiter is in name. */ if (!(tokadv = strrchr(lbuf, CFGDELIMITER))) { madverr(errfp, dgettext(TEXT_DOMAIN, "%s: no delimiter specified - cfgfile:" " %s, line: %d\n"), madvident, cfgfile, lineno); continue; } *tokadv++ = '\0'; /* * Remove newline from end of advice options. */ if (str = strrchr(tokadv, '\n')) *str = '\0'; /* * Get optional argument string. */ if (tokarg = strrchr(lbuf, ARGDELIMITER)) { *tokarg++ = '\0'; } /* * Compare exec name. */ tok = lbuf; if (!fnmatch(execname, tok, cwd)) { tokadv = tokarg = NULL; cwd[cwdlen] = '\0'; continue; } /* * Compare arguments if argument string specified. */ if (tokarg && !empty(tokarg) && !argmatch(tokarg)) { tokadv = tokarg = NULL; cwd[cwdlen] = '\0'; continue; } /* * Parse advice options. * If empty, any advice from ENV_MADV is reset. */ if (empty(tokadv)) { advice_all = -1; } else { advice_opts(tokadv, execname, cfgfile, lineno); } break; } (void) fclose(fp); } /* * Pagesize needed for proper aligning by brk interpose. */ pagesize = sysconf(_SC_PAGESIZE); /* * Apply global advice if set. * Specific options in the cfgfile take precedence. */ if (advice_all >= 0) { if (advice_heap < 0) advice_heap = advice_all; if (advice_shm < 0) advice_shm = advice_all; if (advice_map < 0) advice_map = advice_all; } MADVPRINT(2, (stderr, "advice_all %d\n", advice_all)); MADVPRINT(2, (stderr, "advice_heap %d\n", advice_heap)); MADVPRINT(2, (stderr, "advice_shm %d\n", advice_shm)); MADVPRINT(2, (stderr, "advice_ism %d\n", advice_ism)); MADVPRINT(2, (stderr, "advice_dism %d\n", advice_dism)); MADVPRINT(2, (stderr, "advice_map %d\n", advice_map)); MADVPRINT(2, (stderr, "advice_mapshared %d\n", advice_mapshared)); MADVPRINT(2, (stderr, "advice_mapprivate %d\n", advice_mapprivate)); MADVPRINT(2, (stderr, "advice_mapanon %d\n", advice_mapanon)); /* * If heap advice is specified, apply it to the existing heap. * As the heap grows the kernel applies the advice automatically * to new portions of the heap. */ if (advice_heap >= 0) { if (rc = mygetbrk(&brkbase, &brksize)) { madverr(errfp, dgettext(TEXT_DOMAIN, "%s: /proc/self/status read failed [%s]\n"), madvident, strerror(rc)); } else { MADVPRINT(4, (stderr, "brkbase 0x%x brksize 0x%x\n", brkbase, brksize)); /* * Align start address for memcntl and apply advice * on full pages of heap. Create a page of heap if * it does not already exist. */ brkend = roundup(brkbase+brksize, pagesize); brkbase = roundup(brkbase, pagesize); brksize = brkend - brkbase; if (brksize < pagesize) { if (sbrk(pagesize) == (void *)-1) { madverr(errfp, dgettext(TEXT_DOMAIN, "%s: sbrk failed [%s]\n"), madvident, strerror(errno)); goto out; } brksize = pagesize; } MADVPRINT(1, (stderr, "heap advice: 0x%x 0x%x %d\n", brkbase, brksize, advice_heap)); if (memcntl((caddr_t)brkbase, brksize, MC_ADVISE, (caddr_t)(intptr_t)advice_heap, 0, 0) < 0) { madverr(errfp, dgettext(TEXT_DOMAIN, "%s: memcntl() failed [%s]: heap advice\n"), madvident, strerror(errno)); } } } out: if (errfp) { (void) fclose(errfp); (void) setlocale(LC_MESSAGES, locale); } else { /* close log file: no-op if nothing logged to syslog */ closelog(); } }
void __mpssmain() { static size_t heapsz = (size_t)-1, stacksz = (size_t)-1, sz; char *cfgfile, *errfile; const char *execname; char *cwd; int cwdlen; FILE *fp = NULL, *errfp = NULL; char *tok, *tokheap = NULL, *tokstack = NULL, *tokarg; char *str, *envheap, *envstack; int lineno = 0; char *locale; /* * If a private error file is indicated then set the locale * for error messages for the duration of this routine. * Error messages destined for syslog should not be translated * and thus come from the default C locale. */ if ((errfile = getenv(ENV_MPSSERRFILE)) != NULL) { errfp = fopen(errfile, "aF"); if (errfp) { locale = setlocale(LC_MESSAGES, ""); } else { mpsserr(NULL, dgettext(TEXT_DOMAIN, "%s: cannot open error file: %s [%s]\n"), mpssident, errfile, strerror(errno)); } } #ifdef MPSSDEBUG if (str = getenv(ENV_MPSSDEBUG)) mpssdebug = atosz(str); #endif pgszinit(); if (envstack = getenv(ENV_MPSSSTACK)) { sz = atosz(envstack); if (pgszok(sz)) stacksz = sz; else mpsserr(errfp, dgettext(TEXT_DOMAIN, "%s: invalid stack page size specified:" " MPSSSTACK=%s\n"), mpssident, envstack); } if (envheap = getenv(ENV_MPSSHEAP)) { sz = atosz(envheap); if (pgszok(sz)) heapsz = sz; else mpsserr(errfp, dgettext(TEXT_DOMAIN, "%s: invalid heap page size specified:" " MPSSHEAP=%s\n"), mpssident, envheap); } /* * Open specified cfg file or default one. */ if (cfgfile = getenv(ENV_MPSSCFGFILE)) { fp = fopen(cfgfile, "rF"); if (!fp) { mpsserr(errfp, dgettext(TEXT_DOMAIN, "%s: cannot open configuration file: %s [%s]\n"), mpssident, cfgfile, strerror(errno)); } } else { cfgfile = DEF_MPSSCFGFILE; fp = fopen(cfgfile, "rF"); } execname = mygetexecname(); if (fp) { cwd = getcwd(pbuf, MAXPATHLEN); if (!cwd) return; cwd = strcat(cwd, "/"); cwdlen = strlen(cwd); while (fgets(lbuf, MAXLINELEN, fp)) { lineno++; if (empty(lbuf)) continue; /* * Make sure line wasn't truncated. */ if (strlen(lbuf) >= MAXLINELEN - 1) { mpsserr(errfp, dgettext(TEXT_DOMAIN, "%s: invalid entry, " "line too long - cfgfile:" " %s, line: %d\n"), mpssident, cfgfile, lineno); continue; } /* * parse right to left in case delimiter is * in name. */ if (!(tokstack = strrchr(lbuf, CFGDELIMITER))) { mpsserr(errfp, dgettext(TEXT_DOMAIN, "%s: no delimiters specified - cfgfile:" " %s, line: %d\n"), mpssident, cfgfile, lineno); continue; } /* found delimiter in lbuf */ *tokstack++ = '\0'; /* remove for error message */ if (str = strrchr(tokstack, '\n')) *str = '\0'; if (!(tokheap = strrchr(lbuf, CFGDELIMITER))) { mpsserr(errfp, dgettext(TEXT_DOMAIN, "%s: invalid entry, " "missing delimiter - cfgfile: %s," " line: %d\n"), mpssident, cfgfile, lineno); continue; } *tokheap++ = '\0'; /* exec-args is optional */ if (tokarg = strrchr(lbuf, ARGDELIMITER)) { *tokarg++ = '\0'; } tok = lbuf; if (!fnmatch(execname, tok, cwd)) { tokheap = tokstack = tokarg = NULL; cwd[cwdlen] = '\0'; continue; } if (tokarg && !empty(tokarg) && !argmatch(tokarg, errfp)) { tokheap = tokstack = tokarg = NULL; cwd[cwdlen] = '\0'; continue; } /* heap token */ if (empty(tokheap)) { /* empty cfg entry */ heapsz = (size_t)-1; } else { sz = atosz(tokheap); if (pgszok(sz)) heapsz = sz; else { mpsserr(errfp, dgettext(TEXT_DOMAIN, "%s: invalid heap page size" " specified (%s) for %s - " "cfgfile: %s, line: %d\n"), mpssident, tokheap, execname, cfgfile, lineno); heapsz = (size_t)-1; } } /* stack token */ if (empty(tokstack)) { stacksz = (size_t)-1; break; } else { sz = atosz(tokstack); if (pgszok(sz)) stacksz = sz; else { mpsserr(errfp, dgettext(TEXT_DOMAIN, "%s: invalid stack page size" " specified (%s) for %s - " "cfgfile: %s, line: %d\n"), mpssident, tokstack, execname, cfgfile, lineno); stacksz = (size_t)-1; } } break; } (void) fclose(fp); } if ((heapsz != (size_t)-1) && (pgszset(heapsz, MPSSHEAP) < 0)) mpsserr(errfp, dgettext(TEXT_DOMAIN, "%s: memcntl() failed [%s]: heap page size (%s)" " for %s not set\n"), mpssident, strerror(errno), (tokheap) ? tokheap : envheap, execname); if ((stacksz != (size_t)-1) && (pgszset(stacksz, MPSSSTACK) < 0)) mpsserr(errfp, dgettext(TEXT_DOMAIN, "%s: memcntl() failed [%s]: stack page size (%s)" " for %s not set\n"), mpssident, strerror(errno), (tokstack) ? tokstack: envstack, execname); if (errfp) { (void) fclose(errfp); (void) setlocale(LC_MESSAGES, locale); } else { /* close log file: no-op if nothing logged to syslog */ closelog(); } }