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.15 2017/12/08 02:28:08 tg Exp $");
27 static VFILE vfiles = { {&vfiles, &vfiles}, 0, 0, 0, 0, NULL, 0, NULL, 0, NULL, NULL, 0, 0 };
28 static VPAGE *freepages = NULL; /* Linked list of free pages */
29 static VPAGE *htab[HTSIZE]; /* Hash table of page headers */
30 static long curvalloc = 0; /* Amount of memory in use */
31 static long maxvalloc = ILIMIT; /* Maximum allowed */
32 unsigned char *vbase; /* Data first entry in vheader refers to */
33 VPAGE **vheaders = NULL; /* Array of header addresses */
34 static int vheadsz = 0; /* No. entries allocated to vheaders */
36 static unsigned int joe_random(void);
47 for (vfile = vfiles.link.next; vfile != &vfiles; vfile = vfile->link.next) {
52 for (x = 0; x != HTSIZE; x++)
53 for (vp = htab[x]; vp; vp = vp->next)
54 if (vp->addr < addr && vp->addr > last && vp->vfile == vfile && (vp->addr >= vfile->size || (vp->dirty && !vp->count))) {
60 vfile->name = mktmp(NULL,
61 vfile->fd ? NULL : &vfile->fd);
63 vfile->fd = open((char *)(vfile->name), O_RDWR);
64 lseek(vfile->fd, addr, 0);
65 if (addr + PGSIZE > vsize(vfile)) {
66 joe_write(vfile->fd, vlowest->data, vsize(vfile) - addr);
67 vfile->size = vsize(vfile);
69 joe_write(vfile->fd, vlowest->data, PGSIZE);
70 if (addr + PGSIZE > vfile->size)
71 vfile->size = addr + PGSIZE;
80 void vflshf(VFILE *vfile)
90 for (x = 0; x != HTSIZE; x++)
91 for (vp = htab[x]; vp; vp = vp->next)
92 if (vp->addr < addr && vp->dirty && vp->vfile == vfile && !vp->count) {
98 vfile->name = mktmp(NULL,
99 vfile->fd ? NULL : &vfile->fd);
101 vfile->fd = open((char *)(vfile->name), O_RDWR);
103 lseek(vfile->fd, addr, 0);
104 if (addr + PGSIZE > vsize(vfile)) {
105 joe_write(vfile->fd, vlowest->data, vsize(vfile) - addr);
106 vfile->size = vsize(vfile);
108 joe_write(vfile->fd, vlowest->data, PGSIZE);
109 if (addr + PGSIZE > vfile->size)
110 vfile->size = addr + PGSIZE;
117 static unsigned char *mema(int align, int size)
119 unsigned char *z = malloc(align + size);
121 return z + (align - ((size_t)z % align));
124 unsigned char *vlock(VFILE *vfile, unsigned long addr)
128 long ofst = (addr & (PGSIZE - 1));
132 for (vp = htab[((addr >> LPGSIZE) + (unsigned long) vfile) & (HTSIZE - 1)]; vp; vp = vp->next)
133 if (vp->vfile == vfile && (unsigned long)vp->addr == addr) {
135 return vp->data + ofst;
140 freepages = vp->next;
144 if (curvalloc + PGSIZE <= maxvalloc) {
145 vp = malloc(sizeof(VPAGE) * INC);
147 vp->data = (unsigned char *) mema(PGSIZE, PGSIZE * INC);
151 curvalloc += PGSIZE * INC;
153 vheaders = malloc((vheadsz = INC) * sizeof(VPAGE *));
155 } else if ((size_t)vp->data < (size_t)vbase) {
156 VPAGE **t = vheaders;
157 int amnt = (((size_t)vbase) - ((size_t)vp->data)) >> LPGSIZE;
159 vheaders = malloc((amnt + vheadsz) * sizeof(VPAGE *));
160 mmove(vheaders + amnt, t, vheadsz * sizeof(VPAGE *));
164 } else if (((((size_t)vp->data + PGSIZE * INC) - ((size_t)vbase)) >> LPGSIZE) > (unsigned long)vheadsz) {
165 vheaders = realloc(vheaders,
166 (vheadsz = (((((size_t)vp->data + PGSIZE * INC) - ((size_t)vbase)) >> LPGSIZE))) * sizeof(VPAGE *));
168 for (q = 1; q != INC; ++q) {
169 vp[q].next = freepages;
171 vp[q].data = vp->data + q * PGSIZE;
172 vheader(vp->data + q * PGSIZE) = vp + q;
174 vheader(vp->data) = vp;
182 for (y = HTSIZE, x = (joe_random() & (HTSIZE - 1)); y; x = ((x + 1) & (HTSIZE - 1)), --y)
183 for (pp = (VPAGE *) (htab + x), vp = pp->next; vp; pp = vp, vp = vp->next)
184 if (!vp->count && !vp->dirty) {
189 for (y = HTSIZE, x = (joe_random() & (HTSIZE - 1)); y; x = ((x + 1) & (HTSIZE - 1)), --y)
190 for (pp = (VPAGE *) (htab + x), vp = pp->next; vp; pp = vp, vp = vp->next)
191 if (!vp->count && !vp->dirty) {
195 if (write(2, "vfile: out of memory\n", 21)) {}
203 vp->next = htab[((addr >> LPGSIZE) + (unsigned long)vfile) & (HTSIZE - 1)];
204 htab[((addr >> LPGSIZE) + (unsigned long)vfile) & (HTSIZE - 1)] = vp;
206 if (addr < (unsigned long)vfile->size) {
208 vfile->fd = open((char *)(vfile->name), O_RDWR);
210 lseek(vfile->fd, addr, 0);
211 if (addr + PGSIZE > (unsigned long)vfile->size) {
212 joe_read(vfile->fd, vp->data, vfile->size - addr);
213 mset(vp->data + vfile->size - addr, 0, PGSIZE - (int) (vfile->size - addr));
215 joe_read(vfile->fd, vp->data, PGSIZE);
217 mset(vp->data, 0, PGSIZE);
219 return vp->data + ofst;
224 VFILE *new = malloc(sizeof(VFILE));
236 return enqueb_f(VFILE, link, &vfiles, new);
239 void vclose(VFILE *vfile)
245 vunlock(vfile->vpage);
247 vunlock(vfile->vpage1);
250 unlink((char *)vfile->name);
257 free(deque_f(VFILE, link, vfile));
258 for (x = 0; x != HTSIZE; x++)
259 for (pp = (VPAGE *) (htab + x), vp = pp->next; vp;)
260 if (vp->vfile == vfile) {
262 vp->next = freepages;
271 long my_valloc(VFILE *vfile, long int size)
273 long start = vsize(vfile);
275 vfile->alloc = start + size;
277 if (vheader(vfile->vpage)->addr + PGSIZE > vfile->alloc)
278 vfile->lv = PGSIZE - (vfile->alloc - vheader(vfile->vpage)->addr);
285 #if ((HTSIZE) <= 0x8000)
290 static unsigned int lcg_state = 5381;
292 return (((lcg_state = 22695477 * lcg_state + 1) >> 16) & 0x7FFF);