vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | Refs

allocb.c (3448B)


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