19ef1f84bSDavid du Colombier #include "u.h"
29ef1f84bSDavid du Colombier #include "../port/lib.h"
39ef1f84bSDavid du Colombier #include "mem.h"
49ef1f84bSDavid du Colombier #include "dat.h"
59ef1f84bSDavid du Colombier #include "fns.h"
69ef1f84bSDavid du Colombier
79ef1f84bSDavid du Colombier enum
89ef1f84bSDavid du Colombier {
99ef1f84bSDavid du Colombier Hdrspc = 64, /* leave room for high-level headers */
109ef1f84bSDavid du Colombier Bdead = 0x51494F42, /* "QIOB" */
11*406c76faSDavid du Colombier Bmagic = 0x0910b10c,
129ef1f84bSDavid du Colombier };
139ef1f84bSDavid du Colombier
149ef1f84bSDavid du Colombier struct
159ef1f84bSDavid du Colombier {
169ef1f84bSDavid du Colombier Lock;
179ef1f84bSDavid du Colombier ulong bytes;
189ef1f84bSDavid du Colombier ulong limit;
199ef1f84bSDavid du Colombier
209ef1f84bSDavid du Colombier } ialloc;
219ef1f84bSDavid du Colombier
229ef1f84bSDavid du Colombier static Block*
_allocb(int size)239ef1f84bSDavid du Colombier _allocb(int size)
249ef1f84bSDavid du Colombier {
259ef1f84bSDavid du Colombier Block *b;
269ef1f84bSDavid du Colombier uchar *p;
279ef1f84bSDavid du Colombier int n;
289ef1f84bSDavid du Colombier
299ef1f84bSDavid du Colombier n = BLOCKALIGN + ROUNDUP(size+Hdrspc, BLOCKALIGN) + sizeof(Block);
309ef1f84bSDavid du Colombier if((p = malloc(n)) == nil)
319ef1f84bSDavid du Colombier return nil;
329ef1f84bSDavid du Colombier
339ef1f84bSDavid du Colombier b = (Block*)(p + n - sizeof(Block)); /* block at end of allocated space */
349ef1f84bSDavid du Colombier b->base = p;
359ef1f84bSDavid du Colombier b->next = nil;
369ef1f84bSDavid du Colombier b->list = nil;
379ef1f84bSDavid du Colombier b->free = 0;
389ef1f84bSDavid du Colombier b->flag = 0;
39*406c76faSDavid du Colombier b->magic = Bmagic;
409ef1f84bSDavid du Colombier
419ef1f84bSDavid du Colombier /* align base and bounds of data */
429ef1f84bSDavid du Colombier b->lim = (uchar*)(PTR2UINT(b) & ~(BLOCKALIGN-1));
439ef1f84bSDavid du Colombier
449ef1f84bSDavid du Colombier /* align start of writable data, leaving space below for added headers */
459ef1f84bSDavid du Colombier b->rp = b->lim - ROUNDUP(size, BLOCKALIGN);
469ef1f84bSDavid du Colombier b->wp = b->rp;
479ef1f84bSDavid du Colombier
489ef1f84bSDavid du Colombier if(b->rp < b->base || b->lim - b->rp < size)
499ef1f84bSDavid du Colombier panic("_allocb");
509ef1f84bSDavid du Colombier
519ef1f84bSDavid du Colombier return b;
529ef1f84bSDavid du Colombier }
539ef1f84bSDavid du Colombier
549ef1f84bSDavid du Colombier Block*
allocb(int size)559ef1f84bSDavid du Colombier allocb(int size)
569ef1f84bSDavid du Colombier {
579ef1f84bSDavid du Colombier Block *b;
589ef1f84bSDavid du Colombier
599ef1f84bSDavid du Colombier /*
609ef1f84bSDavid du Colombier * Check in a process and wait until successful.
619ef1f84bSDavid du Colombier * Can still error out of here, though.
629ef1f84bSDavid du Colombier */
639ef1f84bSDavid du Colombier if(up == nil)
64*406c76faSDavid du Colombier panic("allocb without up: %#p", getcallerpc(&size));
659ef1f84bSDavid du Colombier if((b = _allocb(size)) == nil){
66*406c76faSDavid du Colombier splhi();
679ef1f84bSDavid du Colombier mallocsummary();
68*406c76faSDavid du Colombier delay(500);
69*406c76faSDavid du Colombier panic("allocb: no memory for %d bytes; caller %#p", size,
70*406c76faSDavid du Colombier getcallerpc(&size));
719ef1f84bSDavid du Colombier }
729ef1f84bSDavid du Colombier
739ef1f84bSDavid du Colombier return b;
749ef1f84bSDavid du Colombier }
759ef1f84bSDavid du Colombier
769ef1f84bSDavid du Colombier void
ialloclimit(ulong limit)779ef1f84bSDavid du Colombier ialloclimit(ulong limit)
789ef1f84bSDavid du Colombier {
799ef1f84bSDavid du Colombier ialloc.limit = limit;
809ef1f84bSDavid du Colombier }
819ef1f84bSDavid du Colombier
829ef1f84bSDavid du Colombier Block*
iallocb(int size)839ef1f84bSDavid du Colombier iallocb(int size)
849ef1f84bSDavid du Colombier {
859ef1f84bSDavid du Colombier Block *b;
869ef1f84bSDavid du Colombier static int m1, m2, mp;
879ef1f84bSDavid du Colombier
889ef1f84bSDavid du Colombier if(ialloc.bytes > ialloc.limit){
899ef1f84bSDavid du Colombier if((m1++%10000)==0){
909ef1f84bSDavid du Colombier if(mp++ > 1000){
919ef1f84bSDavid du Colombier active.exiting = 1;
929ef1f84bSDavid du Colombier exit(0);
939ef1f84bSDavid du Colombier }
949ef1f84bSDavid du Colombier iprint("iallocb: limited %lud/%lud\n",
959ef1f84bSDavid du Colombier ialloc.bytes, ialloc.limit);
969ef1f84bSDavid du Colombier }
979ef1f84bSDavid du Colombier return nil;
989ef1f84bSDavid du Colombier }
999ef1f84bSDavid du Colombier
1009ef1f84bSDavid du Colombier if((b = _allocb(size)) == nil){
1019ef1f84bSDavid du Colombier if((m2++%10000)==0){
1029ef1f84bSDavid du Colombier if(mp++ > 1000){
1039ef1f84bSDavid du Colombier active.exiting = 1;
1049ef1f84bSDavid du Colombier exit(0);
1059ef1f84bSDavid du Colombier }
1069ef1f84bSDavid du Colombier iprint("iallocb: no memory %lud/%lud\n",
1079ef1f84bSDavid du Colombier ialloc.bytes, ialloc.limit);
1089ef1f84bSDavid du Colombier }
1099ef1f84bSDavid du Colombier return nil;
1109ef1f84bSDavid du Colombier }
1119ef1f84bSDavid du Colombier b->flag = BINTR;
1129ef1f84bSDavid du Colombier
1139ef1f84bSDavid du Colombier ilock(&ialloc);
1149ef1f84bSDavid du Colombier ialloc.bytes += b->lim - b->base;
1159ef1f84bSDavid du Colombier iunlock(&ialloc);
1169ef1f84bSDavid du Colombier
1179ef1f84bSDavid du Colombier return b;
1189ef1f84bSDavid du Colombier }
1199ef1f84bSDavid du Colombier
1209ef1f84bSDavid du Colombier void
freeb(Block * b)1219ef1f84bSDavid du Colombier freeb(Block *b)
1229ef1f84bSDavid du Colombier {
1239ef1f84bSDavid du Colombier void *dead = (void*)Bdead;
1249ef1f84bSDavid du Colombier uchar *p;
1259ef1f84bSDavid du Colombier
1269ef1f84bSDavid du Colombier if(b == nil)
1279ef1f84bSDavid du Colombier return;
128*406c76faSDavid du Colombier if(Bmagic && b->magic != Bmagic)
129*406c76faSDavid du Colombier panic("freeb: bad magic %#lux in Block %#p; caller pc %#p",
130*406c76faSDavid du Colombier b->magic, b, getcallerpc(&b));
1319ef1f84bSDavid du Colombier
1329ef1f84bSDavid du Colombier /*
1339ef1f84bSDavid du Colombier * drivers which perform non cache coherent DMA manage their own buffer
1349ef1f84bSDavid du Colombier * pool of uncached buffers and provide their own free routine.
1359ef1f84bSDavid du Colombier */
1369ef1f84bSDavid du Colombier if(b->free) {
1379ef1f84bSDavid du Colombier b->free(b);
1389ef1f84bSDavid du Colombier return;
1399ef1f84bSDavid du Colombier }
1409ef1f84bSDavid du Colombier if(b->flag & BINTR) {
1419ef1f84bSDavid du Colombier ilock(&ialloc);
1429ef1f84bSDavid du Colombier ialloc.bytes -= b->lim - b->base;
1439ef1f84bSDavid du Colombier iunlock(&ialloc);
1449ef1f84bSDavid du Colombier }
1459ef1f84bSDavid du Colombier
1469ef1f84bSDavid du Colombier p = b->base;
1479ef1f84bSDavid du Colombier
1489ef1f84bSDavid du Colombier /* poison the block in case someone is still holding onto it */
1499ef1f84bSDavid du Colombier b->next = dead;
1509ef1f84bSDavid du Colombier b->rp = dead;
1519ef1f84bSDavid du Colombier b->wp = dead;
1529ef1f84bSDavid du Colombier b->lim = dead;
1539ef1f84bSDavid du Colombier b->base = dead;
154*406c76faSDavid du Colombier b->magic = 0;
1559ef1f84bSDavid du Colombier
1569ef1f84bSDavid du Colombier free(p);
1579ef1f84bSDavid du Colombier }
1589ef1f84bSDavid du Colombier
1599ef1f84bSDavid du Colombier void
checkb(Block * b,char * msg)1609ef1f84bSDavid du Colombier checkb(Block *b, char *msg)
1619ef1f84bSDavid du Colombier {
1629ef1f84bSDavid du Colombier void *dead = (void*)Bdead;
1639ef1f84bSDavid du Colombier
1649ef1f84bSDavid du Colombier if(b == dead)
1659ef1f84bSDavid du Colombier panic("checkb b %s %#p", msg, b);
1669ef1f84bSDavid du Colombier if(b->base == dead || b->lim == dead || b->next == dead
1679ef1f84bSDavid du Colombier || b->rp == dead || b->wp == dead){
1689ef1f84bSDavid du Colombier print("checkb: base %#p lim %#p next %#p\n",
1699ef1f84bSDavid du Colombier b->base, b->lim, b->next);
1709ef1f84bSDavid du Colombier print("checkb: rp %#p wp %#p\n", b->rp, b->wp);
171*406c76faSDavid du Colombier panic("checkb dead: %s", msg);
1729ef1f84bSDavid du Colombier }
173*406c76faSDavid du Colombier if(Bmagic && b->magic != Bmagic)
174*406c76faSDavid du Colombier panic("checkb: bad magic %#lux in Block %#p", b->magic, b);
1759ef1f84bSDavid du Colombier if(b->base > b->lim)
1769ef1f84bSDavid du Colombier panic("checkb 0 %s %#p %#p", msg, b->base, b->lim);
1779ef1f84bSDavid du Colombier if(b->rp < b->base)
1789ef1f84bSDavid du Colombier panic("checkb 1 %s %#p %#p", msg, b->base, b->rp);
1799ef1f84bSDavid du Colombier if(b->wp < b->base)
1809ef1f84bSDavid du Colombier panic("checkb 2 %s %#p %#p", msg, b->base, b->wp);
1819ef1f84bSDavid du Colombier if(b->rp > b->lim)
1829ef1f84bSDavid du Colombier panic("checkb 3 %s %#p %#p", msg, b->rp, b->lim);
1839ef1f84bSDavid du Colombier if(b->wp > b->lim)
1849ef1f84bSDavid du Colombier panic("checkb 4 %s %#p %#p", msg, b->wp, b->lim);
1859ef1f84bSDavid du Colombier }
1869ef1f84bSDavid du Colombier
1879ef1f84bSDavid du Colombier void
iallocsummary(void)1889ef1f84bSDavid du Colombier iallocsummary(void)
1899ef1f84bSDavid du Colombier {
1909ef1f84bSDavid du Colombier print("ialloc %lud/%lud\n", ialloc.bytes, ialloc.limit);
1919ef1f84bSDavid du Colombier }
192