/*****************************************************************************/

/*
 *      osprimitives.c -- REALmagic Celeste Application
 *
 *      Copyright (C) 1999-2000 Sigma Designs
 *                   written by Emmanuel Michon <emmanuel_michon@sdesigns.com>
 *
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/*****************************************************************************/

#include "remote.h"

#define LIBC_ERROR 1
#define GDB_ERROR 2

// TIMING FUNCTIONS

#define TICK 10000.0 // duration of a timeslice in microseconds.

void OSSleep_s(int i)
{
	sleep(i);
}

void OSSleep_t(int i)
{
	usleep(i*TICK);
}

DWORD OSGetTickCount_()
{
	static struct timeval firstcallisorigin={0,0};
	struct timeval now;

	if (!firstcallisorigin.tv_sec) gettimeofday(&firstcallisorigin,NULL);
		
	gettimeofday(&now,NULL);

	return (DWORD)((
		       (now.tv_sec-firstcallisorigin.tv_sec)*1000000
		       +now.tv_usec-firstcallisorigin.tv_usec
		       )/TICK);
}

DWORD OSGetClockRate()
{
	return (DWORD)1.0/(TICK*0.000001);
}

// MEMORY ALLOCATION FUNCTIONS

void *OSCelMalloc(DWORD size)
{
	return malloc(size);
}

void OSCelFree(void *p)
{
	free(p);
}

void OSCelMemCheck()
{
	// doing nothing
}

int OSInitPolling(char *thread_name, FUNCPTR func_name, DWORD context)
{
	return (int)OSCreateThread(thread_name,UNUSED_ARG,func_name,(int)context);
}

void OSThreadDelete(int thID)
{
	if (thID==0) 
		printf("Warning: thID should not be zero.\n");
	else
		OSCancelThread((THREADHANDLE)thID);
}

int OSCelSetThreadPriority(int thID, int pri)
{
	// not implemented (not needed)
	return S_OK;
}

int OSCelGetThreadPriority(int thID, int *pri)
{
	// not implemented (not needed)
	return S_OK;
}

// MESSAGE FUNCTIONS

MESSAGE_QUEUE_OBJECT OSCreateMessageQueue (void)
{
	return OSCreatemessagequeue(IPC_PRIVATE,REASONABLE_UMASK);
}

unsigned long OSDestroyMessageQueue(MESSAGE_QUEUE_OBJECT MsgQ)
{
	OSDestroyMessageQueue(MsgQ);
	return S_OK; 
}

unsigned long OSGetMessage(MESSAGE_QUEUE_OBJECT MsgQ, char *Msg, unsigned long MsgLength)
{
	OSBlockingReceiveFrommessagequeue(MsgQ,Msg,MsgLength,MSGOTHERKIND);
	return S_OK;
}

unsigned long OSPostMessage(MESSAGE_QUEUE_OBJECT MsgQ, char *Msg, unsigned long MsgLength)
{
	OSPostInmessagequeue(MsgQ,Msg,MsgLength,MSGOTHERKIND);
	return S_OK; 
}

void OSPurgeMQ(MESSAGE_QUEUE_OBJECT msgQueue)
{
	char buf[MAXMSGLENGTH];
	usleep(20*TICK);        // wait to avoid repetition
	OSGetMessage(msgQueue, buf, MAXMSGLENGTH);
}
