Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <draw.h>
4
#include <thread.h>
5
#include <cursor.h>
6
#include <mouse.h>
7
#include <keyboard.h>
8
#include <frame.h>
9
#include <fcall.h>
10
#include <plumb.h>
11
#include "dat.h"
12
#include "fns.h"
13
 
14
static	Block	*blist;
15
 
16
int
17
tempfile(void)
18
{
19
	char buf[128];
20
	int i, fd;
21
 
22
	snprint(buf, sizeof buf, "/tmp/X%d.%.4sacme", getpid(), getuser());
23
	for(i='A'; i<='Z'; i++){
24
		buf[5] = i;
25
		if(access(buf, AEXIST) == 0)
26
			continue;
27
		fd = create(buf, ORDWR|ORCLOSE|OCEXEC, 0600);
28
		if(fd >= 0)
29
			return fd;
30
	}
31
	return -1;
32
}
33
 
34
Disk*
35
diskinit()
36
{
37
	Disk *d;
38
 
39
	d = emalloc(sizeof(Disk));
40
	d->fd = tempfile();
41
	if(d->fd < 0){
42
		fprint(2, "acme: can't create temp file: %r\n");
43
		threadexitsall("diskinit");
44
	}
45
	return d;
46
}
47
 
48
static
49
uint
50
ntosize(uint n, uint *ip)
51
{
52
	uint size;
53
 
54
	if(n > Maxblock)
55
		error("internal error: ntosize");
56
	size = n;
57
	if(size & (Blockincr-1))
58
		size += Blockincr - (size & (Blockincr-1));
59
	/* last bucket holds blocks of exactly Maxblock */
60
	if(ip)
61
		*ip = size/Blockincr;
62
	return size * sizeof(Rune);
63
}
64
 
65
Block*
66
disknewblock(Disk *d, uint n)
67
{
68
	uint i, j, size;
69
	Block *b;
70
 
71
	size = ntosize(n, &i);
72
	b = d->free[i];
73
	if(b)
74
		d->free[i] = b->next;
75
	else{
76
		/* allocate in chunks to reduce malloc overhead */
77
		if(blist == nil){
78
			blist = emalloc(100*sizeof(Block));
79
			for(j=0; j<100-1; j++)
80
				blist[j].next = &blist[j+1];
81
		}
82
		b = blist;
83
		blist = b->next;
84
		b->addr = d->addr;
85
		d->addr += size;
86
	}
87
	b->n = n;
88
	return b;
89
}
90
 
91
void
92
diskrelease(Disk *d, Block *b)
93
{
94
	uint i;
95
 
96
	ntosize(b->n, &i);
97
	b->next = d->free[i];
98
	d->free[i] = b;
99
}
100
 
101
void
102
diskwrite(Disk *d, Block **bp, Rune *r, uint n)
103
{
104
	int size, nsize;
105
	Block *b;
106
 
107
	b = *bp;
108
	size = ntosize(b->n, nil);
109
	nsize = ntosize(n, nil);
110
	if(size != nsize){
111
		diskrelease(d, b);
112
		b = disknewblock(d, n);
113
		*bp = b;
114
	}
115
	if(pwrite(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))
116
		error("write error to temp file");
117
	b->n = n;
118
}
119
 
120
void
121
diskread(Disk *d, Block *b, Rune *r, uint n)
122
{
123
	int tot, nr;
124
	char *p;
125
 
126
	if(n > b->n)
127
		error("internal error: diskread");
128
 
129
	ntosize(b->n, nil);
130
	n *= sizeof(Rune);
131
	p = (char*)r;
132
	for(tot = 0; tot < n; tot += nr){
133
		nr = pread(d->fd, p+tot, n-tot, b->addr+tot);
134
		if(nr <= 0)
135
			break;		/* tot < n, so error */
136
	}
137
	if(tot != n)
138
		error("read error from temp file");
139
}