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