Пример #1
0
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();
	}

}
Пример #2
0
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();
	}
}