xref: /plan9/sys/src/9/port/ucallocb.c (revision afe147c3d2695726595a8d244cde0015ee42d661)
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