Пример #1
0
/*
 * Fork and then allocate in both the parent and the child, in case
 * fork messes up the heap. Note: this is not intended to test the
 * parent and child running concurrently -- that should probably be
 * its own test program.
 */
static
void
test12(void)
{
	pid_t pid;
	void *p;

	tprintf("Forking...\n");
	pid = dofork();
	if (pid == 0) {
		/* child */
		say("Child allocating a page...\n");
		p = dosbrk(PAGE_SIZE);
		markpage(p, 0);
		if (checkpage(p, 0, false)) {
			errx(1, "FAILED: data corrupt in child");
		}
		say("Child done.\n");
		exit(0);
	}
	/* parent */
	say("Parent allocating a page...\n");
	p = dosbrk(PAGE_SIZE);
	markpage(p, 0);
	if (checkpage(p, 0, false)) {
		errx(1, "FAILED: data corrupt in parent");
	}
	say("Parent done.\n");
	dowait(pid);
	tprintf("Passed sbrk test 12.\n");
	success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest");
}
Пример #2
0
/*
 * Allocate one page, check that it holds data, and free it.
 */
static
void
test2(void)
{
	void *op, *p, *q;

	op = dosbrk(0);

	tprintf("Allocating a page...\n");
	p = dosbrk(PAGE_SIZE);
	if (p != op) {
		errx(1, "FAILED: sbrk grow didn't return the old break "
		    "(got %p, expected %p", p, op);
	}
	markpage(p, 0);
	if (checkpage(p, 0, false)) {
		errx(1, "FAILED: data corrupt");
	}

	p = dosbrk(0);

	tprintf("Freeing the page...\n");
	q = dosbrk(-PAGE_SIZE);
	if (q != p) {
		errx(1, "FAILED: sbrk shrink didn't return the old break "
		     "(got %p, expected %p", q, p);
	}
	q = dosbrk(0);
	if (q != op) {
		errx(1, "FAILED: sbrk shrink didn't restore the heap "
		     "(got %p, expected %p", q, op);
	}
	success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest");
}
Пример #3
0
static
void
setup(void)
{
	void *op;
	uintptr_t opx;
	size_t amount;
	int error;

	op = dosbrk(0);
	opx = (uintptr_t)op;

	if (opx % PAGE_SIZE) {
		amount = PAGE_SIZE - (opx % PAGE_SIZE);
		if (sbrk(amount) == (void *)-1) {
			error = errno;
			warnx("Initial heap was not page aligned");
			warnx("...and trying to align it gave: %s",
			      strerror(error));
		}
	}

	op = dosbrk(0);
	opx = (uintptr_t)op;

	if (opx % PAGE_SIZE) {
		warnx("Initial heap was not page aligned");
		errx(1, "...and trying to align it didn't take.");
	}
}
Пример #4
0
static
void
test22(void)
{
	int i;
	void *p, *q;
	int num = 10;
	int num_pages = 5 * 1024;	// 20MB

	p = dosbrk(num_pages * PAGE_SIZE);
	q = dosbrk(0);

	if ((unsigned int)q - (unsigned int)p != (unsigned int)(num_pages*PAGE_SIZE)) {
		errx(1, "Heap size not equal to expected size: p=0x%x q=0x%x", (unsigned int)p, (unsigned int)q);
	}

	// Just touch the last 10 pages
	for (i = 0; i < num; i++) {
		markpage(p, num_pages-(i+1));
	}

	// Check the last 10 pages
	for (i = 0; i < num; i++) {
		if (checkpage(p, num_pages-(i+1), false)) {
			errx(1, "FAILED: data corrupt");
		}
	}

	success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest");
}
Пример #5
0
/*
 * Allocate, then fork, then free the allocated page in the child.
 */
static
void
test14(void)
{
	pid_t pid;
	void *p;

	tprintf("Allocating a page...\n");
	p = dosbrk(PAGE_SIZE);
	markpage(p, 0);
	if (checkpage(p, 0, false)) {
		errx(1, "FAILED: data corrupt before forking");
	}

	tprintf("Forking...\n");
	pid = dofork();
	if (pid == 0) {
		/* child */
		if (checkpage(p, 0, false)) {
			errx(1, "FAILED: data corrupt in child");
		}
		tprintf("Child freeing a page...\n");
		dosbrk(-PAGE_SIZE);
		exit(0);
	}
	dowait(pid);
	if (checkpage(p, 0, false)) {
		errx(1, "FAILED: data corrupt in parent after child ran");
	}
	tprintf("Passed sbrk test 14.\n");
	success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest");
}
Пример #6
0
/*
 * Allocate six pages, check that they hold data and that the pages
 * don't get mixed up, and free them one at a time, repeating the
 * check after each free.
 */
