Scott Haseley 0ab862abfa 1) Moved tprintf and related functions to their own file in common/libc/printf/tprintf.c.
This file is included by both libc and hostcompat.

2) Changed printf -> tprintf in all testbin programs
2016-01-15 13:33:11 -05:00

205 lines
3.5 KiB
C

/*
* bloat - waste memory.
*
* This test allocates memory a page at a time and keeps going until
* it runs out. It gets the memory directly with sbrk to avoid malloc-
* related overheads, which as long as OS/161 has a dumb userlevel
* malloc is important for performance.
*/
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <err.h>
/* OS/161 doesn't currently have a way to get this from the kernel. */
#define PAGE_SIZE 4096
/* the memory we've gotten */
static void *firstpage;
static void *lastpage;
/* number of page allocations per cycle */
static unsigned allocs;
/* number of pages to touch every cycle */
static unsigned touchpages;
/* when touching pages, the extent to which we favor the middle of the range */
static unsigned bias;
static
void
moremem(void)
{
static unsigned totalpages;
void *ptr;
unsigned i;
for (i=0; i<allocs; i++) {
ptr = sbrk(PAGE_SIZE);
if (ptr == (void *)-1) {
err(1, "After %u pages: sbrk", totalpages);
}
totalpages++;
lastpage = ptr;
if (firstpage == NULL) {
firstpage = ptr;
}
}
}
static
void
touchpage(unsigned pagenum)
{
int *ptr;
ptr = (void *)((uintptr_t)firstpage + PAGE_SIZE * pagenum);
*ptr = pagenum;
}
static
unsigned
pickpage(unsigned numpages)
{
unsigned mnum, moffset;
unsigned span, val, i;
/* take 1 in 1000 pages uniformly from the entire space */
if (random() % 1000 == 0) {
return random() % numpages;
}
/* the rest is taken from the middle 1% */
mnum = numpages / 100;
if (mnum < touchpages * 2) {
mnum = touchpages * 2;
}
if (mnum >= numpages) {
mnum = numpages;
}
moffset = numpages / 2 - mnum / 2;
assert(bias >= 1);
span = (mnum + bias - 1) / bias;
do {
val = 0;
for (i=0; i<bias; i++) {
val += random() % span;
}
} while (val >= mnum);
return moffset + val;
}
static
void
touchmem(void)
{
unsigned i, num;
num = (((uintptr_t)lastpage - (uintptr_t)firstpage) / PAGE_SIZE) + 1;
if (num % 256 == 0) {
warnx("%u pages", num);
}
for (i=0; i<touchpages; i++) {
touchpage(pickpage(num));
}
}
static
void
run(void)
{
while (1) {
moremem();
touchmem();
}
}
static
void
printsettings(void)
{
tprintf("Page size: %u\n", PAGE_SIZE);
tprintf("Allocating %u pages and touching %u pages on each cycle.\n",
allocs, touchpages);
tprintf("Page selection bias: %u\n", bias);
tprintf("\n");
}
static
void
usage(void)
{
warnx("bloat [-a allocs] [-b bias] [-p pages]");
warnx(" allocs: number of pages allocated per cycle (default 4)");
warnx(" bias: number of dice rolled to touch pages (default 8)");
warnx(" pages: pages touched per cycle (default 8)");
exit(1);
}
int
main(int argc, char *argv[])
{
int i;
/* default mode */
allocs = 4;
touchpages = 8;
bias = 8;
srandom(1234);
for (i=1; i<argc; i++) {
if (!strcmp(argv[i], "-a")) {
i++;
if (i == argc) {
errx(1, "-a: option requires argument");
}
allocs = atoi(argv[i]);
if (allocs == 0) {
errx(1, "-a: must not be zero");
}
}
else if (!strcmp(argv[i], "-b")) {
i++;
if (i == argc) {
errx(1, "-b: option requires argument");
}
bias = atoi(argv[i]);
if (bias == 0) {
errx(1, "-b: must not be zero");
}
}
else if (!strcmp(argv[i], "-h")) {
usage();
}
else if (!strcmp(argv[i], "-p")) {
i++;
if (i == argc) {
errx(1, "-p: option requires argument");
}
touchpages = atoi(argv[i]);
}
else {
errx(1, "Argument %s not recognized", argv[i]);
usage();
}
}
printsettings();
run();
return 0;
}