sendmesg.c 2.54 KB
/**************************************************************************
 *									  *
 *		 Copyright (C) 1994, Silicon Graphics, Inc.		  *
 *									  *
 *  These coded instructions, statements, and computer programs  contain  *
 *  unpublished  proprietary  information of Silicon Graphics, Inc., and  *
 *  are protected by Federal copyright law.  They  may  not be disclosed  *
 *  to  third  parties  or copied or duplicated in any form, in whole or  *
 *  in part, without the prior written consent of Silicon Graphics, Inc.  *
 *									  *
 **************************************************************************/

#include "osint.h"
/* #include "assert.h" */

/*
 * Name:   osSendMesg
 *
 * Description:
 *	This routine writes a message to the back of a given message queue. 
 *	It also wakes up any thread waiting on this message queue. 
 *	If flags is set to M_BLOCK, the routine will block on a full queue; 
 *	that is, the current running thread is yielded and put back to the 
 *	message thread queue behind other threads of the same priority. 
 *	Normally, flags should be set to OS_MESG_NOBLOCK so that the routine
 *	can return when the queue is full.
 *
 *	Upon successful completion, a value of 0 is returned. Otherwise, a 
 *	value of -1 is returned.
 *
 * Globals Referenced: 
 *	None
 */
s32
osSendMesg(OSMesgQueue *mq, OSMesg msg, s32 flags)
{
	register u32 saveMask;
	register s32 last;

	/* Ensure that message queue is not null */
	/* assert(mq != NULL); */

#ifdef _DEBUG
	/* Ensure that flags contain valid data */
	if ((flags != OS_MESG_NOBLOCK) && (flags != OS_MESG_BLOCK)) {
		__osError(ERR_OSSENDMESG, 1, flags);
		return(-1);
	}
#endif

	/* Disable interrupts */
	saveMask = __osDisableInt();

	/* Check for full queue */
	while (MQ_IS_FULL(mq)) {
		if (flags == OS_MESG_BLOCK) {
			/* Yield processing and enqueue the calling thread */
			__osRunningThread->state = OS_STATE_WAITING;
			__osEnqueueAndYield(&mq->fullqueue);
		} else {
			/* Restore interrupts */
			__osRestoreInt(saveMask);
			return(-1);
		}
	}

	/* Increment the last ptr for next available slot */
	last = (mq->first + mq->validCount) % mq->msgCount;

	/* Copy message into the queue buffer */
	mq->msg[last] = msg;

	/* Increment valid message counter */
	mq->validCount++;

	/* 
	 * Now, check to see if there's any thread blocked because the
	 * queue was empty. If there is, we simply start it again.
	 */
	if (mq->mtqueue->next != NULL) {
		osStartThread(__osPopThread(&mq->mtqueue));
	}

	/* Restore interrupts */
	__osRestoreInt(saveMask);

	return(0);

}  /* end of osSendMesg */