static
void
test4(void)
{
	const unsigned num = 6;

	void *op, *p, *q;
	unsigned i, j;
	bool bad;

	op = dosbrk(0);

	printf("Allocating %u pages...\n", num);
	p = dosbrk(PAGE_SIZE * num);
	if (p != op) {
		errx(1, "FAILED: sbrk grow didn't return the old break "
		     "(got %p, expected %p", p, op);
	}

	bad = false;
	for (i=0; i<num; i++) {
		markpage(p, i);
		if (checkpage(p, i, false)) {
			warnx("FAILED: data corrupt on page %u", i);
			bad = true;
		}
	}
	if (bad) {
		exit(1);
	}

	printf("Freeing the pages one at a time...\n");
	for (i=num; i-- > 0; ) {
		(void)dosbrk(-PAGE_SIZE);
		for (j=0; j<i; j++) {
			if (checkpage(p, j, false)) {
				warnx("FAILED: data corrupt on page %u "
				      "after freeing %u pages", j, i);
				bad = true;
			}
		}
	}
	if (bad) {
		exit(1);
	}

	q = dosbrk(0);
	if (q != op) {
		errx(1, "FAILED: sbrk shrink didn't restore the heap "
		     "(got %p, expected %p", q, op);
	}

	printf("Passed sbrk test 4.\n");
}
Пример #7
0
/*
 * Allocates a page and checks that the next page past it is not
 * valid. (Crashes when successful.)
 */
static
void
test6_helper(void)
{
	void *p;

	(void)dosbrk(PAGE_SIZE);
	p = dosbrk(0);
	tprintf("This should produce fatal signal 11 (SIGSEGV).\n");
	((long *)p)[10] = 0;
	errx(1, "FAILED: I didn't crash");
}
Пример #8
0
/*
 * Allocate and then fork, in case fork doesn't preserve the heap.
 */
static
void
test13(void)
{
	pid_t pid;
	void *p;

	printf("Allocating a page...\n");
	p = dosbrk(PAGE_SIZE);
	markpage(p, 0);
	if (checkpage(p, 0, false)) {
		errx(1, "FAILED: data corrupt before forking");
	}

	printf("Forking...\n");
	pid = dofork();
	if (pid == 0) {
		/* child */
		if (checkpage(p, 0, false)) {
			errx(1, "FAILED: data corrupt in child");
		}
		exit(0);
	}
	if (checkpage(p, 0, false)) {
		errx(1, "FAILED: data corrupt in parent");
	}
	dowait(pid);
	printf("Passed sbrk test 13.\n");
}
Пример #9
0
/*
 * Allocate all of memory one page at a time. The same restrictions
 * and considerations apply as above.
 */
static
void
test10(void)
{
	void *p, *op;
	unsigned i, n;
	bool bad;

	tprintf("Allocating all of memory one page at a time:\n");
	op = dosbrk(0);
	n = 0;
	while ((p = sbrk(PAGE_SIZE)) != (void *)-1) {
		markpagelight(op, n);
		n++;
	}
	tprintf("Got %u pages (%zu bytes).\n", n, (size_t)PAGE_SIZE * n);

	tprintf("Now freeing them.\n");
	bad = false;
	for (i=0; i<n; i++) {
		if (checkpagelight(op, n - i - 1, false)) {
			warnx("FAILED: data corrupt on page %u", i);
			bad = true;
		}
		(void)dosbrk(-PAGE_SIZE);
	}
	if (bad) {
		exit(1);
	}
	tprintf("Freed %u pages.\n", n);

	p = dosbrk(0);
	if (p != op) {
		errx(1, "FAILURE: break did not return to original value");
	}

	tprintf("Now let's see if I can allocate another page.\n");
	p = dosbrk(PAGE_SIZE);
	markpage(p, 0);
	if (checkpage(p, 0, false)) {
		errx(1, "FAILED: data corrupt");
	}
	(void)dosbrk(-PAGE_SIZE);

	tprintf("Passed sbrk test 10.\n");
	success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest");
}
Пример #10
0
/*
 * Allocate six pages, check that they hold data and that the
 * pages don't get mixed up, and free them.
 */
