/*
    SyscallMsg.c, Copyright 1999 (c) by George Fankhauser,
    Swiss Federal Institute of Technology,
    Computer Engineering and Networks Laboratory.
 
    TOPSY -- A Teachable Operating System.
             Implementation of a tiny and simple
             micro kernel for teaching purposes.
 
    For further information, please visit http://www.tik.ee.ethz.ch/~topsy
 
    This software is provided under the terms of the GNU General Public Licence.
 
    A full copy of the GNU GPL is provided in the file COPYING found in the 
    development root of Topsy.
*/
/*
	*** empty log message ***
	
	Revision 1.3  1999/05/19 14:30:47  gfa
	ome linux tweakin' done...
 
	Revision 1.2  1999/05/13 17:06:05  jeker
	Initial revision
 
*/

#include "Messages.h"
#include "Syscall.h"

#include "Unix.h"

/* message passing, usually performed by traps, is mapped to unix signals
 * 
 * the unused USR1 (SEND) and USR2 (RECV) signals are used for this purpose
 *
 * signals are, like exceptions and interrupts, centrally dispatched in
 * generalExceptionHandler(). other signals are used for task switching and
 * preemption (SIGALARM).
 */

SYSCALL_ERROR tmMsgSend(ThreadId to, Message* msg)
{
  msg->from = to;

  kill(getpid(), SEND);

#ifdef sparc

  asm("mov %g7,%i0");		// replaces the return
#endif				// on other architectures, the return register
}				// stays the same (g7 is a hack; see Unix.h)


SYSCALL_ERROR
tmMsgRecv(ThreadId* from, MessageId msgId, Message* msg, int timeOut)
{
  msg->from = *from;
  msg->id = msgId;

  kill(getpid(), RECV);

  *from = msg->from;		// from id stored by kernel in msg->from

#ifdef sparc

  asm("mov %g7,%i0");		// replaces the return
#endif				// on other architectures, the return register
}				// stays the same


Boolean testAndSet(Boolean* lockvar)
{
  Boolean ret;

  // turn off signals/clock
  sigset_t set, oldset;

  // save old mask
  sigprocmask(SIG_SETMASK, NULL, &oldset);

  // block all sigs
  sigfillset(&set);
  sigprocmask(SIG_SETMASK, &set, NULL);
  if (*lockvar == FALSE)
  {
    *lockvar = TRUE;
    ret = TRUE;
  }
  else
  {
    ret = FALSE;
  }
  // restore old mask
  sigprocmask(SIG_SETMASK, &oldset, NULL);

  return ret;
}
