/*
 * $Id$
 */

#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/tasks.h>
#include <exec/memory.h>
#include <exec/alerts.h>
#include <exec/ports.h>
#include <exec/libraries.h>
#include <exec/semaphores.h>
#include <exec/resident.h>

#include <dos/doshunks.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/datetime.h>
#include <dos/dosasl.h>
#include <dos/rdargs.h>

#include <clib/exec_protos.h>
#include <pragmas/exec_pragmas.h>

#include <clib/dos_protos.h>
#include <pragmas/dos_pragmas.h>

#include <utility/tagitem.h>
#include <clib/utility_protos.h>
#include <pragmas/utility_pragmas.h>

#include <string.h>

#define DOSLIB	   "dos.library"
#define DOSVER	   37L

#define OPENFAIL { Result2(ERROR_INVALID_RESIDENT_LIBRARY); }
#define EXECBASE (*(struct ExecBase **)4)

#define THISPROC    ((struct Process *)(EXECBASE->ThisTask))
#define Result2(x)  THISPROC->pr_Result2 = x


/******************************************************************************/
/*
 * Define the following to get assembly connection to the pools.
 * This will only work in SAS/C as it uses the register argument
 * passing for the routines.  Using the assembly interface gives
 * you the option of passing in SysBase in a6 already rather than
 * trying to reload it from a global symbol.
 * The Defines are used such that code for V39 can be used
 * by just adding the lines below.
 */
#define	AsmPools

#ifdef	AsmPools

void * __asm AsmCreatePool(register __d0 ULONG,register __d1 ULONG,register __d2 ULONG,register __a6 struct ExecBase *);
void __asm AsmDeletePool(register __a0 void *,register __a6 struct ExecBase *);
void * __asm AsmAllocPooled(register __a0 void *,register __d0 ULONG,register __a6 struct ExecBase *);
void __asm AsmFreePooled(register __a0 void *,register __a1 void *,register __d0 ULONG,register __a6 struct ExecBase *);

#define	CreatePool(x,y,z)	AsmCreatePool(x,y,z,(struct ExecBase *)SysBase)
#define	DeletePool(x)		AsmDeletePool(x,(struct ExecBase *)SysBase)
#define	AllocPooled(x,y)	AsmAllocPooled(x,y,(struct ExecBase *)SysBase)
#define	FreePooled(x,y,z)	AsmFreePooled(x,y,z,(struct ExecBase *)SysBase)

#else

void __stdargs *LibCreatePool(ULONG,ULONG,ULONG);
void __stdargs LibDeletePool(void *);
void __stdargs *LibAllocPooled(void *,ULONG);
void __stdargs LibFreePooled(void *,void *,ULONG);

#define	CreatePool	LibCreatePool
#define	DeletePool	LibDeletePool
#define	AllocPooled	LibAllocPooled
#define	FreePooled	LibFreePooled

struct	Library		*SysBase=NULL;

#endif
/******************************************************************************/


/* This is the command template. */
#define TEMPLATE  "SIZE/N,THRESH/N"

#define	OPT_SIZE	0
#define	OPT_THRESH	1
#define	OPT_COUNT	2


