/*-=-=-=-=-=-=-=-=-=-=-=- RCCL/RCI Notice of Copyright -=-=-=-=-=-=-=-=-=-=-*
 *									    *
 *	Copyright (C) 1987, 1991 by John E. Lloyd.			    *
 *									    *
 *	Information on copyright permissions, as well as a complete	    *
 *	disclaimer of warranty, is given in the file COPYRIGHT.		    *
 *									    *
 *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*---------------------------------------------------------------------------
 *		
 * MODULE NAME:	accessMem
 *
 * DESCRIPTION:	Routines for reading, writing, and finding memory objects
 *		created by allocMem(). 
 *
 *		These routines may be called from either the control or
 *		planning level.
 * 
 * CAVEATS:	The primitives lockMem() and unlockMem() cannot be called
 *		from the planning level until we provide a feature where
 *		the planning level task can mask out RCI tasks on the
 *		ARBITER.
 *
 * AUTHOR/DATE:	John Lloyd, Fall 1987
 *
 * MODIFICATION HISTORY:
 *
 *		John Lloyd, Fall 1989: Converted this over from the old
 *			'object' package.
 *
 *--------------------------------------------------------------------------*/

#include "../h/allocMem.h"
#include "../h/rciTask.h"
#include "../h/errorCodes.h"

#include "../rci/hashTable.h"
#include "../rci/maskInterrupts.h"

/* ----- Error Messages. Defined externally to save space ----- */

static char *cantLocateMemMsg	= "%s -- can't locate memory 0x%x\n";

void *locateSharedMem();

void *getMemByNameId (name, id)
const char *name;
int id;
{
	char *fxnName = "getMemByNameId()";

	char *raw;
	void *addr;
	int cpu;

	if (hashTableLookup (name, id, &addr, &cpu) <= 0)
	 { return (NULL);
	 }
	if ((raw = (char*)locateSharedMem (addr)) == NULL)
	 { rciAbort (EInternal, cantLocateMemMsg, fxnName, addr);
	   return (NULL);
	 }
	return ((void*)(raw + sizeof(MEM_HEADER)));
}

void *getMemByName (name)
const char *name;
{
	return (getMemByNameId (name, MEM_HASH_ID));
}

char *getMemName (mem)
void *mem;
{
	MEM_HEADER *ohead;

	ohead = (MEM_HEADER*)((char*)mem - sizeof(MEM_HEADER));
	return ((char*)locateSharedMem(ohead->name));
}

readMem (mem, buf)
void *mem;
void *buf;
{
	MEM_HEADER *ohead = (MEM_HEADER*)((char*)mem - sizeof(MEM_HEADER));

	atomicCopy (&ohead->mutex, mem, buf, ohead->size);
}

void *getMemByAddr (addr)
void *addr;
{
	char *fxnName = "getMemByAddr()";

	return (locateSharedMem(addr));
}

writeMem (mem, buf)
void *mem;
void *buf;
{
	MEM_HEADER *ohead = (MEM_HEADER*)((char*)mem - sizeof(MEM_HEADER));

	atomicCopy (&ohead->mutex, buf, mem, ohead->size);
}

accessMem (mem, src, dest, size)
void *mem;
void *src;
void *dest;
int size;
{
	MEM_HEADER *ohead = (MEM_HEADER*)((char*)mem - sizeof(MEM_HEADER));

	atomicCopy (&ohead->mutex, src, dest, size);
}

lockMem (mem)
void *mem;
{
	char *fxnName = "lockMem()";
	MUTEX *mutex;

	if (!controlLevelCheck(fxnName))
	 { return (-1);
	 }
	mutex = &((MEM_HEADER*)((char*)mem - sizeof(MEM_HEADER)))->mutex;
	if (!(MUTEX_VALID(mutex)))
	 { mutexAbort(fxnName, mutex);
	   return(-1);
	 }
	MASK_INTERRUPTS;
	mutexBegin (mutex);
}

unlockMem (mem)
void *mem;
{
	char *fxnName = "unlockMem()";
	MUTEX *mutex;

	if (!controlLevelCheck(fxnName))
	 { return (-1);
	 }
	mutex = &((MEM_HEADER*)((char*)mem - sizeof(MEM_HEADER)))->mutex;
	if (!(MUTEX_VALID(mutex)))
	 { mutexAbort(fxnName, mutex);
	   return(-1);
	 }
	mutexEnd (mutex);
	UNMASK_INTERRUPTS;
}	

#if TEST

#define DO_FIND	1
#define DO_GET	2

printMem (td, opcode)
RCI_DESC *td;
int opcode;
{
	char *memName;
	void **memAddr;
	char *ack;
	char *op;
	static char memValue[256];

	if ((ack = getMemByName("OBJECT_ACK")) == NULL)
	 { rciPrintf ("error -- can't get OBJECT ACK object\n");
	   return (-1);
	 }
	rciPrintf ("excuting %s\n",
		   opcode == DO_GET ? "get" :
		   opcode == DO_FIND ? "find" : "???");
	switch (opcode)
	 { case DO_GET:
	    { if ((memName = getMemByName("OBJECT_NAME")) == NULL)
	       { rciPrintf ("error -- can't get OBJECT NAME object\n");
		 return (-1);
	       }
	      rciPrintf ("memName = %s\n", memName);
	      if ((op = getMemByName(memName)) == NULL)
	       { rciPrintf ("error -- can't get OBJECT\n");
		 return (-1);
	       }
	      rciPrintf ("getMemName() = %s\n", getMemName(op));
	      break;
	    }
	   case DO_FIND:
	    { if ((memAddr = (void**)getMemByName("OBJECT_ADDR")) == NULL)
	       { rciPrintf ("error -- can't get OBJECT ADDR object\n");
		 return (-1);
	       }
	      rciPrintf ("memAddr = 0x%x\n", *memAddr);
	      if ((op = getMemByAddr(*memAddr)) == NULL)
	       { rciPrintf ("error -- can't get OBJECT\n");
		 return (-1);
	       }
	      rciPrintf ("getMemName() = %s\n", getMemName(op));
	      break;
	    }
	 }
	readMem (op, memValue);
	rciPrintf ("found mem: %s read value = %s\n", op, memValue);
	writeMem (ack, memValue);
	return (1);
}

void *callMalloc(td, size)
RCI_DESC *td;
int size;
{
	return (rciMalloc (size));
}

#endif
