/* * 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"); }
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"); }
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"); }
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"); }
/* * 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"); }
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"); }