18ccd4a63SDavid du Colombier #include "u.h"
28ccd4a63SDavid du Colombier #include "lib.h"
38ccd4a63SDavid du Colombier #include "dat.h"
48ccd4a63SDavid du Colombier #include "fns.h"
58ccd4a63SDavid du Colombier #include "error.h"
68ccd4a63SDavid du Colombier
78ccd4a63SDavid du Colombier enum
88ccd4a63SDavid du Colombier {
98ccd4a63SDavid du Colombier Hdrspc = 64, /* leave room for high-level headers */
108ccd4a63SDavid du Colombier Bdead = 0x51494F42, /* "QIOB" */
118ccd4a63SDavid du Colombier };
128ccd4a63SDavid du Colombier
138ccd4a63SDavid du Colombier struct
148ccd4a63SDavid du Colombier {
158ccd4a63SDavid du Colombier Lock lk;
168ccd4a63SDavid du Colombier ulong bytes;
178ccd4a63SDavid du Colombier } ialloc;
188ccd4a63SDavid du Colombier
198ccd4a63SDavid du Colombier static Block*
_allocb(int size)208ccd4a63SDavid du Colombier _allocb(int size)
218ccd4a63SDavid du Colombier {
228ccd4a63SDavid du Colombier Block *b;
23*ec59a3ddSDavid du Colombier uintptr addr;
248ccd4a63SDavid du Colombier
258ccd4a63SDavid du Colombier if((b = mallocz(sizeof(Block)+size+Hdrspc, 0)) == nil)
268ccd4a63SDavid du Colombier return nil;
278ccd4a63SDavid du Colombier
288ccd4a63SDavid du Colombier b->next = nil;
298ccd4a63SDavid du Colombier b->list = nil;
308ccd4a63SDavid du Colombier b->free = 0;
318ccd4a63SDavid du Colombier b->flag = 0;
328ccd4a63SDavid du Colombier
338ccd4a63SDavid du Colombier /* align start of data portion by rounding up */
34*ec59a3ddSDavid du Colombier addr = (uintptr)b;
358ccd4a63SDavid du Colombier addr = ROUND(addr + sizeof(Block), BLOCKALIGN);
368ccd4a63SDavid du Colombier b->base = (uchar*)addr;
378ccd4a63SDavid du Colombier
388ccd4a63SDavid du Colombier /* align end of data portion by rounding down */
398ccd4a63SDavid du Colombier b->lim = ((uchar*)b) + sizeof(Block)+size+Hdrspc;
40*ec59a3ddSDavid du Colombier addr = (uintptr)(b->lim);
418ccd4a63SDavid du Colombier addr = addr & ~(BLOCKALIGN-1);
428ccd4a63SDavid du Colombier b->lim = (uchar*)addr;
438ccd4a63SDavid du Colombier
448ccd4a63SDavid du Colombier /* leave sluff at beginning for added headers */
458ccd4a63SDavid du Colombier b->rp = b->lim - ROUND(size, BLOCKALIGN);
468ccd4a63SDavid du Colombier if(b->rp < b->base)
478ccd4a63SDavid du Colombier panic("_allocb");
488ccd4a63SDavid du Colombier b->wp = b->rp;
498ccd4a63SDavid du Colombier
508ccd4a63SDavid du Colombier return b;
518ccd4a63SDavid du Colombier }
528ccd4a63SDavid du Colombier
538ccd4a63SDavid du Colombier Block*
allocb(int size)548ccd4a63SDavid du Colombier allocb(int size)
558ccd4a63SDavid du Colombier {
568ccd4a63SDavid du Colombier Block *b;
578ccd4a63SDavid du Colombier
588ccd4a63SDavid du Colombier /*
598ccd4a63SDavid du Colombier * Check in a process and wait until successful.
608ccd4a63SDavid du Colombier * Can still error out of here, though.
618ccd4a63SDavid du Colombier */
628ccd4a63SDavid du Colombier if(up == nil)
63*ec59a3ddSDavid du Colombier panic("allocb without up: %p\n", getcallerpc(&size));
648ccd4a63SDavid du Colombier if((b = _allocb(size)) == nil){
658ccd4a63SDavid du Colombier panic("allocb: no memory for %d bytes\n", size);
668ccd4a63SDavid du Colombier }
678ccd4a63SDavid du Colombier setmalloctag(b, getcallerpc(&size));
688ccd4a63SDavid du Colombier
698ccd4a63SDavid du Colombier return b;
708ccd4a63SDavid du Colombier }
718ccd4a63SDavid du Colombier
728ccd4a63SDavid du Colombier Block*
iallocb(int size)738ccd4a63SDavid du Colombier iallocb(int size)
748ccd4a63SDavid du Colombier {
758ccd4a63SDavid du Colombier Block *b;
768ccd4a63SDavid du Colombier static int m1, m2;
778ccd4a63SDavid du Colombier
788ccd4a63SDavid du Colombier if(ialloc.bytes > conf.ialloc){
798ccd4a63SDavid du Colombier if((m1++%10000)==0)
808ccd4a63SDavid du Colombier print("iallocb: limited %lud/%lud\n",
818ccd4a63SDavid du Colombier ialloc.bytes, conf.ialloc);
828ccd4a63SDavid du Colombier return 0;
838ccd4a63SDavid du Colombier }
848ccd4a63SDavid du Colombier
858ccd4a63SDavid du Colombier if((b = _allocb(size)) == nil){
868ccd4a63SDavid du Colombier if((m2++%10000)==0)
878ccd4a63SDavid du Colombier print("iallocb: no memory %lud/%lud\n",
888ccd4a63SDavid du Colombier ialloc.bytes, conf.ialloc);
898ccd4a63SDavid du Colombier return nil;
908ccd4a63SDavid du Colombier }
918ccd4a63SDavid du Colombier setmalloctag(b, getcallerpc(&size));
928ccd4a63SDavid du Colombier b->flag = BINTR;
938ccd4a63SDavid du Colombier
948ccd4a63SDavid du Colombier ilock(&ialloc.lk);
958ccd4a63SDavid du Colombier ialloc.bytes += b->lim - b->base;
968ccd4a63SDavid du Colombier iunlock(&ialloc.lk);
978ccd4a63SDavid du Colombier
988ccd4a63SDavid du Colombier return b;
998ccd4a63SDavid du Colombier }
1008ccd4a63SDavid du Colombier
1018ccd4a63SDavid du Colombier void
freeb(Block * b)1028ccd4a63SDavid du Colombier freeb(Block *b)
1038ccd4a63SDavid du Colombier {
1048ccd4a63SDavid du Colombier void *dead = (void*)Bdead;
1058ccd4a63SDavid du Colombier
1068ccd4a63SDavid du Colombier if(b == nil)
1078ccd4a63SDavid du Colombier return;
1088ccd4a63SDavid du Colombier
1098ccd4a63SDavid du Colombier /*
1108ccd4a63SDavid du Colombier * drivers which perform non cache coherent DMA manage their own buffer
1118ccd4a63SDavid du Colombier * pool of uncached buffers and provide their own free routine.
1128ccd4a63SDavid du Colombier */
1138ccd4a63SDavid du Colombier if(b->free) {
1148ccd4a63SDavid du Colombier b->free(b);
1158ccd4a63SDavid du Colombier return;
1168ccd4a63SDavid du Colombier }
1178ccd4a63SDavid du Colombier if(b->flag & BINTR) {
1188ccd4a63SDavid du Colombier ilock(&ialloc.lk);
1198ccd4a63SDavid du Colombier ialloc.bytes -= b->lim - b->base;
1208ccd4a63SDavid du Colombier iunlock(&ialloc.lk);
1218ccd4a63SDavid du Colombier }
1228ccd4a63SDavid du Colombier
1238ccd4a63SDavid du Colombier /* poison the block in case someone is still holding onto it */
1248ccd4a63SDavid du Colombier b->next = dead;
1258ccd4a63SDavid du Colombier b->rp = dead;
1268ccd4a63SDavid du Colombier b->wp = dead;
1278ccd4a63SDavid du Colombier b->lim = dead;
1288ccd4a63SDavid du Colombier b->base = dead;
1298ccd4a63SDavid du Colombier
1308ccd4a63SDavid du Colombier free(b);
1318ccd4a63SDavid du Colombier }
1328ccd4a63SDavid du Colombier
1338ccd4a63SDavid du Colombier void
checkb(Block * b,char * msg)1348ccd4a63SDavid du Colombier checkb(Block *b, char *msg)
1358ccd4a63SDavid du Colombier {
1368ccd4a63SDavid du Colombier void *dead = (void*)Bdead;
1378ccd4a63SDavid du Colombier
1388ccd4a63SDavid du Colombier if(b == dead)
1398ccd4a63SDavid du Colombier panic("checkb b %s %lux", msg, b);
1408ccd4a63SDavid du Colombier if(b->base == dead || b->lim == dead || b->next == dead
1418ccd4a63SDavid du Colombier || b->rp == dead || b->wp == dead){
1428ccd4a63SDavid du Colombier print("checkb: base 0x%8.8luX lim 0x%8.8luX next 0x%8.8luX\n",
1438ccd4a63SDavid du Colombier b->base, b->lim, b->next);
1448ccd4a63SDavid du Colombier print("checkb: rp 0x%8.8luX wp 0x%8.8luX\n", b->rp, b->wp);
1458ccd4a63SDavid du Colombier panic("checkb dead: %s\n", msg);
1468ccd4a63SDavid du Colombier }
1478ccd4a63SDavid du Colombier
1488ccd4a63SDavid du Colombier if(b->base > b->lim)
1498ccd4a63SDavid du Colombier panic("checkb 0 %s %lux %lux", msg, b->base, b->lim);
1508ccd4a63SDavid du Colombier if(b->rp < b->base)
1518ccd4a63SDavid du Colombier panic("checkb 1 %s %lux %lux", msg, b->base, b->rp);
1528ccd4a63SDavid du Colombier if(b->wp < b->base)
1538ccd4a63SDavid du Colombier panic("checkb 2 %s %lux %lux", msg, b->base, b->wp);
1548ccd4a63SDavid du Colombier if(b->rp > b->lim)
1558ccd4a63SDavid du Colombier panic("checkb 3 %s %lux %lux", msg, b->rp, b->lim);
1568ccd4a63SDavid du Colombier if(b->wp > b->lim)
1578ccd4a63SDavid du Colombier panic("checkb 4 %s %lux %lux", msg, b->wp, b->lim);
1588ccd4a63SDavid du Colombier
1598ccd4a63SDavid du Colombier }
1608ccd4a63SDavid du Colombier
1618ccd4a63SDavid du Colombier void
iallocsummary(void)1628ccd4a63SDavid du Colombier iallocsummary(void)
1638ccd4a63SDavid du Colombier {
1648ccd4a63SDavid du Colombier print("ialloc %lud/%lud\n", ialloc.bytes, conf.ialloc);
1658ccd4a63SDavid du Colombier }
166