2 * Software virtual memory system
4 * (C) 1992 Joseph H. Allen
6 * This file is part of JOE (Joe's Own Editor)
11 __RCSID("$MirOS: contrib/code/jupp/vfile.c,v 1.10 2017/12/02 02:07:38 tg Exp $");
13 #ifdef HAVE_SYS_STAT_H
30 static VFILE vfiles = { {&vfiles, &vfiles} }; /* Known vfiles */
31 static VPAGE *freepages = NULL; /* Linked list of free pages */
32 static VPAGE *htab[HTSIZE]; /* Hash table of page headers */
33 static long curvalloc = 0; /* Amount of memory in use */
34 static long maxvalloc = ILIMIT; /* Maximum allowed */
35 unsigned char *vbase; /* Data first entry in vheader refers to */
36 VPAGE **vheaders = NULL; /* Array of header addresses */
37 static int vheadsz = 0; /* No. entries allocated to vheaders */
39 static unsigned int joe_random(void);
50 for (vfile = vfiles.link.next; vfile != &vfiles; vfile = vfile->link.next) {
55 for (x = 0; x != HTSIZE; x++)
56 for (vp = htab[x]; vp; vp = vp->next)
57 if (vp->addr < addr && vp->addr > last && vp->vfile == vfile && (vp->addr >= vfile->size || (vp->dirty && !vp->count))) {
63 vfile->name = mktmp(NULL,
64 vfile->fd ? NULL : &vfile->fd);
66 vfile->fd = open((char *)(vfile->name), O_RDWR);
67 lseek(vfile->fd, addr, 0);
68 if (addr + PGSIZE > vsize(vfile)) {
69 joe_write(vfile->fd, vlowest->data, vsize(vfile) - addr);
70 vfile->size = vsize(vfile);
72 joe_write(vfile->fd, vlowest->data, PGSIZE);
73 if (addr + PGSIZE > vfile->size)
74 vfile->size = addr + PGSIZE;
83 void vflshf(VFILE *vfile)
93 for (x = 0; x != HTSIZE; x++)
94 for (vp = htab[x]; vp; vp = vp->next)
95 if (vp->addr < addr && vp->dirty && vp->vfile == vfile && !vp->count) {
101 vfile->name = mktmp(NULL,
102 vfile->fd ? NULL : &vfile->fd);
104 vfile->fd = open((char *)(vfile->name), O_RDWR);
106 lseek(vfile->fd, addr, 0);
107 if (addr + PGSIZE > vsize(vfile)) {
108 joe_write(vfile->fd, vlowest->data, vsize(vfile) - addr);
109 vfile->size = vsize(vfile);
111 joe_write(vfile->fd, vlowest->data, PGSIZE);
112 if (addr + PGSIZE > vfile->size)
113 vfile->size = addr + PGSIZE;
120 static unsigned char *mema(int align, int size)
122 unsigned char *z = (unsigned char *) joe_malloc(align + size);
124 return z + align - physical(z) % align;
127 unsigned char *vlock(VFILE *vfile, unsigned long addr)
131 long ofst = (addr & (PGSIZE - 1));
135 for (vp = htab[((addr >> LPGSIZE) + (unsigned long) vfile) & (HTSIZE - 1)]; vp; vp = vp->next)
136 if (vp->vfile == vfile && (unsigned long)vp->addr == addr) {
138 return vp->data + ofst;
143 freepages = vp->next;
147 if (curvalloc + PGSIZE <= maxvalloc) {
148 vp = (VPAGE *) joe_malloc(sizeof(VPAGE) * INC);
150 vp->data = (unsigned char *) mema(PGSIZE, PGSIZE * INC);
154 curvalloc += PGSIZE * INC;
156 vheaders = (VPAGE **) joe_malloc((vheadsz = INC) * sizeof(VPAGE *));
158 } else if (physical(vp->data) < physical(vbase)) {
159 VPAGE **t = vheaders;
160 int amnt = (physical(vbase) - physical(vp->data)) >> LPGSIZE;
162 vheaders = (VPAGE **) joe_malloc((amnt + vheadsz) * sizeof(VPAGE *));
163 mmove(vheaders + amnt, t, vheadsz * sizeof(VPAGE *));
167 } else if (((physical(vp->data + PGSIZE * INC) - physical(vbase)) >> LPGSIZE) > (unsigned long)vheadsz) {
168 vheaders = (VPAGE **)
169 joe_realloc(vheaders, (vheadsz = (((physical(vp->data + PGSIZE * INC) - physical(vbase)) >> LPGSIZE))) * sizeof(VPAGE *));
171 for (q = 1; q != INC; ++q) {
172 vp[q].next = freepages;
174 vp[q].data = vp->data + q * PGSIZE;
175 vheader(vp->data + q * PGSIZE) = vp + q;
177 vheader(vp->data) = vp;
185 for (y = HTSIZE, x = (joe_random() & (HTSIZE - 1)); y; x = ((x + 1) & (HTSIZE - 1)), --y)
186 for (pp = (VPAGE *) (htab + x), vp = pp->next; vp; pp = vp, vp = vp->next)
187 if (!vp->count && !vp->dirty) {
192 for (y = HTSIZE, x = (joe_random() & (HTSIZE - 1)); y; x = ((x + 1) & (HTSIZE - 1)), --y)
193 for (pp = (VPAGE *) (htab + x), vp = pp->next; vp; pp = vp, vp = vp->next)
194 if (!vp->count && !vp->dirty) {
198 if (write(2, "vfile: out of memory\n", 21)) {}
206 vp->next = htab[((addr >> LPGSIZE) + (unsigned long)vfile) & (HTSIZE - 1)];
207 htab[((addr >> LPGSIZE) + (unsigned long)vfile) & (HTSIZE - 1)] = vp;
209 if (addr < (unsigned long)vfile->size) {
211 vfile->fd = open((char *)(vfile->name), O_RDWR);
213 lseek(vfile->fd, addr, 0);
214 if (addr + PGSIZE > (unsigned long)vfile->size) {
215 joe_read(vfile->fd, vp->data, vfile->size - addr);
216 mset(vp->data + vfile->size - addr, 0, PGSIZE - (int) (vfile->size - addr));
218 joe_read(vfile->fd, vp->data, PGSIZE);
220 mset(vp->data, 0, PGSIZE);
222 return vp->data + ofst;
227 VFILE *new = (VFILE *) joe_malloc(sizeof(VFILE));
239 return enqueb_f(VFILE, link, &vfiles, new);
242 void vclose(VFILE *vfile)
248 vunlock(vfile->vpage);
250 vunlock(vfile->vpage1);
253 unlink((char *)vfile->name);
260 joe_free(deque_f(VFILE, link, vfile));
261 for (x = 0; x != HTSIZE; x++)
262 for (pp = (VPAGE *) (htab + x), vp = pp->next; vp;)
263 if (vp->vfile == vfile) {
265 vp->next = freepages;
274 long my_valloc(VFILE *vfile, long int size)
276 long start = vsize(vfile);
278 vfile->alloc = start + size;
280 if (vheader(vfile->vpage)->addr + PGSIZE > vfile->alloc)
281 vfile->lv = PGSIZE - (vfile->alloc - vheader(vfile->vpage)->addr);
288 #if ((HTSIZE) <= 0x8000)
293 static unsigned int lcg_state = 5381;
295 return (((lcg_state = 22695477 * lcg_state + 1) >> 16) & 0x7FFF);