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 }