mesg2.c 7.39 KB
#include <os.h>
#include <rmon.h>
#include "corefunc.h"

/*
 * mesg2
 *
 * Tests for:
 *	osSendMesg
 *	osRecvMesg
 *
 * Assumed working:
 *	osGetIntMask
 *	osSetIntMask
 *	osCreateMesgQueue
 *	osCreateThread
 *	osStartThread
 *	osYieldThread
 *
 * Description:
 *	Check that osSendMesg blocks when requested and there is no more
 *		room in the message queue.
 *	Check that osSendRecvMesg does not yield processor when blocked
 *		sending thread has same priority as receiver.
 */

#define	NUM_LOG		29
#define	MAX_MESSAGE	3

static void		slave(void *);
static int		logExecution(int);

static OSMesgQueue	mesgQueue;
static OSMesg		mesgBuf[MAX_MESSAGE];

static OSMesgQueue	slaveMesgQueue;
static OSMesg		slaveMesgBuf[1];

static OSThread		slaveThread;
static char		slaveStack[STACKSIZE];

static int		logTab[NUM_LOG];
static int		*logPtr = logTab;
static int		expLogTab[NUM_LOG] = {
	0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0,
	1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1    };

int
mesg2(void)
{
    OSIntMask savedMask, currentMask;
    OSMesg expectedMesg;
    int i, j;
    int retValue;
    int addFailures, numFailures = 0;
    
    savedMask = osSetIntMask(OS_IM_ALL);

    osCreateMesgQueue(&slaveMesgQueue, slaveMesgBuf, 1);

    osCreateThread(&slaveThread, 100, slave, (void *)0,
		   slaveStack+STACKSIZE, 10);
    osStartThread(&slaveThread);

    if (logExecution(0))
	numFailures++;

    /*
     * Create messages queues of varying sizes, and try to send one more
     * message than it can hold. In this scenario, the slave will yield
     * after the first message.
     */
    for (i = 1; i < MAX_MESSAGE; i++) {
	osCreateMesgQueue(&mesgQueue, mesgBuf, i);
	for (j = 0; j < i+1; j++) {
	    expectedMesg = (OSMesg)((j<<24)|(j<<16)|(j<<8)|j);
	    retValue = osSendMesg(&mesgQueue, expectedMesg, OS_MESG_BLOCK);

	    if (logExecution(0))
		numFailures++;

	    if (retValue != 0) {
		osSyncPrintf(
			"mesg2: expected osSendMesg ret value %d, actual %d\n",
			0, retValue);
		numFailures++;
	    }
	    currentMask = osGetIntMask();
	    if (currentMask != OS_IM_ALL) {
		osSyncPrintf("mesg2: expected interrupt mask 0x%x, actual 0x%x\n",
			OS_IM_ALL, currentMask);
		numFailures++;
	    }
	}

	/*
	 * Yield the processor so the slave can begin empty the queue
	 */
	osYieldThread();

	if (logExecution(0))
	    numFailures++;
    }

    /*
     * Create messages queues of varying sizes, and try to send one more
     * message than it can hold. In this scenario, the slave will *not*
     * yield after the first message. Also send and receive one message
     * at the start so we're not always checking for empty at the beginning
     * of the queue.
     */
    for (i = 1; i < MAX_MESSAGE; i++) {
	osCreateMesgQueue(&mesgQueue, mesgBuf, i);
	osSendMesg(&mesgQueue, (OSMesg)0, OS_MESG_BLOCK);
	(void)osRecvMesg(&mesgQueue, (OSMesg *)NULL, OS_MESG_BLOCK);
	for (j = 0; j < i+1; j++) {
	    expectedMesg = (OSMesg)((j<<24)|(j<<16)|(j<<8)|j);
	    retValue = osSendMesg(&mesgQueue, expectedMesg, OS_MESG_BLOCK);

	    if (logExecution(0))
		numFailures++;

	    if (retValue != 0) {
		osSyncPrintf(
			"mesg2: expected osSendMesg ret value %d, actual %d\n",
			0, retValue);
		numFailures++;
	    }
	    currentMask = osGetIntMask();
	    if (currentMask != OS_IM_ALL) {
		osSyncPrintf("mesg2: expected interrupt mask 0x%x, actual 0x%x\n",
			OS_IM_ALL, currentMask);
		numFailures++;
	    }
	}
	/*
	 * Yield the processor so the slave can begin empty the queue
	 */
	osYieldThread();

	if (logExecution(0))
	    numFailures++;
    }
    (void)osRecvMesg(&slaveMesgQueue, (OSMesg *)&addFailures, OS_MESG_BLOCK);
    numFailures += addFailures;

    /*
     * Verify everybody ran when they were supposed to.
     */
    if (logPtr != &logTab[NUM_LOG]) {
	osSyncPrintf("mesg2: log table underflow\n");
	numFailures++;
    }
    for (i = 0; i < logPtr - logTab; i++) {
	if (expLogTab[i] != logTab[i]) {
	    osSyncPrintf("mesg2: expected log id %d, actual %d at entry %d\n",
		expLogTab[i], logTab[i], i);
	    numFailures++;
	}
    }

    /*
     * Restore original interrupt mask and check it once more.
     */
    currentMask = osSetIntMask(savedMask);
    if (currentMask != OS_IM_ALL) {
	osSyncPrintf("mesg2: expected interrupt mask 0x%x, actual 0x%x\n",
		OS_IM_ALL, currentMask);
	numFailures++;
    }
    return(numFailures);
}

