/* * zone: a virtual memory manager for bauble that uses zones. */ #include #include #ifdef USG #include #endif #include #ifdef MSDOS #include #include #endif #include #include #include "news.h" /* for definition of NEWS directory */ #include "zone.h" unsigned short zonemap[ZMAP]; int swapdev; #define VADR(x) (x+(long)ZTOC) /* * vread() reads from the swapdevice, with all the usual panicking. */ vread(address, data, count) register long address; char *data; register int count; { register int sz; if (lseek(swapdev, VADR(address), SEEK_SET) != VADR(address)) panic("vmread seek fault @ %ld", address); if ((sz=read(swapdev, data, count)) != count) panic("vmread fault at @ %ld [%ld] (%d of %d bytes)", address, tell(swapdev), sz, count); } /* * vwrite() writes to the swapdevice, with all the usual panicking. */ vwrite(address, data, count) long address; char *data; register int count; { register int sz; if (lseek(swapdev, VADR(address), SEEK_SET) != VADR(address)) panic("vmwrite seek fault @ %ld", address); if ((sz=write(swapdev, data, count)) != count) panic("vmwrite fault at @ %ld [%ld] (%d of %d bytes)", address, tell(swapdev), sz, count); } /* * vopen() opens the vm area */ vopen(vmfile) char *vmfile; #ifndef O_BINARY #define O_BINARY 0 #endif { makepath(zonemap, NEWS, vmfile); if ((swapdev = open((char*)zonemap, O_RDWR|O_CREAT|O_BINARY, S_IREAD|S_IWRITE)) < 0) panic("can't open VM file"); if (lseek(swapdev, 0L, SEEK_END) < ZTOC) { memset(zonemap, 0, ZTOC); vwrite(-((long)ZTOC), zonemap, ZTOC); } #ifndef MULTITASKING else loadzone(); #endif } /* * loadzone() synchronises core with the disk image of the zonemap */ loadzone() { vread(-((long)ZTOC), zonemap, ZTOC); } /* * vfree() frees up previously allocated virtual memory */ vfree(loc) register long loc; { zoneheader hdr; register int size; register int index; #ifdef MULTITASKING vlock(); loadzone(); #endif if (Zvalid(loc)) { index = (int)(loc/(long)ZSIZE); if (!Zisfree(index)) { vread(loc-sizeof(hdr), &hdr, sizeof hdr); if (hdr.z_magic != Z_MAGIC) { printf("free invalid block @seg %d\n", index); #ifdef MULTITASKING vrelease(); #endif return -1; } vwrite(loc-sizeof(hdr), "@@", 2); for (size=hdr.z_segs; size-- > 0; index++) { if (Zisfree(index)) panic("freeblock overrun @seg %d!\n", index); Zfree(index); } vwrite(-((long)ZTOC), zonemap, ZTOC); } } #ifdef MULTITASKING vrelease(); #endif return 0; } /* vfree */ /* * _vstretch() is a local that expands the actual virtual memory file */ static _vstretch(addr) register long addr; { register long tofill; register int chunk; register long end=lseek(swapdev, 0L, SEEK_END); extern int errno; char fill[ZTOC]; if (end < 0) panic("vstretch seek error %d\n", errno); tofill = addr-end; if (tofill > 0) { memset(fill, 0xff, ZTOC); while (tofill > 0) { chunk = (tofill > ZTOC) ? ZTOC : tofill; write(swapdev, fill, chunk); tofill -= ZTOC; } } } /* _vstretch */ /* * vmalloc() allocates some virtual memory */ long vmalloc(size) register int size; { register int i, total, counting; register int start; zoneheader hdr; long block; /* get # zones that this req will use */ size = (size+sizeof hdr+(ZSIZE-1))/ZSIZE; if (size < 1) return 0; #ifdef MULTITASKING vlock(); loadzone(); #endif /* scan through the zonemap looking for enough contiguous zones * to allocate for this request */ for (counting=i=0; i= size) break; } else counting=0; if (total < size) { /* out of virtual memory! */ #ifdef MULTITASKING vrelease(); #endif return 0L; } /* mark all the just-found memory as used, write the size of the * memory block just allocated, write back zonemap */ for (total=size, i=start; total>0; i++,total--) Zalloc(i); block = ((long)start*(long)ZSIZE); _vstretch(ZTOC+block+((long)size * (long)ZSIZE)); hdr.z_magic = Z_MAGIC; hdr.z_segs = size; vwrite(block, &hdr, sizeof hdr); vwrite(-((long)ZTOC), zonemap, ZTOC); /* * return physical address of first usable byte in this block */ #ifdef MULTITASKING vrelease(); #endif return block+sizeof hdr; } /* vmalloc */ /* * xvmalloc() also allocates virtual memory, but it panics if it fails */ long xvmalloc(size) { register long tmp; if (tmp=vmalloc(size)) return tmp; panic("couldn't vmalloc %d bytes", size); } /* xvmalloc */