1*74a4d8c2SCharles.Forsyth #include "u.h"
2*74a4d8c2SCharles.Forsyth #include "../port/lib.h"
3*74a4d8c2SCharles.Forsyth #include "mem.h"
4*74a4d8c2SCharles.Forsyth #include "dat.h"
5*74a4d8c2SCharles.Forsyth #include "fns.h"
6*74a4d8c2SCharles.Forsyth #include "../port/error.h"
7*74a4d8c2SCharles.Forsyth
8*74a4d8c2SCharles.Forsyth enum
9*74a4d8c2SCharles.Forsyth {
10*74a4d8c2SCharles.Forsyth Hdrspc = 64, /* leave room for high-level headers */
11*74a4d8c2SCharles.Forsyth Bdead = 0x51494F42, /* "QIOB" */
12*74a4d8c2SCharles.Forsyth };
13*74a4d8c2SCharles.Forsyth
14*74a4d8c2SCharles.Forsyth struct
15*74a4d8c2SCharles.Forsyth {
16*74a4d8c2SCharles.Forsyth Lock;
17*74a4d8c2SCharles.Forsyth ulong bytes;
18*74a4d8c2SCharles.Forsyth } ialloc;
19*74a4d8c2SCharles.Forsyth
20*74a4d8c2SCharles.Forsyth /*
21*74a4d8c2SCharles.Forsyth * allocate blocks (round data base address to 64 bit boundary).
22*74a4d8c2SCharles.Forsyth * if mallocz gives us more than we asked for, leave room at the front
23*74a4d8c2SCharles.Forsyth * for header.
24*74a4d8c2SCharles.Forsyth */
25*74a4d8c2SCharles.Forsyth Block*
_allocb(int size)26*74a4d8c2SCharles.Forsyth _allocb(int size)
27*74a4d8c2SCharles.Forsyth {
28*74a4d8c2SCharles.Forsyth Block *b;
29*74a4d8c2SCharles.Forsyth ulong addr;
30*74a4d8c2SCharles.Forsyth int n;
31*74a4d8c2SCharles.Forsyth
32*74a4d8c2SCharles.Forsyth b = mallocz(sizeof(Block)+size+Hdrspc+(BY2V-1), 0);
33*74a4d8c2SCharles.Forsyth if(b == nil)
34*74a4d8c2SCharles.Forsyth return nil;
35*74a4d8c2SCharles.Forsyth
36*74a4d8c2SCharles.Forsyth b->next = nil;
37*74a4d8c2SCharles.Forsyth b->list = nil;
38*74a4d8c2SCharles.Forsyth b->free = nil;
39*74a4d8c2SCharles.Forsyth b->flag = 0;
40*74a4d8c2SCharles.Forsyth
41*74a4d8c2SCharles.Forsyth addr = (ulong)b;
42*74a4d8c2SCharles.Forsyth addr = ROUND(addr + sizeof(Block), BY2V);
43*74a4d8c2SCharles.Forsyth b->base = (uchar*)addr;
44*74a4d8c2SCharles.Forsyth b->lim = ((uchar*)b) + msize(b);
45*74a4d8c2SCharles.Forsyth b->rp = b->base;
46*74a4d8c2SCharles.Forsyth n = b->lim - b->base - size;
47*74a4d8c2SCharles.Forsyth b->rp += n & ~(BY2V-1);
48*74a4d8c2SCharles.Forsyth b->wp = b->rp;
49*74a4d8c2SCharles.Forsyth
50*74a4d8c2SCharles.Forsyth return b;
51*74a4d8c2SCharles.Forsyth }
52*74a4d8c2SCharles.Forsyth
53*74a4d8c2SCharles.Forsyth Block*
allocb(int size)54*74a4d8c2SCharles.Forsyth allocb(int size)
55*74a4d8c2SCharles.Forsyth {
56*74a4d8c2SCharles.Forsyth Block *b;
57*74a4d8c2SCharles.Forsyth
58*74a4d8c2SCharles.Forsyth if(0 && up == nil)
59*74a4d8c2SCharles.Forsyth panic("allocb outside process: %8.8lux", getcallerpc(&size));
60*74a4d8c2SCharles.Forsyth b = _allocb(size);
61*74a4d8c2SCharles.Forsyth if(b == 0)
62*74a4d8c2SCharles.Forsyth exhausted("Blocks");
63*74a4d8c2SCharles.Forsyth setmalloctag(b, getcallerpc(&size));
64*74a4d8c2SCharles.Forsyth return b;
65*74a4d8c2SCharles.Forsyth }
66*74a4d8c2SCharles.Forsyth
67*74a4d8c2SCharles.Forsyth /*
68*74a4d8c2SCharles.Forsyth * interrupt time allocation
69*74a4d8c2SCharles.Forsyth */
70*74a4d8c2SCharles.Forsyth Block*
iallocb(int size)71*74a4d8c2SCharles.Forsyth iallocb(int size)
72*74a4d8c2SCharles.Forsyth {
73*74a4d8c2SCharles.Forsyth Block *b;
74*74a4d8c2SCharles.Forsyth
75*74a4d8c2SCharles.Forsyth if(ialloc.bytes > conf.ialloc){
76*74a4d8c2SCharles.Forsyth //print("iallocb: limited %lud/%lud\n", ialloc.bytes, conf.ialloc);
77*74a4d8c2SCharles.Forsyth return nil;
78*74a4d8c2SCharles.Forsyth }
79*74a4d8c2SCharles.Forsyth
80*74a4d8c2SCharles.Forsyth b = _allocb(size);
81*74a4d8c2SCharles.Forsyth if(b == nil){
82*74a4d8c2SCharles.Forsyth //print("iallocb: no memory %lud/%lud\n", ialloc.bytes, conf.ialloc);
83*74a4d8c2SCharles.Forsyth return nil;
84*74a4d8c2SCharles.Forsyth }
85*74a4d8c2SCharles.Forsyth setmalloctag(b, getcallerpc(&size));
86*74a4d8c2SCharles.Forsyth b->flag = BINTR;
87*74a4d8c2SCharles.Forsyth
88*74a4d8c2SCharles.Forsyth ilock(&ialloc);
89*74a4d8c2SCharles.Forsyth ialloc.bytes += b->lim - b->base;
90*74a4d8c2SCharles.Forsyth iunlock(&ialloc);
91*74a4d8c2SCharles.Forsyth
92*74a4d8c2SCharles.Forsyth return b;
93*74a4d8c2SCharles.Forsyth }
94*74a4d8c2SCharles.Forsyth
95*74a4d8c2SCharles.Forsyth void
freeb(Block * b)96*74a4d8c2SCharles.Forsyth freeb(Block *b)
97*74a4d8c2SCharles.Forsyth {
98*74a4d8c2SCharles.Forsyth void *dead = (void*)Bdead;
99*74a4d8c2SCharles.Forsyth
100*74a4d8c2SCharles.Forsyth if(b == nil)
101*74a4d8c2SCharles.Forsyth return;
102*74a4d8c2SCharles.Forsyth
103*74a4d8c2SCharles.Forsyth /*
104*74a4d8c2SCharles.Forsyth * drivers which perform non cache coherent DMA manage their own buffer
105*74a4d8c2SCharles.Forsyth * pool of uncached buffers and provide their own free routine.
106*74a4d8c2SCharles.Forsyth */
107*74a4d8c2SCharles.Forsyth if(b->free) {
108*74a4d8c2SCharles.Forsyth b->free(b);
109*74a4d8c2SCharles.Forsyth return;
110*74a4d8c2SCharles.Forsyth }
111*74a4d8c2SCharles.Forsyth if(b->flag & BINTR) {
112*74a4d8c2SCharles.Forsyth ilock(&ialloc);
113*74a4d8c2SCharles.Forsyth ialloc.bytes -= b->lim - b->base;
114*74a4d8c2SCharles.Forsyth iunlock(&ialloc);
115*74a4d8c2SCharles.Forsyth }
116*74a4d8c2SCharles.Forsyth
117*74a4d8c2SCharles.Forsyth /* poison the block in case someone is still holding onto it */
118*74a4d8c2SCharles.Forsyth b->next = dead;
119*74a4d8c2SCharles.Forsyth b->rp = dead;
120*74a4d8c2SCharles.Forsyth b->wp = dead;
121*74a4d8c2SCharles.Forsyth b->lim = dead;
122*74a4d8c2SCharles.Forsyth b->base = dead;
123*74a4d8c2SCharles.Forsyth
124*74a4d8c2SCharles.Forsyth free(b);
125*74a4d8c2SCharles.Forsyth }
126*74a4d8c2SCharles.Forsyth
127*74a4d8c2SCharles.Forsyth void
checkb(Block * b,char * msg)128*74a4d8c2SCharles.Forsyth checkb(Block *b, char *msg)
129*74a4d8c2SCharles.Forsyth {
130*74a4d8c2SCharles.Forsyth void *dead = (void*)Bdead;
131*74a4d8c2SCharles.Forsyth
132*74a4d8c2SCharles.Forsyth if(b == dead)
133*74a4d8c2SCharles.Forsyth panic("checkb b %s %lux", msg, b);
134*74a4d8c2SCharles.Forsyth if(b->base == dead || b->lim == dead || b->next == dead
135*74a4d8c2SCharles.Forsyth || b->rp == dead || b->wp == dead){
136*74a4d8c2SCharles.Forsyth print("checkb: base 0x%8.8luX lim 0x%8.8luX next 0x%8.8luX\n",
137*74a4d8c2SCharles.Forsyth b->base, b->lim, b->next);
138*74a4d8c2SCharles.Forsyth print("checkb: rp 0x%8.8luX wp 0x%8.8luX\n", b->rp, b->wp);
139*74a4d8c2SCharles.Forsyth panic("checkb dead: %s\n", msg);
140*74a4d8c2SCharles.Forsyth }
141*74a4d8c2SCharles.Forsyth
142*74a4d8c2SCharles.Forsyth if(b->base > b->lim)
143*74a4d8c2SCharles.Forsyth panic("checkb 0 %s %lux %lux", msg, b->base, b->lim);
144*74a4d8c2SCharles.Forsyth if(b->rp < b->base)
145*74a4d8c2SCharles.Forsyth panic("checkb 1 %s %lux %lux", msg, b->base, b->rp);
146*74a4d8c2SCharles.Forsyth if(b->wp < b->base)
147*74a4d8c2SCharles.Forsyth panic("checkb 2 %s %lux %lux", msg, b->base, b->wp);
148*74a4d8c2SCharles.Forsyth if(b->rp > b->lim)
149*74a4d8c2SCharles.Forsyth panic("checkb 3 %s %lux %lux", msg, b->rp, b->lim);
150*74a4d8c2SCharles.Forsyth if(b->wp > b->lim)
151*74a4d8c2SCharles.Forsyth panic("checkb 4 %s %lux %lux", msg, b->wp, b->lim);
152*74a4d8c2SCharles.Forsyth
153*74a4d8c2SCharles.Forsyth }
154*74a4d8c2SCharles.Forsyth
155*74a4d8c2SCharles.Forsyth void
iallocsummary(void)156*74a4d8c2SCharles.Forsyth iallocsummary(void)
157*74a4d8c2SCharles.Forsyth {
158*74a4d8c2SCharles.Forsyth print("ialloc %lud/%lud\n", ialloc.bytes, conf.ialloc);
159*74a4d8c2SCharles.Forsyth }
160