/*

mem.c - Memory routines

*/

/*...sincludes:0:*/
#include <stdlib.h>
#include "list.h"
#include "fiber.h"
#include "mem.h"

/*...vlist\46\h:0:*/
/*...vfiber\46\h:0:*/
/*...vmem\46\h:0:*/
/*...e*/

/*...smem_init_empty:0:*/
void mem_init_empty(MEM_POOL *mpool)
	{
	mpool->count = 0;
	list_init(&(mpool->free));
	list_init(&(mpool->waiters));
	}
/*...e*/
/*...smem_init:0:*/
void mem_init(MEM_POOL *mpool, byte *ptr, unsigned n, unsigned size)
	{
	mpool->count = n;
	list_init(&(mpool->free));
	list_init(&(mpool->waiters));
	while ( n-- > 0 )
		{
		list_add_first(&(mpool->free), ptr);
		ptr += size;
		}
	}
/*...e*/
/*...smem_retry:0:*/
static void mem_retry(MEM_POOL *mpool)
	{
	MEM_RESERVE *mres;
	while ( (mres = list_first(&(mpool->waiters))) != NULL &&
	        mpool->count >= mres->n )
		{
		mpool->count -= mres->n;
		list_remove_first(&(mpool->waiters));
		fiber_enqueue((FIBER *) mres);
		}
	}
/*...e*/
/*...smem_reserve:0:*/
void mem_reserve(MEM_POOL *mpool, MEM_RESERVE *mres, unsigned n, NF nf, void *nfp)
	{
	mres->n         = n;
	mres->fiber.nf  = nf;
	mres->fiber.nfp = nfp;
	list_add_last(&(mpool->waiters), mres);
	mem_retry(mpool);
	}
/*...e*/
/*...smem_unreserve:0:*/
void mem_unreserve(MEM_POOL *mpool, unsigned n)
	{
	mpool->count += n;
	mem_retry(mpool);
	}
/*...e*/
/*...smem_alloc:0:*/
void *mem_alloc(MEM_POOL *mpool)
	{
	return list_remove_first(&(mpool->free));
	}
/*...e*/
/*...smem_free:0:*/
void mem_free(MEM_POOL *mpool, void *ptr)
	{
	list_add_first(&(mpool->free), ptr);
	}
/*...e*/
