int1.c 9.26 KB
#include <os.h>
#include <os_internal.h>
#include <rmon.h>
#include <R4300.h>
#include "corefunc.h"

/*
 * int1
 *
 * Tests for:
 *	osSetEventMesg
 *	__osSetCause
 *	__osSetCompare
 *	__osSetCount
 *
 * Assumed working:
 *	osGetIntMask
 *	osSetIntMask
 *	osCreateMesgQueue
 *	osRecvMesg
 *	osCreateThread
 *	osStartThread
 *
 * Description:
 *	Check that interrupt messages are correctly sent and received with
 *		a blocking osRecvMesg call.
 *	Check that a message received by a previously blocked thread having
 *		the same priority of the running thread does not incorrectly
 *		preempt the running thread.
 *	Check that a message received by a previously blocked thread having
 *		a higher priority of the running thread does preempt the
 *		running thread.
 */

#define	NUM_LOG		18

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

static OSMesgQueue	sw1MesgQueue;
static OSMesg		sw1MesgBuf[1];

static OSMesgQueue	sw2MesgQueue;
static OSMesg		sw2MesgBuf[1];

static OSMesgQueue	counterMesgQueue;
static OSMesg		counterMesgBuf[1];

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, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0 };

int
int1(void)
{
    OSIntMask savedMask, currentMask;
    OSMesg actualMesg, expectedMesg;
    int i;
    int retValue;
    int addFailures, numFailures = 0;
    
    savedMask = osSetIntMask(OS_IM_NONE);

    /*
     * Trigger a SW1 interrupt, block for it, and check it.
     */
    osCreateMesgQueue(&sw1MesgQueue, sw1MesgBuf, 1);
    expectedMesg = (OSMesg)0x11111111;
    osSetEventMesg(OS_EVENT_SW1, &sw1MesgQueue, expectedMesg);

    __osSetCause(CAUSE_SW1);

    (void)osRecvMesg(&sw1MesgQueue, &actualMesg, OS_MESG_BLOCK);
    if (expectedMesg != actualMesg) {
	osSyncPrintf("int1: expected message 0x%x, actual 0x%x\n",
		expectedMesg, actualMesg);
	numFailures++;
    }
    currentMask = osGetIntMask();
    if (currentMask != OS_IM_NONE) {
	osSyncPrintf("int1: expected interrupt mask 0x%x, actual 0x%x\n",
		OS_IM_NONE, currentMask);
	numFailures++;
    }

    /*
     * Trigger a SW2 interrupt, block for it, and check it.
     */
    osCreateMesgQueue(&sw2MesgQueue, sw2MesgBuf, 1);
    expectedMesg = (OSMesg)0x22222222;
    osSetEventMesg(OS_EVENT_SW2, &sw2MesgQueue, expectedMesg);

    __osSetCause(CAUSE_SW2);

    (void)osRecvMesg(&sw2MesgQueue, &actualMesg, OS_MESG_BLOCK);
    if (expectedMesg != actualMesg) {
	osSyncPrintf("int1: expected message 0x%x, actual 0x%x\n",
		expectedMesg, actualMesg);
	numFailures++;
    }
    currentMask = osGetIntMask();
    if (currentMask != OS_IM_NONE) {
	osSyncPrintf("int1: expected interrupt mask 0x%x, actual 0x%x\n",
		OS_IM_NONE, currentMask);
	numFailures++;
    }

    /*
     * Trigger a counter interrupt, block for it, and check it.
     */
    osCreateMesgQueue(&counterMesgQueue, counterMesgBuf, 1);
    expectedMesg = (OSMesg)0x33333333;
    osSetEventMesg(OS_EVENT_COUNTER, &counterMesgQueue, expectedMesg);

    __osSetCompare(0);
    __osSetCount(0);

    (void)osRecvMesg(&counterMesgQueue, &actualMesg, OS_MESG_BLOCK);

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

    /*
     * Give the master (current) thread the same priority as the slave's
     * initial priority.
     */

    osSetThreadPri(NULL, 10);

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

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

    if (logExecution(0))		/* 0 */
	numFailures++;

    osYieldThread();

    if (logExecution(0))		/* 2 */
	numFailures++;

    /*
     * Trigger a SW1 interrupt that will be received by the child.
     */

    __osSetCause(CAUSE_SW1);

    /*
     * A context switch should not occur here.
     */
    if (logExecution(0))		/* 3 */
	numFailures++;

    osYieldThread();

    if (logExecution(0))		/* 5 */
	numFailures++;

   /* 
    * Repeat the exercise with the SW2 interrupt.
    */
    __osSetCause(CAUSE_SW2);

    /*
     * A context switch should not occur here.
     */
    if (logExecution(0))		/* 6 */
	numFailures++;

    osYieldThread();

    if (logExecution(0))		/* 8 */
	numFailures++;

   /*
    * Repeat the exercise with the counter interrupt.
    */
    __osSetCount(0);

    /*
     * A context switch should not occur here.
     */
    if (logExecution(0))		/* 9 */
	numFailures++;

    osYieldThread();

    if (logExecution(0))		/* 11 */
	numFailures++;

    /*
     * Trigger a SW1 interrupt again.
     */
    __osSetCause(CAUSE_SW1);

    /*
     * This time, a context switch *will* occur here since
     * the slave is now running at a higher priority.
     */
    if (logExecution(0))		/* 13 */
	numFailures++;

   /*
    * Repeat the exercise with the SW2 interrupt.
    */
    __osSetCause(CAUSE_SW2);

    /*
     * Context switch occurs here.
     */

    if (logExecution(0))		/* 15 */
	numFailures++;

   /*
    * Repeat the exercise with the counter interrupt.
    */
    __osSetCount(0);

    /*
     * Context switch occurs here.
     */

    if (logExecution(0))		/* 17 */
	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("int1: expected interrupt mask 0x%x, actual 0x%x\n",
		OS_IM_ALL, currentMask);
	numFailures++;
    }
    return(numFailures);
}

