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.11 2017/12/02 18:50:04 tg Exp $");
13 #ifdef HAVE_SYS_STAT_H
31 static VFILE vfiles = { {&vfiles, &vfiles}, 0, 0, 0, 0, NULL, 0, NULL, 0, NULL, NULL, 0, 0 };
32 static VPAGE *freepages = NULL; /* Linked list of free pages */
33 static VPAGE *htab[HTSIZE]; /* Hash table of page headers */
34 static long curvalloc = 0; /* Amount of memory in use */
35 static long maxvalloc = ILIMIT; /* Maximum allowed */
36 unsigned char *vbase; /* Data first entry in vheader refers to */
37 VPAGE **vheaders = NULL; /* Array of header addresses */
38 static int vheadsz = 0; /* No. entries allocated to vheaders */
40 static unsigned int joe_random(void);
51 for (vfile = vfiles.link.next; vfile != &vfiles; vfile = vfile->link.next) {
56 for (x = 0; x != HTSIZE; x++)
57 for (vp = htab[x]; vp; vp = vp->next)
58 if (vp->addr < addr && vp->addr > last && vp->vfile == vfile && (vp->addr >= vfile->size || (vp->dirty && !vp->count))) {
64 vfile->name = mktmp(NULL,
65 vfile->fd ? NULL : &vfile->fd);
67 vfile->fd = open((char *)(vfile->name), O_RDWR);
68 lseek(vfile->fd, addr, 0);
69 if (addr + PGSIZE > vsize(vfile)) {
70 joe_write(vfile->fd, vlowest->data, vsize(vfile) - addr);
71 vfile->size = vsize(vfile);
73 joe_write(vfile->fd, vlowest->data, PGSIZE);
74 if (addr + PGSIZE > vfile->size)
75 vfile->size = addr + PGSIZE;
84 void vflshf(VFILE *vfile)
94 for (x = 0; x != HTSIZE; x++)
95 for (vp = htab[x]; vp; vp = vp->next)
96 if (vp->addr < addr && vp->dirty && vp->vfile == vfile && !vp->count) {
102 vfile->name = mktmp(NULL,
103 vfile->fd ? NULL : &vfile->fd);
105 vfile->fd = open((char *)(vfile->name), O_RDWR);
107 lseek(vfile->fd, addr, 0);
108 if (addr + PGSIZE > vsize(vfile)) {
109 joe_write(vfile->fd, vlowest->data, vsize(vfile) - addr);
110 vfile->size = vsize(vfile);
112 joe_write(vfile->fd, vlowest->data, PGSIZE);
113 if (addr + PGSIZE > vfile->size)
114 vfile->size = addr + PGSIZE;
121 static unsigned char *mema(int align, int size)
123 unsigned char *z = (unsigned char *) joe_malloc(align + size);
125 return z + align - physical(z) % align;
128 unsigned char *vlock(VFILE *vfile, unsigned long addr)
132 long ofst = (addr & (PGSIZE - 1));
136 for (vp = htab[((addr >> LPGSIZE) + (unsigned long) vfile) & (HTSIZE - 1)]; vp; vp = vp->next)
137 if (vp->vfile == vfile && (unsigned long)vp->addr == addr) {
139 return vp->data + ofst;
144 freepages = vp->next;
148 if (curvalloc + PGSIZE <= maxvalloc) {
149 vp = (VPAGE *) joe_malloc(sizeof(VPAGE) * INC);
151 vp->data = (unsigned char *) mema(PGSIZE, PGSIZE * INC);
155 curvalloc += PGSIZE * INC;
157 vheaders = (VPAGE **) joe_malloc((vheadsz = INC) * sizeof(VPAGE *));
159 } else if (physical(vp->data) < physical(vbase)) {
160 VPAGE **t = vheaders;
161 int amnt = (physical(vbase) - physical(vp->data)) >> LPGSIZE;
163 vheaders = (VPAGE **) joe_malloc((amnt + vheadsz) * sizeof(VPAGE *));
164 mmove(vheaders + amnt, t, vheadsz * sizeof(VPAGE *));
168 } else if (((physical(vp->data + PGSIZE * INC) - physical(vbase)) >> LPGSIZE) > (unsigned long)vheadsz) {
169 vheaders = (VPAGE **)
170 joe_realloc(vheaders, (vheadsz = (((physical(vp->data + PGSIZE * INC) - physical(vbase)) >> LPGSIZE))) * sizeof(VPAGE *));
172 for (q = 1; q != INC; ++q) {
173 vp[q].next = freepages;
175 vp[q].data = vp->data + q * PGSIZE;
176 vheader(vp->data + q * PGSIZE) = vp + q;
178 vheader(vp->data) = vp;
186 for (y = HTSIZE, x = (joe_random() & (HTSIZE - 1)); y; x = ((x + 1) & (HTSIZE - 1)), --y)
187 for (pp = (VPAGE *) (htab + x), vp = pp->next; vp; pp = vp, vp = vp->next)
188 if (!vp->count && !vp->dirty) {
193 for (y = HTSIZE, x = (joe_random() & (HTSIZE - 1)); y; x = ((x + 1) & (HTSIZE - 1)), --y)
194 for (pp = (VPAGE *) (htab + x), vp = pp->next; vp; pp = vp, vp = vp->next)
195 if (!vp->count && !vp->dirty) {
199 if (write(2, "vfile: out of memory\n", 21)) {}
207 vp->next = htab[((addr >> LPGSIZE) + (unsigned long)vfile) & (HTSIZE - 1)];
208 htab[((addr >> LPGSIZE) + (unsigned long)vfile) & (HTSIZE - 1)] = vp;
210 if (addr < (unsigned long)vfile->size) {
212 vfile->fd = open((char *)(vfile->name), O_RDWR);
214 lseek(vfile->fd, addr, 0);
215 if (addr + PGSIZE > (unsigned long)vfile->size) {
216 joe_read(vfile->fd, vp->data, vfile->size - addr);
217 mset(vp->data + vfile->size - addr, 0, PGSIZE - (int) (vfile->size - addr));
219 joe_read(vfile->fd, vp->data, PGSIZE);
221 mset(vp->data, 0, PGSIZE);
223 return vp->data + ofst;
228 VFILE *new = (VFILE *) joe_malloc(sizeof(VFILE));
240 return enqueb_f(VFILE, link, &vfiles, new);
243 void vclose(VFILE *vfile)
249 vunlock(vfile->vpage);
251 vunlock(vfile->vpage1);
254 unlink((char *)vfile->name);
261 joe_free(deque_f(VFILE, link, vfile));
262 for (x = 0; x != HTSIZE; x++)
263 for (pp = (VPAGE *) (htab + x), vp = pp->next; vp;)
264 if (vp->vfile == vfile) {
266 vp->next = freepages;
275 long my_valloc(VFILE *vfile, long int size)
277 long start = vsize(vfile);
279 vfile->alloc = start + size;
281 if (vheader(vfile->vpage)->addr + PGSIZE > vfile->alloc)
282 vfile->lv = PGSIZE - (vfile->alloc - vheader(vfile->vpage)->addr);
289 #if ((HTSIZE) <= 0x8000)
294 static unsigned int lcg_state = 5381;
296 return (((lcg_state = 22695477 * lcg_state + 1) >> 16) & 0x7FFF);