]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/sam/disk.c
aux/realemu: run cpuproc in same fd group as fileserver
[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                 if(d->addr+size < d->addr){
75                         panic("temp file overflow");
76                 }
77                 d->addr += size;
78         }
79         b->n = n;
80         return b;
81 }
82
83 void
84 diskrelease(Disk *d, Block *b)
85 {
86         uint i;
87
88         ntosize(b->n, &i);
89         b->next = d->free[i];
90         d->free[i] = b;
91 }
92
93 void
94 diskwrite(Disk *d, Block **bp, Rune *r, uint n)
95 {
96         int size, nsize;
97         Block *b;
98
99         b = *bp;
100         size = ntosize(b->n, nil);
101         nsize = ntosize(n, nil);
102         if(size != nsize){
103                 diskrelease(d, b);
104                 b = disknewblock(d, n);
105                 *bp = b;
106         }
107         if(pwrite(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))
108                 panic("write error to temp file");
109         b->n = n;
110 }
111
112 void
113 diskread(Disk *d, Block *b, Rune *r, uint n)
114 {
115         if(n > b->n)
116                 panic("internal error: diskread");
117
118         ntosize(b->n, nil);     /* called only for sanity check on Maxblock */
119         if(pread(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))
120                 panic("read error from temp file");
121 }