timer2.c 5.2 KB
#include <os.h>
#include <rmon.h>
#include <R4300.h>
#include "osprof.h"
/*
 * timer2
 *
 * Tests for:
 *	osSetTimer
 *	osStopTimer
 *
 * Assumed working:
 *	osGetIntMask
 *	osCreateMesgQueue
 *	osRecvMessage
 *
 * Description:
 *	Setup interval timer for each slave and check that the messages are
 *		delivered every interval time to the corresponding thread
 *	Stop interval timer
 *	Check that message queue is empty
 */

#define	NUM_LOG		17
#define	NUM_SLAVES	2
#define	NUMBER_TIMER	2
#define	LOOP		6

static void		slave1(void *);
static void		slave2(void *);

static int		logExecution(int);

static OSMesgQueue	slaveMesgQueue;
static OSMesg		slaveMesgBuf[NUM_SLAVES];
static OSTimer		mytimer[NUMBER_TIMER];
static OSMesgQueue	timerMesgQueue;
static OSMesg		timerMesgBuf[NUM_SLAVES];


static OSThread		slave1Thread, slave2Thread;
static char		slave1Stack[STACKSIZE], slave2Stack[STACKSIZE];

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

int
timer2(void)
{
    OSIntMask savedMask, currentMask;
    int i;
    int addFailures, numFailures = 0;
    int retValue;
    OSMesg actualMesg;

    savedMask = osSetIntMask(OS_IM_ALL);

    /*
     * Start two slave threads with the same priority as the master.
     */
    osCreateMesgQueue(&slaveMesgQueue, slaveMesgBuf, NUM_SLAVES);
    osCreateMesgQueue(&timerMesgQueue, timerMesgBuf, NUM_SLAVES);

    osCreateThread(&slave1Thread, 101, slave1, (void *)0,
		   slave1Stack+STACKSIZE, 10);
    osStartThread(&slave1Thread);

    osCreateThread(&slave2Thread, 102, slave2, (void *)0,
		   slave2Stack+STACKSIZE, 10);
    osStartThread(&slave2Thread);

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

    osYieldThread();		/* allow slaves to run */

    /*
     * Both slaves have now run and wait for timer to 
     * expire
     */

    if (logExecution(0))	
	numFailures++;

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

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

    /*
     * Verify that the message queue is now empty.
     */
    retValue = osRecvMesg(&timerMesgQueue, &actualMesg, OS_MESG_NOBLOCK);

    if (retValue != -1) {
        rmonPrintf("timer2: expected return value %d, actual %d\n",
                -1, retValue);
        numFailures++;
    }

    /*
     * Verify everybody ran when they were supposed to.
     */
    if (logPtr != &logTab[NUM_LOG]) {
	rmonPrintf("timer2: logPtr 0x%x &logTab[NUM_LOG] 0x%x\n", logPtr,  &logTab[NUM_LOG]);
	rmonPrintf("timer2: log table underflow\n");
	numFailures++;
    }
    for (i = 0; i < logPtr - logTab; i++) {
	if (expLogTab[i] != logTab[i]) {
	    numFailures++;
	}
    }

    /*
     * Restore original interrupt mask and check it once more.
     */
    return(numFailures);
}

static void
slave1(void *arg)
{
    OSIntMask currentMask;
    int numFailures = 0;
    int i;
    OSMesg actualMesg;
    int retValue;

    /*
     * The first slave will log its execution 
     */
    if (logExecution(1))	/* 1 */
	numFailures++;

    timerMesgBuf[0] = (OSMesg)11111111;
    /* setup interval timer */

    osSetTimer(&mytimer[0], 0, OS_NSEC_TO_CYCLES(500000000), &timerMesgQueue, &timerMesgBuf[0]);

    /* Wait for timer to expire */

    for (i=0; i < LOOP; i ++) {
	    (void)osRecvMesg(&timerMesgQueue, &actualMesg, OS_MESG_BLOCK);
	    if (&timerMesgBuf[0] != actualMesg) {
		rmonPrintf("timer2: expected message 0x%x, actual 0x%x\n",
			&timerMesgBuf[0], actualMesg);
		numFailures++;
	    }
	    if (logExecution(1))	/* 1 */
		numFailures++;
    }
   retValue =  osStopTimer(&mytimer[0]);
   if (retValue) {
	rmonPrintf("timer2: Interval timer should on the timer list\n");
	numFailures++;
   }
    /*
     * Have to send this now, since we shouldn't live beyond the destroy.
     */
    osSendMesg(&slaveMesgQueue, (OSMesg)numFailures, OS_MESG_BLOCK);

    osDestroyThread((OSThread *)NULL);
}


static void
slave2(void *arg)
{
    OSIntMask currentMask;
    int numFailures = 0;
    int i;
    OSMesg actualMesg;
    int retValue;

    /*
     * The second slave will log its execution 
     */
    if (logExecution(2))	/* 1 */
	numFailures++;

    timerMesgBuf[1] = (OSMesg)22222222;

    /* setup interval timer */

    osSetTimer(&mytimer[1], 0, OS_NSEC_TO_CYCLES(550000000), &timerMesgQueue, &timerMesgBuf[1]);

    /* Wait for timer to expire */

    for (i=0; i < LOOP; i ++) {
	    (void)osRecvMesg(&timerMesgQueue, &actualMesg, OS_MESG_BLOCK);
	    if (&timerMesgBuf[1] != actualMesg) {
		rmonPrintf("timer2: expected message 0x%x, actual 0x%x\n",
			&timerMesgBuf[1], actualMesg);
		numFailures++;
	    }
	    if (logExecution(2))	/* 2 */
		numFailures++;
    }
   retValue =  osStopTimer(&mytimer[1]);
   if (retValue) {
	rmonPrintf("timer2: Interval timer should on the timer list\n");
	numFailures++;
   }
    /*
     * Have to send this now, since we shouldn't live beyond the destroy.
     */
    osSendMesg(&slaveMesgQueue, (OSMesg)numFailures, OS_MESG_BLOCK);

   osDestroyThread((OSThread *)NULL);
}

static int
logExecution(int id)
{
    if (logPtr >= &logTab[NUM_LOG]) {
	rmonPrintf("timer2: log table overflow\n");
	return(1);
    }
    *logPtr++ = id;
    return(0);
}