1*afe147c3SDavid du Colombier /*
2*afe147c3SDavid du Colombier * allocate Blocks from uncached memory
3*afe147c3SDavid du Colombier */
4*afe147c3SDavid du Colombier #include "u.h"
5*afe147c3SDavid du Colombier #include "../port/lib.h"
6*afe147c3SDavid du Colombier #include "mem.h"
7*afe147c3SDavid du Colombier #include "dat.h"
8*afe147c3SDavid du Colombier #include "fns.h"
9*afe147c3SDavid du Colombier #include "error.h"
10*afe147c3SDavid du Colombier
11*afe147c3SDavid du Colombier enum
12*afe147c3SDavid du Colombier {
13*afe147c3SDavid du Colombier Hdrspc = 64, /* leave room for high-level headers */
14*afe147c3SDavid du Colombier Bdead = 0x51494F42, /* "QIOB" */
15*afe147c3SDavid du Colombier };
16*afe147c3SDavid du Colombier
17*afe147c3SDavid du Colombier struct
18*afe147c3SDavid du Colombier {
19*afe147c3SDavid du Colombier Lock;
20*afe147c3SDavid du Colombier ulong bytes;
21*afe147c3SDavid du Colombier } ucialloc;
22*afe147c3SDavid du Colombier
23*afe147c3SDavid du Colombier static Block*
_ucallocb(int size)24*afe147c3SDavid du Colombier _ucallocb(int size)
25*afe147c3SDavid du Colombier {
26*afe147c3SDavid du Colombier Block *b;
27*afe147c3SDavid du Colombier ulong addr;
28*afe147c3SDavid du Colombier
29*afe147c3SDavid du Colombier if((b = ucalloc(sizeof(Block)+size+Hdrspc)) == nil)
30*afe147c3SDavid du Colombier return nil;
31*afe147c3SDavid du Colombier
32*afe147c3SDavid du Colombier b->next = nil;
33*afe147c3SDavid du Colombier b->list = nil;
34*afe147c3SDavid du Colombier b->free = 0;
35*afe147c3SDavid du Colombier b->flag = 0;
36*afe147c3SDavid du Colombier b->ref = 0;
37*afe147c3SDavid du Colombier _xinc(&b->ref);
38*afe147c3SDavid du Colombier
39*afe147c3SDavid du Colombier /* align start of data portion by rounding up */
40*afe147c3SDavid du Colombier addr = (ulong)b;
41*afe147c3SDavid du Colombier addr = ROUND(addr + sizeof(Block), BLOCKALIGN);
42*afe147c3SDavid du Colombier b->base = (uchar*)addr;
43*afe147c3SDavid du Colombier
44*afe147c3SDavid du Colombier /* align end of data portion by rounding down */
45*afe147c3SDavid du Colombier b->lim = ((uchar*)b) + msize(b);
46*afe147c3SDavid du Colombier addr = (ulong)(b->lim);
47*afe147c3SDavid du Colombier addr = addr & ~(BLOCKALIGN-1);
48*afe147c3SDavid du Colombier b->lim = (uchar*)addr;
49*afe147c3SDavid du Colombier
50*afe147c3SDavid du Colombier /* leave sluff at beginning for added headers */
51*afe147c3SDavid du Colombier b->rp = b->lim - ROUND(size, BLOCKALIGN);
52*afe147c3SDavid du Colombier if(b->rp < b->base)
53*afe147c3SDavid du Colombier panic("_ucallocb");
54*afe147c3SDavid du Colombier b->wp = b->rp;
55*afe147c3SDavid du Colombier
56*afe147c3SDavid du Colombier return b;
57*afe147c3SDavid du Colombier }
58*afe147c3SDavid du Colombier
59*afe147c3SDavid du Colombier Block*
ucallocb(int size)60*afe147c3SDavid du Colombier ucallocb(int size)
61*afe147c3SDavid du Colombier {
62*afe147c3SDavid du Colombier Block *b;
63*afe147c3SDavid du Colombier
64*afe147c3SDavid du Colombier /*
65*afe147c3SDavid du Colombier * Check in a process and wait until successful.
66*afe147c3SDavid du Colombier * Can still error out of here, though.
67*afe147c3SDavid du Colombier */
68*afe147c3SDavid du Colombier if(up == nil)
69*afe147c3SDavid du Colombier panic("ucallocb without up: %#p", getcallerpc(&size));
70*afe147c3SDavid du Colombier if((b = _ucallocb(size)) == nil)
71*afe147c3SDavid du Colombier panic("ucallocb: no memory for %d bytes", size);
72*afe147c3SDavid du Colombier setmalloctag(b, getcallerpc(&size));
73*afe147c3SDavid du Colombier
74*afe147c3SDavid du Colombier return b;
75*afe147c3SDavid du Colombier }
76*afe147c3SDavid du Colombier
77*afe147c3SDavid du Colombier Block*
uciallocb(int size)78*afe147c3SDavid du Colombier uciallocb(int size)
79*afe147c3SDavid du Colombier {
80*afe147c3SDavid du Colombier Block *b;
81*afe147c3SDavid du Colombier static int m1, m2, mp;
82*afe147c3SDavid du Colombier
83*afe147c3SDavid du Colombier if(0 && ucialloc.bytes > conf.ialloc){
84*afe147c3SDavid du Colombier if((m1++%10000)==0){
85*afe147c3SDavid du Colombier if(mp++ > 1000){
86*afe147c3SDavid du Colombier active.exiting = 1;
87*afe147c3SDavid du Colombier exit(0);
88*afe147c3SDavid du Colombier }
89*afe147c3SDavid du Colombier iprint("uciallocb: limited %lud/%lud\n",
90*afe147c3SDavid du Colombier ucialloc.bytes, conf.ialloc);
91*afe147c3SDavid du Colombier }
92*afe147c3SDavid du Colombier return nil;
93*afe147c3SDavid du Colombier }
94*afe147c3SDavid du Colombier
95*afe147c3SDavid du Colombier if((b = _ucallocb(size)) == nil){
96*afe147c3SDavid du Colombier if(0 && (m2++%10000)==0){
97*afe147c3SDavid du Colombier if(mp++ > 1000){
98*afe147c3SDavid du Colombier active.exiting = 1;
99*afe147c3SDavid du Colombier exit(0);
100*afe147c3SDavid du Colombier }
101*afe147c3SDavid du Colombier iprint("uciallocb: no memory %lud/%lud\n",
102*afe147c3SDavid du Colombier ucialloc.bytes, conf.ialloc);
103*afe147c3SDavid du Colombier }
104*afe147c3SDavid du Colombier return nil;
105*afe147c3SDavid du Colombier }
106*afe147c3SDavid du Colombier setmalloctag(b, getcallerpc(&size));
107*afe147c3SDavid du Colombier b->flag = BINTR;
108*afe147c3SDavid du Colombier
109*afe147c3SDavid du Colombier ilock(&ucialloc);
110*afe147c3SDavid du Colombier ucialloc.bytes += b->lim - b->base;
111*afe147c3SDavid du Colombier iunlock(&ucialloc);
112*afe147c3SDavid du Colombier
113*afe147c3SDavid du Colombier return b;
114*afe147c3SDavid du Colombier }
115*afe147c3SDavid du Colombier
116*afe147c3SDavid du Colombier void
ucfreeb(Block * b)117*afe147c3SDavid du Colombier ucfreeb(Block *b)
118*afe147c3SDavid du Colombier {
119*afe147c3SDavid du Colombier void *dead = (void*)Bdead;
120*afe147c3SDavid du Colombier long ref;
121*afe147c3SDavid du Colombier
122*afe147c3SDavid du Colombier if(b == nil || (ref = _xdec(&b->ref)) > 0)
123*afe147c3SDavid du Colombier return;
124*afe147c3SDavid du Colombier
125*afe147c3SDavid du Colombier if(ref < 0){
126*afe147c3SDavid du Colombier dumpstack();
127*afe147c3SDavid du Colombier panic("ucfreeb: ref %ld; caller pc %#p", ref, getcallerpc(&b));
128*afe147c3SDavid du Colombier }
129*afe147c3SDavid du Colombier
130*afe147c3SDavid du Colombier /*
131*afe147c3SDavid du Colombier * drivers which perform non cache coherent DMA manage their own buffer
132*afe147c3SDavid du Colombier * pool of uncached buffers and provide their own free routine.
133*afe147c3SDavid du Colombier */
134*afe147c3SDavid du Colombier if(b->free) {
135*afe147c3SDavid du Colombier b->free(b);
136*afe147c3SDavid du Colombier return;
137*afe147c3SDavid du Colombier }
138*afe147c3SDavid du Colombier if(b->flag & BINTR) {
139*afe147c3SDavid du Colombier ilock(&ucialloc);
140*afe147c3SDavid du Colombier ucialloc.bytes -= b->lim - b->base;
141*afe147c3SDavid du Colombier iunlock(&ucialloc);
142*afe147c3SDavid du Colombier }
143*afe147c3SDavid du Colombier
144*afe147c3SDavid du Colombier /* poison the block in case someone is still holding onto it */
145*afe147c3SDavid du Colombier b->next = dead;
146*afe147c3SDavid du Colombier b->rp = dead;
147*afe147c3SDavid du Colombier b->wp = dead;
148*afe147c3SDavid du Colombier b->lim = dead;
149*afe147c3SDavid du Colombier b->base = dead;
150*afe147c3SDavid du Colombier
151*afe147c3SDavid du Colombier ucfree(b);
152*afe147c3SDavid du Colombier }
153