Ejemplo n.º 1
0
static boolean
getmoreblocks(int sz)
{
	void *page;
	int bpp;
	int ind;
	struct freeblock *e;
	struct pageinfo *pi;
	int i;

	FPRINTF((stderr, "getmoreblocks(%d)\n", sz));

	if (sz < 1 || sz > PAGETHRESHHOLD)
		return FALSE;

	FPRINTF((stderr, "getmoreblocks(%d), size is valid\n", sz));
	page = allocpages(1);		/* get a page */

	if (page == NULL)
		return FALSE;

	FPRINTF((stderr, "getmoreblocks(%d), got new page\n", sz));

	/* fill out pageinfo for this page */
	bpp = (BYTESPERPAGE - sizeof (struct pageinfo)) / sz;
	ind = sz / MINBLOCK;
	e = (struct freeblock *)((char *)page + sizeof (struct pageinfo));
	pi = (struct pageinfo *)page;
	pi->blocksize = sz;
	pi->numblocks = bpp;
	pi->block = e;
	pi->link = g.blockmap[ind];
	g.blockmap[ind] = pi;
	bpp--;

	for (i = 0; i < bpp; i++, e = e->link)
		e->link = (struct freeblock *)((char *)e + sz);

	e->link = NULL;

#ifdef DO_GC
	CLEARBITMAP(pi->refbits);
	ind = PAGENUM(pi);

	if (ind >= MAXPAGES)
		crash("getmoreblocks(): out of space for new pages");

	SETBIT(g.ourpages, ind);
#endif

	return TRUE;
}
Ejemplo n.º 2
0
int _mmfree(int _free_addr, unsigned long long* pgbitmap){
	if( _free_addr==-1)
		return -1;
	CLEARBITMAP(_free_addr, pgbitmap);
	return 0;
}
Ejemplo n.º 3
0
void *
malloc(size_t sz)
{
	int nsz;
	int ind, i;
	struct pageinfo *ppi;
	struct pageinfo *pi;
	void *ptr;

	if (!initialized)
		init();

	if (sz >= PAGETHRESHHOLD - sizeof (struct pageinfo))
	{
		/* block is bigger than threshhold so allocate whole pages */
		int pgs = (sz + sizeof (struct pageinfo)+BYTESPERPAGE - 1) /
			BYTESPERPAGE;
		void *base = allocpages(pgs);

		FPRINTF((stderr, "malloc(%d), large block\n", sz));

		if (base == NULL)
			return NULL;

		pi = (struct pageinfo *)base;
		pi->blocksize = -1;
		pi->numblocks = 0;
		pi->count = pgs;
		pi->link = NULL;
		base = (char *)base + sizeof (struct pageinfo);

		if (g.clearblocks)
			memset(base, 0, pgs * BYTESPERPAGE - sizeof (struct pageinfo));

#ifdef DO_GC
		CLEARBITMAP(pi->refbits);
		ind = PAGENUM(pi);

		if (ind + pgs >= MAXPAGES)
			crash("malloc(): out of space for new pages");

		SETBIT(g.ourpages, ind);

		/* all following pages are marked as part of a big block for GC */
		for (ind++, i = 1; i < pgs; i++, ind++)
			CLEARBIT(g.ourpages, ind);
#endif

		return base;
	}

/* search page list for a free block of our size */
nsz = g.sizemap[sz];

	if (nsz < sz)
		nsz = sz;

	FPRINTF((stderr, "malloc(%d), small block, sz = %d\n", sz, nsz));
	ind = nsz / MINBLOCK;
	ppi = NULL;
	pi = g.blockmap[ind];

	/* search pages with blocks of the given size */
	for (; pi != NULL && pi->block == NULL; pi = pi->link)
		ppi = pi;

	if (pi == NULL)
	{
		if (!getmoreblocks(nsz))
		{
			FPRINTF((stderr, "malloc(%d), no more small blocks\n", sz));
			return NULL;
		}

		/* this works since getmoreblocks always sticks new pages */
		/* at the front of the list */
		pi = g.blockmap[ind];
		ppi = NULL;
	}

	if (ppi != NULL)
	{
		/* move page with free blocks to the head of the list so we save
		   time on the next call for this block size. */
		ppi->link = pi->link;
		pi->link = g.blockmap[ind];
		g.blockmap[ind] = pi;
	}

	ptr = pi->block;
	pi->block = pi->block->link;
	pi->count++;

	if (g.clearblocks)
		memset(ptr, 0, nsz);

	FPRINTF((stderr, "malloc(%d), nsz=%d small block=%p\n", sz, nsz, ptr));
	return (void *)ptr;
}
Ejemplo n.º 4
0
/* garbage collect using mark & sweep */
void
garbagecollect()
{
	static jmp_buf jmp;
	long stacktop;				/* to get the top of stack */
	int i, numpgs;
	struct pageinfo *page;
	size_t totfree;
	int arenasz, expandcnt;

	if (g.ingc || g.heaphigh == NULL)
		return;

	g.ingc = TRUE;

	/* ref bits should already be cleared since we clear them upon return
	   to avoid doing an extra pass over all of memory */

	/* this does not go in our "gc" struct as we really do want it
	   searched */
	memset(jmp, 0, sizeof jmp);
	setjmp(jmp);
	totfree = 0;

	/* set ref bits of referenced blocks */
	gcmarkregion(STACKSTART, STACKEND);

	for (i = 0; i < g.numregions; i++)
	{
		if (g.regions[i].start == NULL)
			continue;

		gcmarkregion(g.regions[i].start, g.regions[i].end);
	}

	numpgs = PAGENUM(g.heaphigh);
	page = g.heaplow;

	/* release unused memory */
	for (i = PAGENUM(page); i < numpgs; i++,
			page = (struct pageinfo *)((char *)page + BYTESPERPAGE))
	{
		if (i >= MAXPAGES)
			crash("garbagecollect(): out of space for new pages");

		if (!GETBIT(g.ourpages, i))
			continue;

		if (page->blocksize == -1)
		{
			if (page->refbits[0])
				page->refbits[0] = 0;
			else
				freepages(page, page->count);
		}
		else if (page->blocksize > 0)
		{
			int j;
			int freed = 0;
			page->block = NULL;

			for (j = 0; j < page->numblocks; j++)
				if (!GETBIT(page->refbits, j))
				{
					struct freeblock *e = (struct freeblock *)
						((char *)page + sizeof (struct pageinfo)+
							page->blocksize * j);

					if (g.clearfree)
						memset(e, 0, page->blocksize);

					e->link = page->block;
					page->block = e;
					freed++;
				}

			CLEARBITMAP(page->refbits);

			if (freed == page->numblocks)
				freeblockspage(page);
			else
			{
				page->count = page->numblocks - freed;
				totfree += freed * page->blocksize;
			}
		}
	}

	/* rebuildfreelist(); */
	g.ingc = FALSE;

	totfree += g.numfreepages * BYTESPERPAGE;
	arenasz = ((char *)g.heaphigh - (char *)g.heaplow) / BYTESPERPAGE;
	expandcnt = arenasz * g.percent;
	expandcnt /= 100;

	if (g.freepagelist == NULL)
	{
		/* if garbage collection didn't yield a page then allow */
		/* heap to grow by g.page or g.percent which ever is larger. */
		g.pagecount = (g.pages > expandcnt ? g.pages : expandcnt);
	}
	else
	{
		/* if garbage collection yielded less than g.percent of the heap */
		/* then give the heap some extra growing room. */
		expandcnt -= totfree / BYTESPERPAGE;
		expandcnt -= g.numfreepages;

		if (g.pagecount < expandcnt)
			g.pagecount = expandcnt;

		if (g.pagecount <= 0)
			g.pagecount = 16;
	}

	return;
}