#include <stdio.h>
#include "global.h"
#include "timer.h"
#include "proc.h"
#include "cmdparse.h"
#ifndef AZTEC_C
#include <proto/exec.h>
#endif

static unsigned long Availmem;
static unsigned long Memfail;
static unsigned long Memdeferred;
int Memwait;

static int domem __ARGS((int argc,char *argv[],void *envp));
static int dostat __ARGS((int argc,char *argv[],void *envp));
static int dothresh __ARGS((int argc,char *argv[],void *envp));

struct cmds Memcmds[] = {
	"thresh",	dothresh,	0, 0, NULLCHAR,
	"status",	dostat,		0, 0, NULLCHAR,
	NULLCHAR,
};

/*
 *  We do the best we can here, but this function returns a lie.  While
 *  we can get the free memory available to the system, we can't account
 *  for block of memory allocated from the system, but in the malloc()/free()
 *  memory pool that the C library uses for this process.  Once the Lattice C
 *  memory routines allocate memory from the system, they don't release it
 *  until the program terminates.
 *
 *  The only way around this is to chuck the Lattice C runtime version of
 *  malloc()/free() and roll our own.  But even this doesn't account for
 *  for some of the lower level memory allocation routines in the C library.
 */

unsigned long
availmem() {
	static int32 lastClock = 0;

	/*
	 * If the clock hasn't ticked, then its too soon to bother checking
	 * for more memory to be available.
	 */
	if (Clock == lastClock)
		return (unsigned long) Availmem;

	lastClock = Clock;
	Availmem = AvailMem(0);
	if (Availmem < 32*1024)
		Availmem = 0;
	else
		Availmem -= 32*1024;

	return (unsigned long) Availmem;
}


void *
mallocw(nb)
unsigned int nb;
{
	register void *p;

	if (p = malloc(nb))
		return p;

	Memdeferred++;
	while ((p = malloc(nb)) == NULL) {
		Memwait++;
		pwait(&Memwait);
		Memwait--;
	}
	return p;
}

void *
callocw(nelem,size)
unsigned int nelem,size;
{
	register void *p;

	p = mallocw(nelem*size);
	memset(p, 0, nelem*size);
	return p;
}

static int
dostat(argc, argv, envp)
int argc;
char *argv[];
void *envp;
{
	tprintf("avail %lu deferred allocs %lu\n", availmem(), Memdeferred);
	return 0;
}

int
domem(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return subcmd(Memcmds,argc,argv,p);
}

static int
dothresh(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return setlong(&Memthresh,"Free memory threshold (bytes)",argc,argv);
}