static
void
test3(void)
{
	const unsigned num = 6;

	void *op, *p, *q;
	unsigned i;
	bool bad;

	op = dosbrk(0);

	tprintf("Allocating %u pages...\n", num);
	p = dosbrk(PAGE_SIZE * num);
	if (p != op) {
		errx(1, "FAILED: sbrk grow didn't return the old break "
		     "(got %p, expected %p", p, op);
	}

	bad = false;
	for (i=0; i<num; i++) {
		markpage(p, i);
		if (checkpage(p, i, false)) {
			warnx("FAILED: data corrupt on page %u", i);
			bad = true;
		}
	}
	if (bad) {
		exit(1);
	}

	p = dosbrk(0);

	tprintf("Freeing the pages...\n");
	q = dosbrk(-PAGE_SIZE * num);
	if (q != p) {
		errx(1, "FAILED: sbrk shrink didn't return the old break "
		     "(got %p, expected %p", q, p);
	}
	q = dosbrk(0);
	if (q != op) {
		errx(1, "FAILED: sbrk shrink didn't restore the heap "
		     "(got %p, expected %p", q, op);
	}
	success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest");
}
Пример #11
0
/*
 * Checks that the page past end of the heap as we got it is not
 * valid. (Crashes when successful.)
 */
static
void
test5(void)
{
	void *p;

	p = dosbrk(0);
	printf("This should produce fatal signal 11 (SIGSEGV).\n");
	((long *)p)[10] = 0;
	errx(1, "FAILED: I didn't crash");
}
Пример #12
0
static
void
test23(void)
{
	// Make sure sbrk is freeing memory. This allocates, in total, just over 4M
	// of memory, but moves the heap breakpoint in such a way that only one page
	// should ever be required. This test doesn't make much sense to run with
	// more than 4M or with swap enabled.
	void *start;
	int num_pages = 1030;
	int num;

	start = dosbrk(PAGE_SIZE);

	for (num = 1; num <= num_pages; num++) {
		TEST161_LPROGRESS(num);
		start = dosbrk(num*PAGE_SIZE);
		markpagelight(start, num-1);
		checkpagelight(start, num-1, true);
		dosbrk(-(num*PAGE_SIZE));
	}
	success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest");
}
Пример #13
0
/*
 * Allocate one page, check that it holds data, and leak it.
 */
static
void
test1(void)
{
	void *p;

	tprintf("Allocating a page...\n");
	p = dosbrk(PAGE_SIZE);
	markpage(p, 0);
	if (checkpage(p, 0, false)) {
		errx(1, "FAILED: data corrupt");
	}
	success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest");
}
Пример #14
0
/*
 * Allocate one page, check that it holds data, and leak it.
 */
static
void
test1(void)
{
	void *p;

	printf("Allocating a page...\n");
	p = dosbrk(PAGE_SIZE);
	markpage(p, 0);
	if (checkpage(p, 0, false)) {
		errx(1, "FAILED: data corrupt");
	}

	printf("Passed sbrk test 1.\n");
}
Пример #15
0
static
void
test11(void)
{
	const unsigned num = 256;

	void *p;
	unsigned i;
	bool bad;

	printf("Allocating %u pages (%zu bytes).\n", num,
	       (size_t)PAGE_SIZE * num);
	p = dosbrk(num * PAGE_SIZE);

	printf("Touching the pages.\n");
	for (i=0; i<num; i++) {
		markpagelight(p, i);
		if (i % 4 == 0) {
			printf(".");
		}
	}
	printf("\n");

	printf("Checking the pages.\n");
	bad = false;
	for (i=0; i<num; i++) {
		if (checkpagelight(p, i, true)) {
			warnx("FAILED: data corrupt");
			bad = true;
		}
		if (i % 4 == 0) {
			printf(".");
		}
	}
	printf("\n");
	if (bad) {
		exit(1);
	}

	printf("Now NOT freeing the pages. They should get freed on exit.\n");
	printf("If not, you'll notice pretty quickly.\n");
}
Пример #16
0
static
void
test11(void)
{
	const unsigned num = 256;

	void *p;
	unsigned i;
	bool bad;

	tprintf("Allocating %u pages (%zu bytes).\n", num,
	       (size_t)PAGE_SIZE * num);
	p = dosbrk(num * PAGE_SIZE);

	tprintf("Touching the pages.\n");
	for (i=0; i<num; i++) {
		markpagelight(p, i);
		TEST161_LPROGRESS_N(i, 4);
	}
	tprintf("\n");

	tprintf("Checking the pages.\n");
	bad = false;
	for (i=0; i<num; i++) {
		if (checkpagelight(p, i, true)) {
			warnx("FAILED: data corrupt");
			bad = true;
		}
		TEST161_LPROGRESS_N(i, 4);
	}
	printf("\n");
	if (bad) {
		exit(1);
	}

	tprintf("Now NOT freeing the pages. They should get freed on exit.\n");
	tprintf("If not, you'll notice pretty quickly.\n");
	success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest");
}
Пример #17
0
/*
 * Allocate and free in both the parent and the child, and do more
 * than one page.
 */
