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