static void
slave(void *arg)
{
    OSMesg actualMesg, expectedMesg;
    int numFailures = 0;

    if (logExecution(1))		/* 1 */
	numFailures++;

    /*
     * Block for a SW1 interrupt triggered by the master.
     */
    expectedMesg = (OSMesg)0x11111111;
    (void)osRecvMesg(&sw1MesgQueue, &actualMesg, OS_MESG_BLOCK);
    if (expectedMesg != actualMesg) {
	osSyncPrintf("int1: expected message 0x%x, actual 0x%x\n",
		expectedMesg, actualMesg);
	numFailures++;
    }

    if (logExecution(1))		/* 4 */
	numFailures++;

    /*
     * Block for a SW2 interrupt triggered by the master.
     */
    expectedMesg = (OSMesg)0x22222222;
    (void)osRecvMesg(&sw2MesgQueue, &actualMesg, OS_MESG_BLOCK);
    if (expectedMesg != actualMesg) {
	osSyncPrintf("int1: expected message 0x%x, actual 0x%x\n",
		expectedMesg, actualMesg);
	numFailures++;
    }

    if (logExecution(1))		/* 7 */
	numFailures++;

    /*
     * Block for a counter interrupt triggered by the master.
     */
    expectedMesg = (OSMesg)0x33333333;
    (void)osRecvMesg(&counterMesgQueue, &actualMesg, OS_MESG_BLOCK);
    if (expectedMesg != actualMesg) {
	osSyncPrintf("int1: expected message 0x%x, actual 0x%x\n",
		expectedMesg, actualMesg);
	numFailures++;
    }

    if (logExecution(1))		/* 10 */
	numFailures++;

    /*
     * Give the slave (current) thread a higher priority than the master.
     * Now the slave will be scheduled immediately after receiving the
     * interrupts below.
     */

    osSetThreadPri(NULL, 20);

    /*
     * Block for a SW1 interrupt triggered by the master.
     */
    expectedMesg = (OSMesg)0x11111111;
    (void)osRecvMesg(&sw1MesgQueue, &actualMesg, OS_MESG_BLOCK);
    if (expectedMesg != actualMesg) {
	osSyncPrintf("int1: expected message 0x%x, actual 0x%x\n",
		expectedMesg, actualMesg);
	numFailures++;
    }

    if (logExecution(1))		/* 12 */
	numFailures++;

    /*
     * Block for a SW2 interrupt triggered by the master.
     */
    expectedMesg = (OSMesg)0x22222222;
    (void)osRecvMesg(&sw2MesgQueue, &actualMesg, OS_MESG_BLOCK);
    if (expectedMesg != actualMesg) {
	osSyncPrintf("int1: expected message 0x%x, actual 0x%x\n",
		expectedMesg, actualMesg);
	numFailures++;
    }

    if (logExecution(1))		/* 14 */
	numFailures++;

    /*
     * Block for a counter interrupt triggered by the master.
     */
    expectedMesg = (OSMesg)0x33333333;
    (void)osRecvMesg(&counterMesgQueue, &actualMesg, OS_MESG_BLOCK);
    if (expectedMesg != actualMesg) {
	osSyncPrintf("int1: expected message 0x%x, actual 0x%x\n",
		expectedMesg, actualMesg);
	numFailures++;
    }

    if (logExecution(1))		/* 16 */
	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);
}