static void
slave(void *arg)
{
    OSIntMask currentMask;
    OSMesg actualMesg, expectedMesg;
    int i, j;
    int retValue;
    int numFailures = 0;

    if (logExecution(1))
	numFailures++;

    /*
     * For each message queue, receive one message, and yield to allow
     * the master to unblock.  Then empty out the queue.
     */
    for (i = 1; i < MAX_MESSAGE; i++) {
	expectedMesg = (OSMesg)0;
	(void)osRecvMesg(&mesgQueue, &actualMesg, OS_MESG_NOBLOCK);

	if (logExecution(1))
	    numFailures++;

	if (expectedMesg != actualMesg) {
	    osSyncPrintf("mesg2: expected message 0x%x, actual 0x%x\n",
		expectedMesg, actualMesg);
	    numFailures++;
	}
	currentMask = osGetIntMask();
	if (currentMask != OS_IM_ALL) {
	    osSyncPrintf("mesg2: expected interrupt mask 0x%x, actual 0x%x\n",
		OS_IM_ALL, currentMask);
	    numFailures++;
	}
	osYieldThread();

	if (logExecution(1))
	    numFailures++;

	for (j = 1; j <i+1; j++) {
	    expectedMesg = (OSMesg)((j<<24)|(j<<16)|(j<<8)|j);
	    (void)osRecvMesg(&mesgQueue, &actualMesg, OS_MESG_BLOCK);
	    if (expectedMesg != actualMesg) {
		osSyncPrintf("mesg2: expected message 0x%x, actual 0x%x\n",
			expectedMesg, actualMesg);
		numFailures++;
	    }

	    currentMask = osGetIntMask();
	    if (currentMask != OS_IM_ALL) {
		osSyncPrintf("mesg2: expected interrupt mask 0x%x, actual 0x%x\n",
			OS_IM_ALL, currentMask);
		numFailures++;
	    }
	}

	/*
	 * Yield the processor so the master can create the next message queue.
	 */
	osYieldThread();

	if (logExecution(1))
	    numFailures++;
    }

    /*
     * For each message queue, receive *all* of the messages destined
     * to be sent before yielding.
     */
    for (i = 1; i < MAX_MESSAGE; i++) {
	for (j = 0; j < i; j++) {
	    expectedMesg = (OSMesg)((j<<24)|(j<<16)|(j<<8)|j);
	    (void)osRecvMesg(&mesgQueue, &actualMesg, OS_MESG_BLOCK);

	    if (logExecution(1))
		numFailures++;

	    if (expectedMesg != actualMesg) {
		osSyncPrintf("mesg2: expected message 0x%x, actual 0x%x\n",
			expectedMesg, actualMesg);
		numFailures++;
	    }

	    currentMask = osGetIntMask();
	    if (currentMask != OS_IM_ALL) {
		osSyncPrintf("mesg2: expected interrupt mask 0x%x, actual 0x%x\n",
			OS_IM_ALL, currentMask);
		numFailures++;
	    }
	}

	expectedMesg = (OSMesg)((i<<24)|(i<<16)|(i<<8)|i);
	(void)osRecvMesg(&mesgQueue, &actualMesg, OS_MESG_BLOCK);

	if (logExecution(1))
	    numFailures++;

	if (expectedMesg != actualMesg) {
	    osSyncPrintf("mesg2: expected message 0x%x, actual 0x%x\n",
		expectedMesg, actualMesg);
	    numFailures++;
	}
	currentMask = osGetIntMask();
	if (currentMask != OS_IM_ALL) {
	    osSyncPrintf("mesg2: expected interrupt mask 0x%x, actual 0x%x\n",
		OS_IM_ALL, currentMask);
	    numFailures++;
	}
	/*
	 * Yield the processor so the master can create the next message queue.
	 */
	osYieldThread();

	if (logExecution(1))
	    numFailures++;
    }
    osSendMesg(&slaveMesgQueue, (OSMesg)numFailures, OS_MESG_BLOCK);
}

static int
logExecution(int id)
{
    if (logPtr >= &logTab[NUM_LOG]) {
	osSyncPrintf("mesg2: log table overflow\n");
	return(1);
    }
/*
    osSyncPrintf("%d. log %d\n", logPtr-logTab, id);
*/
    *logPtr++ = id;
    return(0);
}