allocb.c - vx32 - Local 9vx git repository for patches.
(HTM) git clone git://r-36.net/vx32
(DIR) Log
(DIR) Files
(DIR) Refs
---
allocb.c (3448B)
---
1 #include "u.h"
2 #include "lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "error.h"
7
8 enum
9 {
10 Hdrspc = 64, /* leave room for high-level headers */
11 Bdead = 0x51494F42, /* "QIOB" */
12 };
13
14 struct
15 {
16 Lock lk;
17 ulong bytes;
18 } ialloc;
19
20 static Block*
21 _allocb(int size)
22 {
23 Block *b;
24 ulong addr;
25
26 if((b = mallocz(sizeof(Block)+size+Hdrspc, 0)) == nil)
27 return nil;
28
29 b->next = nil;
30 b->list = nil;
31 b->free = 0;
32 b->flag = 0;
33 b->ref = 0;
34
35 /* align start of data portion by rounding up */
36 addr = (ulong)b;
37 addr = ROUND(addr + sizeof(Block), BLOCKALIGN);
38 b->base = (uchar*)addr;
39
40 /* align end of data portion by rounding down */
41 b->lim = ((uchar*)b) + sizeof(Block)+size+Hdrspc;
42 addr = (ulong)(b->lim);
43 addr = addr & ~(BLOCKALIGN-1);
44 b->lim = (uchar*)addr;
45
46 /* leave sluff at beginning for added headers */
47 b->rp = b->lim - ROUND(size, BLOCKALIGN);
48 if(b->rp < b->base)
49 panic("_allocb");
50 b->wp = b->rp;
51
52 return b;
53 }
54
55 Block*
56 allocb(int size)
57 {
58 Block *b;
59
60 /*
61 * Check in a process and wait until successful.
62 * Can still error out of here, though.
63 */
64 if(up == nil)
65 panic("allocb without up: %#p", getcallerpc(&size));
66 if((b = _allocb(size)) == nil){
67 xsummary();
68 mallocsummary();
69 panic("allocb: no memory for %d bytes", size);
70 }
71 setmalloctag(b, getcallerpc(&size));
72
73 return b;
74 }
75
76 Block*
77 iallocb(int size)
78 {
79 Block *b;
80 static int m1, m2, mp;
81
82 if(ialloc.bytes > conf.ialloc){
83 if((m1++%10000)==0){
84 if(mp++ > 1000){
85 active.exiting = 1;
86 panic("iallocb");
87 }
88 iprint("iallocb: limited %lud/%lud\n",
89 ialloc.bytes, conf.ialloc);
90 }
91 return nil;
92 }
93
94 if((b = _allocb(size)) == nil){
95 if((m2++%10000)==0){
96 if(mp++ > 1000){
97 active.exiting = 1;
98 panic("iallocb");
99 }
100 iprint("iallocb: no memory %lud/%lud\n",
101 ialloc.bytes, conf.ialloc);
102 }
103 return nil;
104 }
105 setmalloctag(b, getcallerpc(&size));
106 b->flag = BINTR;
107
108 ilock(&ialloc.lk);
109 ialloc.bytes += b->lim - b->base;
110 iunlock(&ialloc.lk);
111
112 return b;
113 }
114
115 void
116 freeb(Block *b)
117 {
118 void *dead = (void*)Bdead;
119 long ref;
120
121 if(b == nil)
122 return;
123
124 if(0){
125 dumpstack();
126 panic("freeb: ref %ld; caller pc %#p", ref, getcallerpc(&b));
127 }
128
129 /*
130 * drivers which perform non cache coherent DMA manage their own buffer
131 * pool of uncached buffers and provide their own free routine.
132 */
133 if(b->free) {
134 b->free(b);
135 return;
136 }
137 if(b->flag & BINTR) {
138 ilock(&ialloc.lk);
139 ialloc.bytes -= b->lim - b->base;
140 iunlock(&ialloc.lk);
141 }
142
143 /* poison the block in case someone is still holding onto it */
144 b->next = dead;
145 b->rp = dead;
146 b->wp = dead;
147 b->lim = dead;
148 b->base = dead;
149
150 free(b);
151 }
152
153 void
154 checkb(Block *b, char *msg)
155 {
156 void *dead = (void*)Bdead;
157
158 if(b == dead)
159 panic("checkb b %s %#p", msg, b);
160 if(b->base == dead || b->lim == dead || b->next == dead
161 || b->rp == dead || b->wp == dead){
162 print("checkb: base %#p lim %#p next %#p\n",
163 b->base, b->lim, b->next);
164 print("checkb: rp %#p wp %#p\n", b->rp, b->wp);
165 panic("checkb dead: %s", msg);
166 }
167
168 if(b->base > b->lim)
169 panic("checkb 0 %s %#p %#p", msg, b->base, b->lim);
170 if(b->rp < b->base)
171 panic("checkb 1 %s %#p %#p", msg, b->base, b->rp);
172 if(b->wp < b->base)
173 panic("checkb 2 %s %#p %#p", msg, b->base, b->wp);
174 if(b->rp > b->lim)
175 panic("checkb 3 %s %#p %#p", msg, b->rp, b->lim);
176 if(b->wp > b->lim)
177 panic("checkb 4 %s %#p %#p", msg, b->wp, b->lim);
178 }
179
180 void
181 iallocsummary(void)
182 {
183 print("ialloc %lud/%lud\n", ialloc.bytes, conf.ialloc);
184 }