/* * 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"); }
/* * 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"); }
/* * 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"); }
main() { checkpage(0,0x404); checkpage(10,0x405); ozputs(0,20,"Fill?"); if(ozgetch()!='y') return; fillpage(0x404); fillpage(0x405); return; }
/* * 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"); }
/* * 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"); }
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"); }
/* * 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"); }
/* * 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"); }
/* * 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"); }
/* * 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"); }
/* * 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"); }
int main(int ac, char **av) { const char *corefile = NULL; const char *sysfile = NULL; vm_page_t mptr; struct vm_page m; struct vm_object obj; kvm_t *kd; int ch; int hv; int i; const char *qstr; const char *ostr; while ((ch = getopt(ac, av, "M:N:dv")) != -1) { switch(ch) { case 'd': ++debugopt; break; case 'v': ++verboseopt; break; case 'M': corefile = optarg; break; case 'N': sysfile = optarg; break; default: fprintf(stderr, "%s [-M core] [-N system]\n", av[0]); exit(1); } } ac -= optind; av += optind; if ((kd = kvm_open(sysfile, corefile, NULL, O_RDONLY, "kvm:")) == NULL) { perror("kvm_open"); exit(1); } if (kvm_nlist(kd, Nl) != 0) { perror("kvm_nlist"); exit(1); } #if 0 kkread(kd, Nl[0].n_value, &vm_page_buckets, sizeof(vm_page_buckets)); kkread(kd, Nl[1].n_value, &vm_page_hash_mask, sizeof(vm_page_hash_mask)); #endif kkread(kd, Nl[0].n_value, &vm_page_array, sizeof(vm_page_array)); kkread(kd, Nl[1].n_value, &vm_page_array_size, sizeof(vm_page_array_size)); /* * Scan the vm_page_array validating all pages with associated objects */ for (i = 0; i < vm_page_array_size; ++i) { if (debugopt) { printf("page %d\r", i); fflush(stdout); } kkread(kd, (u_long)&vm_page_array[i], &m, sizeof(m)); if (m.object) { kkread(kd, (u_long)m.object, &obj, sizeof(obj)); checkpage(kd, &vm_page_array[i], &m, &obj); } if (verboseopt) { if (m.queue >= PQ_HOLD) { qstr = "HOLD"; } else if (m.queue >= PQ_CACHE) { qstr = "CACHE"; } else if (m.queue >= PQ_ACTIVE) { qstr = "ACTIVE"; } else if (m.queue >= PQ_INACTIVE) { qstr = "INACTIVE"; } else if (m.queue >= PQ_FREE) { qstr = "FREE"; } else { qstr = "NONE"; } printf("page %p obj %p/%-8jd val=%02x dty=%02x hold=%d " "wire=%-2d act=%-3d busy=%d %8s", &vm_page_array[i], m.object, (intmax_t)m.pindex, m.valid, m.dirty, m.hold_count, m.wire_count, m.act_count, m.busy, qstr ); switch(obj.type) { case OBJT_DEFAULT: ostr = "default"; break; case OBJT_SWAP: ostr = "swap"; break; case OBJT_VNODE: ostr = "vnode"; break; case OBJT_DEVICE: ostr = "device"; break; case OBJT_PHYS: ostr = "phys"; break; case OBJT_DEAD: ostr = "dead"; break; default: ostr = "unknown"; break; } printf(" %-7s", ostr); if (m.flags & PG_BUSY) printf(" BUSY"); if (m.flags & PG_WANTED) printf(" WANTED"); if (m.flags & PG_WINATCFLS) printf(" WINATCFLS"); if (m.flags & PG_FICTITIOUS) printf(" FICTITIOUS"); if (m.flags & PG_WRITEABLE) printf(" WRITEABLE"); if (m.flags & PG_MAPPED) printf(" MAPPED"); if (m.flags & PG_ZERO) printf(" ZERO"); if (m.flags & PG_REFERENCED) printf(" REFERENCED"); if (m.flags & PG_CLEANCHK) printf(" CLEANCHK"); if (m.flags & PG_SWAPINPROG) printf(" SWAPINPROG"); if (m.flags & PG_NOSYNC) printf(" NOSYNC"); if (m.flags & PG_UNMANAGED) printf(" UNMANAGED"); if (m.flags & PG_MARKER) printf(" MARKER"); if (m.flags & PG_RAM) printf(" RAM"); if (m.flags & PG_SWAPPED) printf(" SWAPPED"); printf("\n"); } } if (debugopt || verboseopt) printf("\n"); #if 0 /* * Scan the vm_page_buckets array validating all pages found */ for (i = 0; i <= vm_page_hash_mask; ++i) { if (debugopt) { printf("index %d\r", i); fflush(stdout); } kkread(kd, (u_long)&vm_page_buckets[i], &mptr, sizeof(mptr)); while (mptr) { kkread(kd, (u_long)mptr, &m, sizeof(m)); if (m.object) { kkread(kd, (u_long)m.object, &obj, sizeof(obj)); hv = ((uintptr_t)m.object + m.pindex) ^ obj.hash_rand; hv &= vm_page_hash_mask; if (i != hv) printf("vm_page_buckets[%d] ((struct vm_page *)%p)" " should be in bucket %d\n", i, mptr, hv); checkpage(kd, mptr, &m, &obj); } else { printf("vm_page_buckets[%d] ((struct vm_page *)%p)" " has no object\n", i, mptr); } mptr = m.hnext; } } #endif if (debugopt) printf("\n"); return(0); }