LONG cmd_loadvf(void)
{
#ifdef	AsmPools
struct	Library		*SysBase;
#endif
struct	DosLibrary	*DOSBase;
	LONG		rc;

	SysBase = (*((struct Library **) 4));

	rc=RETURN_FAIL;
	if (DOSBase = (struct DosLibrary *)OpenLibrary(DOSLIB,DOSVER))
	{
	struct	RDargs	*rdargs;
		LONG	opts[OPT_COUNT];

		memset((char *)opts, 0, sizeof(opts));
		rdargs = ReadArgs(TEMPLATE, opts, NULL);

		if (rdargs == NULL)
		{
			PrintFault(IoErr(),NULL);
		}
		else
		{
		VOID	*pool;
		VOID	*mem1;
		VOID	*mem2;
		ULONG	size=200;
		ULONG	thresh=100;
		ULONG	loop;
		ULONG	tmp[2];

			if (opts[OPT_SIZE]) size=*(ULONG *)opts[OPT_SIZE];
			if (opts[OPT_THRESH]) thresh=*(ULONG *)opts[OPT_THRESH];

			pool=CreatePool(MEMF_PUBLIC|MEMF_CLEAR,size,thresh);

			tmp[0]=(ULONG)pool;
			VPrintf("Created pool %08lx\n",tmp);

			if (pool)
			{
				for (loop=0;loop<10;loop++)
				{
					tmp[1]=(ULONG)AllocPooled(pool,30);
					tmp[0]=30;
					VPrintf("Allocated %ld bytes at %08lx\n",tmp);

					mem1=AllocPooled(pool,50);
					tmp[1]=(ULONG)mem1;
					tmp[0]=50;
					VPrintf("Allocated %ld bytes at %08lx\n",tmp);

					mem2=AllocPooled(pool,thresh+50);
					tmp[1]=(ULONG)mem2;
					tmp[0]=thresh+50;
					VPrintf("Allocated %ld bytes at %08lx\n",tmp);

					tmp[1]=(ULONG)AllocPooled(pool,50);
					tmp[0]=50;
					VPrintf("Allocated %ld bytes at %08lx\n",tmp);

					tmp[1]=(ULONG)AllocPooled(pool,50);
					tmp[0]=50;
					VPrintf("Allocated %ld bytes at %08lx\n",tmp);

					tmp[1]=(ULONG)AllocPooled(pool,thresh+50);
					tmp[0]=thresh+50;
					VPrintf("Allocated %ld bytes at %08lx\n",tmp);

					tmp[0]=(ULONG)mem2;
					FreePooled(pool,mem2,thresh+50);
					VPrintf("Free'ed %08lx from pool\n",tmp);

					tmp[0]=(ULONG)mem1;
					FreePooled(pool,mem1,50);
					VPrintf("Free'ed %08lx from pool\n",tmp);

					mem2=AllocPooled(pool,thresh+50);
					tmp[1]=(ULONG)mem2;
					tmp[0]=thresh+50;
					VPrintf("Allocated %ld bytes at %08lx\n",tmp);

					mem1=AllocPooled(pool,50);
					tmp[1]=(ULONG)mem1;
					tmp[0]=50;
					VPrintf("Allocated %ld bytes at %08lx\n",tmp);

					tmp[0]=(ULONG)mem1;
					FreePooled(pool,mem1,50);
					VPrintf("Free'ed %08lx from pool\n",tmp);

					mem1=AllocPooled(pool,20);
					tmp[1]=(ULONG)mem1;
					tmp[0]=20;
					VPrintf("Allocated %ld bytes at %08lx\n",tmp);

					tmp[1]=(ULONG)AllocPooled(pool,40);
					tmp[0]=40;
					VPrintf("Allocated %ld bytes at %08lx\n",tmp);

					tmp[1]=(ULONG)AllocPooled(pool,thresh+50);
					tmp[0]=thresh+50;
					VPrintf("Allocated %ld bytes at %08lx\n",tmp);

					tmp[1]=(ULONG)AllocPooled(pool,50);
					tmp[0]=50;
					VPrintf("Allocated %ld bytes at %08lx\n",tmp);

					tmp[0]=(ULONG)mem1;
					FreePooled(pool,mem1,20);
					VPrintf("Free'ed %08lx from pool\n",tmp);

					tmp[0]=(ULONG)mem2;
					FreePooled(pool,mem2,thresh+50);
					VPrintf("Free'ed %08lx from pool\n",tmp);
				}

				DeletePool(pool);
				tmp[0]=(ULONG)pool;
				VPrintf("Deleted pool %08lx\n",tmp);
			}
			FreeArgs(rdargs);
			rc=0;
		}

		CloseLibrary((struct Library *)DOSBase);
	}
	else
	{
		OPENFAIL;
	}
	return(rc);
}
