Bool MPMCheck(void) { CHECKL(sizeof(Word) * CHAR_BIT == MPS_WORD_WIDTH); CHECKL((Word)1 << MPS_WORD_SHIFT == MPS_WORD_WIDTH); CHECKL(AlignCheck(MPS_PF_ALIGN)); /* Check that trace ids will fit in the TraceId type. */ CHECKL(TraceLIMIT <= UINT_MAX); /* Check that there are enough bits in */ /* a TraceSet to store all possible trace ids. */ CHECKL(sizeof(TraceSet) * CHAR_BIT >= TraceLIMIT); CHECKL((SizeAlignUp(0, 2048) == 0)); CHECKL(!SizeIsAligned(64, (unsigned) -1)); CHECKL(SizeIsAligned(0, 32)); CHECKL((SizeAlignUp(1024, 16) == 1024)); /* .prime: 31051 is prime */ CHECKL(SizeIsAligned(SizeAlignUp(31051, 256), 256)); CHECKL(SizeIsAligned(SizeAlignUp(31051, 512), 512)); CHECKL(!SizeIsAligned(31051, 1024)); CHECKL(!SizeIsP2(0)); CHECKL(SizeIsP2(128)); CHECKL(SizeLog2((Size)1) == 0); CHECKL(SizeLog2((Size)256) == 8); CHECKL(SizeLog2((Size)65536) == 16); CHECKL(SizeLog2((Size)131072) == 17); /* .check.writef: We check that various types will fit in a Word; */ /* See .writef.check. Don't need to check WriteFS or WriteFF as they */ /* should not be cast to Word. */ CHECKL(sizeof(WriteFA) <= sizeof(Word)); CHECKL(sizeof(WriteFP) <= sizeof(Word)); CHECKL(sizeof(WriteFW) <= sizeof(Word)); /* Should be trivial*/ CHECKL(sizeof(WriteFU) <= sizeof(Word)); CHECKL(sizeof(WriteFB) <= sizeof(Word)); CHECKL(sizeof(WriteFC) <= sizeof(Word)); /* .check.write.double: See .write.double.check */ { int e, DBL_EXP_DIG = 1; for (e = DBL_MAX_10_EXP; e > 0; e /= 10) DBL_EXP_DIG++; CHECKL(DBL_EXP_DIG < DBL_DIG); CHECKL(-(DBL_MIN_10_EXP) <= DBL_MAX_10_EXP); } return TRUE; }
Bool ArenaGrainSizeCheck(Size size) { CHECKL(size > 0); /* <design/arena/#req.attr.block.align.min> */ CHECKL(SizeIsAligned(size, MPS_PF_ALIGN)); /* Grain size must be a power of 2 for the tract lookup and the * zones to work. */ CHECKL(SizeIsP2(size)); return TRUE; }
Bool VMCheck(VM vm) { CHECKS(VM, vm); CHECKL(vm->base != 0); CHECKL(vm->limit != 0); CHECKL(vm->base < vm->limit); CHECKL(vm->mapped <= vm->reserved); CHECKL(SizeIsP2(vm->align)); CHECKL(AddrIsAligned(vm->base, vm->align)); CHECKL(AddrIsAligned(vm->limit, vm->align)); return TRUE; }
Res VMCreate(VM *vmReturn, Size size, void *params) { LPVOID vbase; SYSTEM_INFO si; Align align; VM vm; Res res; BOOL b; VMParams vmParams = params; AVER(vmReturn != NULL); AVER(params != NULL); /* FIXME: Should have full AVERT? */ AVER(COMPATTYPE(LPVOID, Addr)); /* .assume.lpvoid-addr */ AVER(COMPATTYPE(SIZE_T, Size)); GetSystemInfo(&si); align = (Align)si.dwPageSize; AVER((DWORD)align == si.dwPageSize); /* check it didn't truncate */ AVER(SizeIsP2(align)); /* see .assume.sysalign */ size = SizeAlignUp(size, align); if ((size == 0) || (size > (Size)(SIZE_T)-1)) return ResRESOURCE; /* Allocate the vm descriptor. This is likely to be wasteful. */ vbase = VirtualAlloc(NULL, SizeAlignUp(sizeof(VMStruct), align), MEM_COMMIT, PAGE_READWRITE); if (vbase == NULL) return ResMEMORY; vm = (VM)vbase; /* Allocate the address space. */ vbase = VirtualAlloc(NULL, size, vmParams->topDown ? MEM_RESERVE | MEM_TOP_DOWN : MEM_RESERVE, PAGE_NOACCESS); if (vbase == NULL) { res = ResRESOURCE; goto failReserve; } AVER(AddrIsAligned(vbase, align)); vm->align = align; vm->base = (Addr)vbase; vm->limit = AddrAdd(vbase, size); vm->reserved = size; vm->mapped = 0; AVER(vm->base < vm->limit); /* .assume.not-last */ vm->sig = VMSig; AVERT(VM, vm); EVENT3(VMCreate, vm, vm->base, vm->limit); *vmReturn = vm; return ResOK; failReserve: b = VirtualFree((LPVOID)vm, (SIZE_T)0, MEM_RELEASE); AVER(b != 0); return res; }
Res VMCreate(VM *vmReturn, Size size, void *params) { Align align; VM vm; int pagesize; void *addr; Res res; AVER(vmReturn != NULL); AVER(params != NULL); /* Find out the page size from the OS */ pagesize = getpagesize(); /* check the actual returned pagesize will fit in an object of */ /* type Align. */ AVER(pagesize > 0); AVER((unsigned long)pagesize <= (unsigned long)(Align)-1); align = (Align)pagesize; AVER(SizeIsP2(align)); size = SizeAlignUp(size, align); if((size == 0) || (size > (Size)(size_t)-1)) return ResRESOURCE; /* Map in a page to store the descriptor on. */ addr = mmap(0, (size_t)SizeAlignUp(sizeof(VMStruct), align), PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); /* On Darwin the MAP_FAILED return value is not documented, but does * work. MAP_FAILED _is_ documented by POSIX. */ if(addr == MAP_FAILED) { int e = errno; AVER(e == ENOMEM); /* .assume.mmap.err */ return ResMEMORY; } vm = (VM)addr; vm->align = align; /* See .assume.not-last. */ addr = mmap(0, (size_t)size, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0); if(addr == MAP_FAILED) { int e = errno; AVER(e == ENOMEM); /* .assume.mmap.err */ res = ResRESOURCE; goto failReserve; } vm->base = (Addr)addr; vm->limit = AddrAdd(vm->base, size); vm->reserved = size; vm->mapped = (Size)0; vm->sig = VMSig; AVERT(VM, vm); EVENT3(VMCreate, vm, vm->base, vm->limit); *vmReturn = vm; return ResOK; failReserve: (void)munmap((void *)vm, (size_t)SizeAlignUp(sizeof(VMStruct), align)); return res; }
Shift SizeLog2(Size size) { AVER(SizeIsP2(size)); return SizeFloorLog2(size); }
Res VMCreate(VM *vmReturn, Size size) { void *addr; Align align; int zero_fd; VM vm; Res res; AVER(vmReturn != NULL); align = (Align)sysconf(_SC_PAGESIZE); AVER(SizeIsP2(align)); size = SizeAlignUp(size, align); if((size == 0) || (size > (Size)(size_t)-1)) return ResRESOURCE; zero_fd = open("/dev/zero", O_RDONLY); if(zero_fd == -1) return ResFAIL; /* Map in a page to store the descriptor on. */ addr = mmap((void *)0, (size_t)SizeAlignUp(sizeof(VMStruct), align), PROT_READ | PROT_WRITE, MAP_PRIVATE, zero_fd, (off_t)0); if(addr == MAP_FAILED) { AVER(errno == ENOMEM || errno == EAGAIN); /* .assume.mmap.err */ res = (errno == ENOMEM || errno == EAGAIN) ? ResMEMORY : ResFAIL; goto failVMMap; } vm = (VM)addr; vm->zero_fd = zero_fd; vm->align = align; /* .map.reserve: MAP_AUTORESRV is necessary to avoid reserving swap. */ addr = mmap((void *)0, (size_t)size, PROT_NONE, MAP_SHARED | MAP_AUTORESRV, zero_fd, (off_t)0); if(addr == MAP_FAILED) { AVER(errno == ENOMEM); /* .assume.mmap.err */ res = (errno == ENOMEM) ? ResRESOURCE : ResFAIL; goto failReserve; } vm->base = (Addr)addr; vm->limit = AddrAdd(vm->base, size); vm->reserved = size; vm->mapped = (Size)0; vm->sig = VMSig; AVERT(VM, vm); EVENT_PAA(VMCreate, vm, vm->base, vm->limit); *vmReturn = vm; return ResOK; failReserve: (void)munmap((void *)vm, (size_t)SizeAlignUp(sizeof(VMStruct), align)); failVMMap: (void)close(zero_fd); return res; }
Res VMCreate(VM *vmReturn, Size size) { caddr_t addr; Align align; int zero_fd; int none_fd; VM vm; Res res; AVER(vmReturn != NULL); align = (Align)getpagesize(); AVER(SizeIsP2(align)); size = SizeAlignUp(size, align); if ((size == 0) || (size > (Size)INT_MAX)) /* see .assume.size */ return ResRESOURCE; zero_fd = open("/dev/zero", O_RDONLY); if (zero_fd == -1) return ResFAIL; none_fd = open("/etc/passwd", O_RDONLY); if (none_fd == -1) { res = ResFAIL; goto failNoneOpen; } /* Map in a page to store the descriptor on. */ addr = mmap((caddr_t)0, SizeAlignUp(sizeof(VMStruct), align), PROT_READ | PROT_WRITE, MAP_PRIVATE, zero_fd, (off_t)0); if (addr == (caddr_t)-1) { int e = errno; AVER(e == ENOMEM); /* .assume.mmap.err */ res = (e == ENOMEM) ? ResMEMORY : ResFAIL; goto failVMMap; } vm = (VM)addr; vm->zero_fd = zero_fd; vm->none_fd = none_fd; vm->align = align; /* .map.reserve: See .assume.not-last. */ addr = mmap((caddr_t)0, size, PROT_NONE, MAP_SHARED, none_fd, (off_t)0); if (addr == (caddr_t)-1) { int e = errno; AVER(e == ENOMEM); /* .assume.mmap.err */ res = (e == ENOMEM) ? ResRESOURCE : ResFAIL; goto failReserve; } vm->base = (Addr)addr; vm->limit = AddrAdd(vm->base, size); vm->reserved = size; vm->mapped = (Size)0; vm->sig = VMSig; AVERT(VM, vm); EVENT_PAA(VMCreate, vm, vm->base, vm->limit); *vmReturn = vm; return ResOK; failReserve: (void)munmap((caddr_t)vm, (size_t)SizeAlignUp(sizeof(VMStruct), align)); failVMMap: (void)close(none_fd); /* see .close.fail */ failNoneOpen: (void)close(zero_fd); return res; }
Res VMCreate(VM *vmReturn, Size size) { void *addr; Align align; int none_fd; VM vm; Res res; AVER(vmReturn != NULL); align = (Align)getpagesize(); AVER(SizeIsP2(align)); size = SizeAlignUp(size, align); if ((size == 0) || (size > (Size)(size_t)-1)) return ResRESOURCE; none_fd = open("/etc/passwd", O_RDONLY); if (none_fd == -1) { return ResFAIL; } /* Map in a page to store the descriptor on. */ addr = mmap(0, (size_t)SizeAlignUp(sizeof(VMStruct), align), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_VARIABLE, -1, 0); if (addr == (void *)-1) { int e = errno; AVER(e == ENOMEM); /* .assume.mmap.err */ res = (e == ENOMEM) ? ResMEMORY : ResFAIL; goto failVMMap; } vm = (VM)addr; vm->none_fd = none_fd; vm->align = align; /* See .assume.not-last. */ addr = mmap(0, (size_t)size, PROT_NONE, MAP_FILE | MAP_SHARED | MAP_VARIABLE, none_fd, 0); if (addr == (void *)-1) { int e = errno; AVER(e == ENOMEM); /* .assume.mmap.err */ res = (e == ENOMEM) ? ResRESOURCE : ResFAIL; goto failReserve; } vm->base = (Addr)addr; vm->limit = AddrAdd(vm->base, size); vm->reserved = size; vm->mapped = (Size)0; vm->sig = VMSig; AVERT(VM, vm); EVENT_PAA(VMCreate, vm, vm->base, vm->limit); *vmReturn = vm; return ResOK; failReserve: (void)munmap((void *)vm, (size_t)SizeAlignUp(sizeof(VMStruct), align)); failVMMap: (void)close(none_fd); /* see .close.fail */ return res; }
Res VMCreate(VM *vmReturn, Size size) { void *addr; Align align; int zero_fd; int none_fd; VM vm; long pagesize; Res res; AVER(vmReturn != NULL); /* Find out the page size from the OS */ pagesize = sysconf(_SC_PAGESIZE); /* check the actual returned pagesize will fit in an object of */ /* type Align. */ AVER(pagesize > 0); AVER((unsigned long)pagesize <= (unsigned long)(Align)-1); /* Note implicit conversion from "long" to "Align". */ align = pagesize; AVER(SizeIsP2(align)); size = SizeAlignUp(size, align); if((size == 0) || (size > (Size)(size_t)-1)) return ResRESOURCE; zero_fd = open("/dev/zero", O_RDONLY); if(zero_fd == -1) return ResFAIL; none_fd = open("/etc/passwd", O_RDONLY); if(none_fd == -1) { res = ResFAIL; goto failNoneOpen; } /* Map in a page to store the descriptor on. */ addr = mmap((void *)0, (size_t)SizeAlignUp(sizeof(VMStruct), align), PROT_READ | PROT_WRITE, MAP_PRIVATE, zero_fd, (off_t)0); if(addr == MAP_FAILED) { AVER(errno == EAGAIN); /* .assume.mmap.err */ res = ResMEMORY; goto failVMMap; } vm = (VM)addr; vm->zero_fd = zero_fd; vm->none_fd = none_fd; vm->align = align; /* .map.reserve: See .assume.not-last. */ addr = mmap((void *)0, (size_t)size, PROT_NONE, MAP_SHARED, none_fd, (off_t)0); if(addr == MAP_FAILED) { AVER(errno == ENOMEM); /* .assume.mmap.err */ res = (errno == ENOMEM) ? ResRESOURCE : ResFAIL; goto failReserve; } vm->base = (Addr)addr; vm->limit = AddrAdd(vm->base, size); vm->reserved = size; vm->mapped = (Size)0; vm->sig = VMSig; AVERT(VM, vm); EVENT_PAA(VMCreate, vm, vm->base, vm->limit); *vmReturn = vm; return ResOK; failReserve: (void)munmap((void *)vm, (size_t)SizeAlignUp(sizeof(VMStruct), align)); failVMMap: (void)close(none_fd); /* see .close.fail */ failNoneOpen: (void)close(zero_fd); return res; }