thread4.c 4.04 KB
#include <os.h>
#include <os_internal.h>
#include <rmon.h>
#include <R4300.h>
#include "corefunc.h"

/*
 * thread4
 *
 * Tests for:
 *	Simple interrupt driven context switching
 *
 * Assumed working:
 *	__osSetCause
 *	osSetIntMask
 *	osGetIntMask
 *	osStartThread
 *	osCreateMesgQueue
 *	osSetEventMesg
 *	osSendMesg
 *	osRecvMesg
 *
 * Description:
 *	Checks that all CPU and FPU registers are saved correctly on
 *		a context switch.
 */

#define	NUM_SLAVES	2

static void	loSlave(void *);
static void	hiSlave(void *);

static char	loThreadStack[STACKSIZE];
static char	hiThreadStack[STACKSIZE];

static OSThread	loSlaveThread, hiSlaveThread;

static OSMesgQueue	slaveMesgQueue;
static OSMesg		slaveMesgBuf[NUM_SLAVES];

       OSMesgQueue	softintMesgQueue;
static OSMesg		softintMesgBuf[1];

int
thread4(void)
{
    OSIntMask savedMask, currentMask;
    int addFailures, numFailures = 0;
    int i;

    savedMask = osSetIntMask(OS_IM_NONE);

    osCreateMesgQueue(&slaveMesgQueue, slaveMesgBuf, NUM_SLAVES);

    osCreateMesgQueue(&softintMesgQueue, softintMesgBuf, 1);
    osSetEventMesg(OS_EVENT_SW2, &softintMesgQueue, (OSMesg)0xabcd);

    /*
     * Give the master (current) thread the highest priority.
     */

    osSetThreadPri(NULL, 20);

    osCreateThread(&hiSlaveThread, 100, hiSlave, (void *)1,
		   hiThreadStack+STACKSIZE, (OSPri)20);
    osCreateThread(&loSlaveThread, 101, loSlave, (void *)2,
		   loThreadStack+STACKSIZE, (OSPri)10);

    osStartThread(&hiSlaveThread);
    osStartThread(&loSlaveThread);

    for (i = 0; i < NUM_SLAVES; i++) {
	(void)osRecvMesg(&slaveMesgQueue, (OSMesg *)&addFailures,
		OS_MESG_BLOCK);
	numFailures += addFailures;
    }

    /*
     * Restore original interrupt mask (and check it).
     */

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

static void
loSlave(void *arg)
{
    OSIntMask currentMask;
    unsigned int currentSR;
    int numFailures = 0;

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

    /*
     * Dirty the registers and then enable the SW interrupt.
     * The hiSlave thread below will then run, dirty all of the registers,
     * and then complete.  When this (the low priority thread) resumes,
     * it will then check all of the registers.
     */
    if (dirtyAndCheck(((unsigned int)arg)<<16)) {
	osSyncPrintf("thread4: registers corrupted\n");
	numFailures++;
    }
    
    currentMask = osGetIntMask();
    if (currentMask != OS_IM_SW2) {
	osSyncPrintf("thread4: expected interrupt mask 0x%x, actual 0x%x\n",
		OS_IM_SW2, currentMask);
	numFailures++;
    }

    currentSR = __osGetSR();
    if ((currentSR & SR_CU1) != SR_CU1) {
	osSyncPrintf("thread4: hi expected SR CU1 bit on, was off\n");
	numFailures++;
    }

    osSendMesg(&slaveMesgQueue, (OSMesg)numFailures, OS_MESG_BLOCK);
}

static void
hiSlave(void *arg)
{
    OSIntMask currentMask;
    unsigned int currentSR;
    int numFailures = 0;

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

    /*
     * Trigger a SW2 interrupt that won't be received yet because it is not
     * enabled.  Call a routine that blocks until the interrupt *is* received,
     * and then dirties all of the registers.
     */
    __osSetCause(CAUSE_SW2);
    waitAndDirty(((unsigned int)arg)<<16);

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

    currentSR = __osGetSR();
    if ((currentSR & SR_CU1) != SR_CU1) {
	osSyncPrintf("thread4: hi expected SR CU1 bit on, was off\n");
	numFailures++;
    }

    osSendMesg(&slaveMesgQueue, (OSMesg)numFailures, OS_MESG_BLOCK);
}