]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/sam/disk.c
realemu: implement IDIV, mark 0xE0000 writeable, fix DIV overfow trap
[plan9front.git] / sys / src / cmd / sam / disk.c
1 #include "sam.h"
2
3 static  Block   *blist;
4
5 static int
6 tempdisk(void)
7 {
8         char buf[128];
9         int i, fd;
10
11         snprint(buf, sizeof buf, "/tmp/X%d.%.4ssam", getpid(), getuser());
12         for(i='A'; i<='Z'; i++){
13                 buf[5] = i;
14                 if(access(buf, AEXIST) == 0)
15                         continue;
16                 fd = create(buf, ORDWR|ORCLOSE|OCEXEC, 0600);
17                 if(fd >= 0)
18                         return fd;
19         }
20         return -1;
21 }
22
23 Disk*
24 diskinit()
25 {
26         Disk *d;
27
28         d = emalloc(sizeof(Disk));
29         d->fd = tempdisk();
30         if(d->fd < 0){
31                 fprint(2, "sam: can't create temp file: %r\n");
32                 exits("diskinit");
33         }
34         return d;
35 }
36
37 static
38 uint
39 ntosize(uint n, uint *ip)
40 {
41         uint size;
42
43         if(n > Maxblock)
44                 panic("internal error: ntosize");
45         size = n;
46         if(size & (Blockincr-1))
47                 size += Blockincr - (size & (Blockincr-1));
48         /* last bucket holds blocks of exactly Maxblock */
49         if(ip)
50                 *ip = size/Blockincr;
51         return size * sizeof(Rune);
52 }
53
54 Block*
55 disknewblock(Disk *d, uint n)
56 {
57         uint i, j, size;
58         Block *b;
59
60         size = ntosize(n, &i);
61         b = d->free[i];
62         if(b)
63                 d->free[i] = b->next;
64         else{
65                 /* allocate in chunks to reduce malloc overhead */
66                 if(blist == nil){
67                         blist = emalloc(100*sizeof(Block));
68                         for(j=0; j<100-1; j++)
69                                 blist[j].next = &blist[j+1];
70                 }
71                 b = blist;
72                 blist = b->next;
73                 b->addr = d->addr;
74                 d->addr += size;
75         }
76         b->n = n;
77         return b;
78 }
79
80 void
81 diskrelease(Disk *d, Block *b)
82 {
83         uint i;
84
85         ntosize(b->n, &i);
86         b->next = d->free[i];
87         d->free[i] = b;
88 }
89
90 void
91 diskwrite(Disk *d, Block **bp, Rune *r, uint n)
92 {
93         int size, nsize;
94         Block *b;
95
96         b = *bp;
97         size = ntosize(b->n, nil);
98         nsize = ntosize(n, nil);
99         if(size != nsize){
100                 diskrelease(d, b);
101                 b = disknewblock(d, n);
102                 *bp = b;
103         }
104         if(pwrite(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))
105                 panic("write error to temp file");
106         b->n = n;
107 }
108
109 void
110 diskread(Disk *d, Block *b, Rune *r, uint n)
111 {
112         if(n > b->n)
113                 panic("internal error: diskread");
114
115         ntosize(b->n, nil);     /* called only for sanity check on Maxblock */
116         if(pread(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))
117                 panic("read error from temp file");
118 }