/*
**	termMemory.c
**
**	Memory management routines
**
**	Copyright © 1990-1994 by Olaf `Olsen' Barthel
**		All Rights Reserved
*/

#include "termGlobal.h"

	// Main memory pool puddle size

#define PUDDLE_SIZE 32768

	// Memory allocation data

STATIC struct SignalSemaphore	MemorySemaphore;
STATIC APTR			MemoryPool;

	// Prototypes for pools.lib

APTR __asm AsmCreatePool(register __d0 ULONG MemFlags,register __d1 ULONG PuddleSize,register __d2 ULONG ThreshSize,register __a6 struct ExecBase *SysBase);
VOID __asm AsmDeletePool(register __a0 APTR PoolHeader,register __a6 struct ExecBase *SysBase);
APTR __asm AsmAllocPooled(register __a0 APTR PoolHeader, register __d0 ULONG Size,register __a6 struct ExecBase *SysBase);
VOID __asm AsmFreePooled(register __a0 APTR PoolHeader,register __a1 APTR Memory,register __d0 ULONG MemSize,register __a6 struct ExecBase *SysBase);

	/* MemorySetup():
	 *
	 *	Set up the main memory pool.
	 */

BOOLEAN
MemorySetup()
{
	InitSemaphore(&MemorySemaphore);

	if(MemoryPool = AsmCreatePool(MEMF_PUBLIC | MEMF_ANY,PUDDLE_SIZE,PUDDLE_SIZE,SysBase))
		return(TRUE);
	else
		return(FALSE);
}

	/* MemoryCleanup():
	 *
	 *	Clean up the main memory pool.
	 */

VOID
MemoryCleanup()
{
	if(MemoryPool)
	{
		AsmDeletePool(MemoryPool,SysBase);

		MemoryPool = NULL;
	}
}

	/* FreeVecPooled(APTR Memory):
	 *
	 *	Free a memory chunk.
	 */

VOID __regargs
FreeVecPooled(APTR Memory)
{
	if(Memory && MemoryPool)
	{
		ULONG *Data = (ULONG *)Memory;

		ObtainSemaphore(&MemorySemaphore);

		AsmFreePooled(MemoryPool,&Data[-1],Data[-1],SysBase);

		ReleaseSemaphore(&MemorySemaphore);
	}
}

	/* AllocVecPooled(ULONG Size,ULONG Flags):
	 *
	 *	Allocate a memory chunk from the main memory pool and
	 *	remember its size.
	 */

APTR __regargs
AllocVecPooled(ULONG Size,ULONG Flags)
{
	if(MemoryPool)
	{
		ULONG *Data;

		Size = (Size + 3 + sizeof(ULONG)) & ~3;

		ObtainSemaphore(&MemorySemaphore);

		if(Data = (ULONG *)AsmAllocPooled(MemoryPool,Size,SysBase))
		{
			ReleaseSemaphore(&MemorySemaphore);

			*Data++ = Size;

				// Zero the chunk if necessary

			if(Flags & MEMF_CLEAR)
			{
				register ULONG *Memory = Data;

				Size /= sizeof(ULONG);

				while(--Size)
					*Memory++ = 0;
			}

			return((APTR)Data);
		}

		ReleaseSemaphore(&MemorySemaphore);
	}

	return(NULL);
}