static
void
test15(void)
{
	unsigned num = 12;

	pid_t pid;
	unsigned i;
	void *p;

	tprintf("Allocating %u pages...\n", num);
	p = dosbrk(PAGE_SIZE * num);
	for (i=0; i<num; i++) {
		markpage(p, i);
	}
	for (i=0; i<num; i++) {
		if (checkpage(p, i, false)) {
			errx(1, "FAILED: data corrupt before forking");
		}
	}

	tprintf("Freeing one page...\n");
	(void)dosbrk(-PAGE_SIZE);
	num--;
	for (i=0; i<num; i++) {
		if (checkpage(p, i, false)) {
			errx(1, "FAILED: data corrupt before forking (2)");
		}
	}

	tprintf("Allocating two pages...\n");
	(void)dosbrk(PAGE_SIZE * 2);
	markpage(p, num++);
	markpage(p, num++);
	for (i=0; i<num; i++) {
		if (checkpage(p, i, false)) {
			errx(1, "FAILED: data corrupt before forking (3)");
		}
	}

	tprintf("Forking...\n");
	pid = dofork();
	if (pid == 0) {
		/* child */
		for (i=0; i<num; i++) {
			if (checkpage(p, i, false)) {
				errx(1, "FAILED: data corrupt in child");
			}
		}

		say("Child: freeing three pages\n");
		dosbrk(-PAGE_SIZE * 3);
		num -= 3;
		for (i=0; i<num; i++) {
			if (checkpage(p, i, false)) {
				errx(1, "FAILED: data corrupt in child (2)");
			}
		}

		say("Child: allocating two pages\n");
		dosbrk(PAGE_SIZE * 2);
		markpage(p, num++);
		markpage(p, num++);
		for (i=0; i<num; i++) {
			if (checkpage(p, i, false)) {
				errx(1, "FAILED: data corrupt in child (3)");
			}
		}

		say("Child: freeing all\n");
		dosbrk(-PAGE_SIZE * num);
		exit(0);
	}
	say("Parent: allocating four pages\n");
	dosbrk(PAGE_SIZE * 4);
	for (i=0; i<4; i++) {
		markpage(p, num++);
	}
	for (i=0; i<num; i++) {
		if (checkpage(p, i, false)) {
			errx(1, "FAILED: data corrupt in parent");
		}
	}

	say("Parent: waiting\n");
	dowait(pid);

	for (i=0; i<num; i++) {
		if (checkpage(p, i, false)) {
			errx(1, "FAILED: data corrupt after waiting");
		}
	}

	(void)dosbrk(-PAGE_SIZE * num);
	tprintf("Passed sbrk test 15.\n");
	success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest");

}
Пример #18
0
static
void
stresstest(unsigned long seed, bool large)
{
	const unsigned loops = 10000;
	const unsigned dot = 200;

	void *op;
	unsigned num;
	unsigned i, j, pages;
	unsigned long r;
	bool bad, neg;

	srandom(seed);
	tprintf("Seeded random number generator with %lu.\n", seed);

	op = dosbrk(0);

	bad = false;
	num = 0;
	for (i=0; i<loops; i++) {
		/*
		 * The goal of this test is not to stress the VM system
		 * by thrashing swap (other tests do that) but by running
		 * the sbrk code a lot. So, clamp the total size at either
		 * 128K or 512K, which is 32 or 128 pages respectively.
		 */
		r = random();
		pages = r % (large ? 32 : 8);
		neg = pages <= num && ((r & 128) == 0);
		if (!neg && num + pages > (large ? 128 : 32)) {
			neg = 1;
		}
	//	if(neg == 1)
	//	tprintf("neg is %d \n", neg);
		if (neg) {
			dosbrk(-(pages * PAGE_SIZE));
			num -= pages;
		}
		else {
			dosbrk(pages * PAGE_SIZE);
			for (j=0; j<pages; j++) {
				markpagelight(op, num + j);
			}
			num += pages;
		}
		for (j=0; j<num; j++) {
			if (checkpagelight(op, j, true)) {
				tprintf("\n");
				tprintf("neg : %d \n", neg);
				warnx("FAILED: data corrupt on page %u", j);
				bad = true;
			}
		}
		TEST161_LPROGRESS_N(i, dot);
	}
	printf("\n");
	if (bad) {
		warnx("FAILED");
		exit(1);
	}

	dosbrk(-(num * PAGE_SIZE));
	tprintf("Passed sbrk %s stress test.\n", large ? "large" : "small");
	success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest");
}
Пример #19
0
/*
 * Allocate all memory at once.
 *
 * This works by trying successively smaller sizes until one succeeds.
 * Note that if you allow arbitrary swap overcommit this test will run
 * the system out of swap. If this kills the system that's probably ok
 * (check with your course staff, but handing OOM is difficult and
 * probably not worth the time it would take you)... but ideally no
 * one process is allowed to get big enough to do this.
 *
 * The recommended behavior is to set the process's maximum heap size
 * to the amount of available RAM + swap that can be used at once.
 * Because the test uses powers of two, this doesn't have to be very
 * precise (e.g. counting the size of the non-heap parts of the
 * process probably doesn't matter unless you're very unlucky) and
 * isn't very difficult.
 *
 * Another option is to disallow swap overcommit, in which case you
 * have sbrk try to reserve swap pages for each allocation, which will
 * fail for huge allocations. The problem with this in practice is
 * that you end up needing a huge swap disk even to run relatively
 * small workloads, and then this test takes forever to run.
 */
