1 #include "u.h" 2 #include "../port/lib.h" 3 #include "mem.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include "../port/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 /* 21 * allocate blocks (round data base address to 64 bit boundary). 22 * if mallocz gives us more than we asked for, leave room at the front 23 * for header. 24 */ 25 Block* 26 _allocb(int size) 27 { 28 Block *b; 29 ulong addr; 30 int n; 31 32 b = mallocz(sizeof(Block)+size+Hdrspc+(BY2V-1), 0); 33 if(b == nil) 34 return nil; 35 36 b->next = nil; 37 b->list = nil; 38 b->free = nil; 39 b->flag = 0; 40 41 addr = (ulong)b; 42 addr = ROUND(addr + sizeof(Block), BY2V); 43 b->base = (uchar*)addr; 44 b->lim = ((uchar*)b) + msize(b); 45 b->rp = b->base; 46 n = b->lim - b->base - size; 47 b->rp += n & ~(BY2V-1); 48 b->wp = b->rp; 49 50 return b; 51 } 52 53 Block* 54 allocb(int size) 55 { 56 Block *b; 57 58 if(0 && up == nil) 59 panic("allocb outside process: %8.8lux", getcallerpc(&size)); 60 b = _allocb(size); 61 if(b == 0) 62 exhausted("Blocks"); 63 setmalloctag(b, getcallerpc(&size)); 64 return b; 65 } 66 67 /* 68 * interrupt time allocation 69 */ 70 Block* 71 iallocb(int size) 72 { 73 Block *b; 74 75 if(ialloc.bytes > conf.ialloc){ 76 //print("iallocb: limited %lud/%lud\n", ialloc.bytes, conf.ialloc); 77 return nil; 78 } 79 80 b = _allocb(size); 81 if(b == nil){ 82 //print("iallocb: no memory %lud/%lud\n", ialloc.bytes, conf.ialloc); 83 return nil; 84 } 85 setmalloctag(b, getcallerpc(&size)); 86 b->flag = BINTR; 87 88 ilock(&ialloc); 89 ialloc.bytes += b->lim - b->base; 90 iunlock(&ialloc); 91 92 return b; 93 } 94 95 void 96 freeb(Block *b) 97 { 98 void *dead = (void*)Bdead; 99 100 if(b == nil) 101 return; 102 103 /* 104 * drivers which perform non cache coherent DMA manage their own buffer 105 * pool of uncached buffers and provide their own free routine. 106 */ 107 if(b->free) { 108 b->free(b); 109 return; 110 } 111 if(b->flag & BINTR) { 112 ilock(&ialloc); 113 ialloc.bytes -= b->lim - b->base; 114 iunlock(&ialloc); 115 } 116 117 /* poison the block in case someone is still holding onto it */ 118 b->next = dead; 119 b->rp = dead; 120 b->wp = dead; 121 b->lim = dead; 122 b->base = dead; 123 124 free(b); 125 } 126 127 void 128 checkb(Block *b, char *msg) 129 { 130 void *dead = (void*)Bdead; 131 132 if(b == dead) 133 panic("checkb b %s %lux", msg, b); 134 if(b->base == dead || b->lim == dead || b->next == dead 135 || b->rp == dead || b->wp == dead){ 136 print("checkb: base 0x%8.8luX lim 0x%8.8luX next 0x%8.8luX\n", 137 b->base, b->lim, b->next); 138 print("checkb: rp 0x%8.8luX wp 0x%8.8luX\n", b->rp, b->wp); 139 panic("checkb dead: %s\n", msg); 140 } 141 142 if(b->base > b->lim) 143 panic("checkb 0 %s %lux %lux", msg, b->base, b->lim); 144 if(b->rp < b->base) 145 panic("checkb 1 %s %lux %lux", msg, b->base, b->rp); 146 if(b->wp < b->base) 147 panic("checkb 2 %s %lux %lux", msg, b->base, b->wp); 148 if(b->rp > b->lim) 149 panic("checkb 3 %s %lux %lux", msg, b->rp, b->lim); 150 if(b->wp > b->lim) 151 panic("checkb 4 %s %lux %lux", msg, b->wp, b->lim); 152 153 } 154 155 void 156 iallocsummary(void) 157 { 158 print("ialloc %lud/%lud\n", ialloc.bytes, conf.ialloc); 159 } 160