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