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