FreeBSD/Linux Kernel Cross Reference
sys/port/allocb.c
1 #include "u.h"
2 #include "../port/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;
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 _xinc(&b->ref);
35
36 /* align start of data portion by rounding up */
37 addr = (ulong)b;
38 addr = ROUND(addr + sizeof(Block), BLOCKALIGN);
39 b->base = (uchar*)addr;
40
41 /* align end of data portion by rounding down */
42 b->lim = ((uchar*)b) + msize(b);
43 addr = (ulong)(b->lim);
44 addr = addr & ~(BLOCKALIGN-1);
45 b->lim = (uchar*)addr;
46
47 /* leave sluff at beginning for added headers */
48 b->rp = b->lim - ROUND(size, BLOCKALIGN);
49 if(b->rp < b->base)
50 panic("_allocb");
51 b->wp = b->rp;
52
53 return b;
54 }
55
56 Block*
57 allocb(int size)
58 {
59 Block *b;
60
61 /*
62 * Check in a process and wait until successful.
63 * Can still error out of here, though.
64 */
65 if(up == nil)
66 panic("allocb without up: %#p", getcallerpc(&size));
67 if((b = _allocb(size)) == nil){
68 xsummary();
69 mallocsummary();
70 panic("allocb: no memory for %d bytes", size);
71 }
72 setmalloctag(b, getcallerpc(&size));
73
74 return b;
75 }
76
77 Block*
78 iallocb(int size)
79 {
80 Block *b;
81 static int m1, m2, mp;
82
83 if(ialloc.bytes > conf.ialloc){
84 if((m1++%10000)==0){
85 if(mp++ > 1000){
86 active.exiting = 1;
87 exit(0);
88 }
89 iprint("iallocb: limited %lud/%lud\n",
90 ialloc.bytes, conf.ialloc);
91 }
92 return nil;
93 }
94
95 if((b = _allocb(size)) == nil){
96 if((m2++%10000)==0){
97 if(mp++ > 1000){
98 active.exiting = 1;
99 exit(0);
100 }
101 iprint("iallocb: no memory %lud/%lud\n",
102 ialloc.bytes, conf.ialloc);
103 }
104 return nil;
105 }
106 setmalloctag(b, getcallerpc(&size));
107 b->flag = BINTR;
108
109 ilock(&ialloc);
110 ialloc.bytes += b->lim - b->base;
111 iunlock(&ialloc);
112
113 return b;
114 }
115
116 void
117 freeb(Block *b)
118 {
119 void *dead = (void*)Bdead;
120 long ref;
121
122 if(b == nil || (ref = _xdec(&b->ref)) > 0)
123 return;
124
125 if(ref < 0){
126 dumpstack();
127 panic("ref %ld callerpc %#p", ref, getcallerpc(&b));
128 }
129
130 /*
131 * drivers which perform non cache coherent DMA manage their own buffer
132 * pool of uncached buffers and provide their own free routine.
133 */
134 if(b->free) {
135 b->free(b);
136 return;
137 }
138 if(b->flag & BINTR) {
139 ilock(&ialloc);
140 ialloc.bytes -= b->lim - b->base;
141 iunlock(&ialloc);
142 }
143
144 /* poison the block in case someone is still holding onto it */
145 b->next = dead;
146 b->rp = dead;
147 b->wp = dead;
148 b->lim = dead;
149 b->base = dead;
150
151 free(b);
152 }
153
154 void
155 checkb(Block *b, char *msg)
156 {
157 void *dead = (void*)Bdead;
158
159 if(b == dead)
160 panic("checkb b %s %#p", msg, b);
161 if(b->base == dead || b->lim == dead || b->next == dead
162 || b->rp == dead || b->wp == dead){
163 print("checkb: base %#p lim %#p next %#p\n",
164 b->base, b->lim, b->next);
165 print("checkb: rp %#p wp %#p\n", b->rp, b->wp);
166 panic("checkb dead: %s", msg);
167 }
168
169 if(b->base > b->lim)
170 panic("checkb 0 %s %#p %#p", msg, b->base, b->lim);
171 if(b->rp < b->base)
172 panic("checkb 1 %s %#p %#p", msg, b->base, b->rp);
173 if(b->wp < b->base)
174 panic("checkb 2 %s %#p %#p", msg, b->base, b->wp);
175 if(b->rp > b->lim)
176 panic("checkb 3 %s %#p %#p", msg, b->rp, b->lim);
177 if(b->wp > b->lim)
178 panic("checkb 4 %s %#p %#p", msg, b->wp, b->lim);
179 }
180
181 void
182 iallocsummary(void)
183 {
184 print("ialloc %lud/%lud\n", ialloc.bytes, conf.ialloc);
185 }
Cache object: 0059afaf593cb8563a4d32225eec7aee
|