static
void
test9(void)
{
	size_t size;
	unsigned i, pages, dot;
	void *p;
	bool bad;

#define HUGESIZE (1024 * 1024 * 1024)	/* 1G */

	tprintf("Checking how much memory we can allocate:\n");
	for (size = HUGESIZE; (p = sbrk(size)) == (void *)-1; size = size/2) {
		tprintf("  %9lu bytes: failed\n", (unsigned long) size);
	}
	tprintf("  %9lu bytes: succeeded\n", (unsigned long) size);
	tprintf("Passed sbrk test 9 (part 1/5)\n");

	tprintf("Touching each page.\n");
	pages = size / PAGE_SIZE;
	dot = pages / 64;
	for (i=0; i<pages; i++) {
		markpagelight(p, i);
		if (dot > 0) {
			TEST161_LPROGRESS_N(i, dot);
		}
	}
	if (dot > 0) {
		printf("\n");
	}

	tprintf("Testing each page.\n");
	bad = false;
	for (i=0; i<pages; i++) {
		if (checkpagelight(p, i, dot > 0)) {
			if (dot > 0) {
				tprintf("\n");
			}
			warnx("FAILED: data corrupt");
			bad = true;
		}
		if (dot > 0) {
			TEST161_LPROGRESS_N(i, dot);
		}
	}
	if (dot > 0) {
		printf("\n");
	}
	if (bad) {
		exit(1);
	}
	tprintf("Passed sbrk test 9 (part 2/5)\n");

	tprintf("Freeing the memory.\n");
	(void)dosbrk(-size);
	tprintf("Passed sbrk test 9 (part 3/5)\n");

	tprintf("Allocating the memory again.\n");
	(void)dosbrk(size);
	tprintf("Passed sbrk test 9 (part 4/5)\n");

	tprintf("And really freeing it.\n");
	(void)dosbrk(-size);
	tprintf("Passed sbrk test 9 (all)\n");
	success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest");
}