thread3.c 6.7 KB
#include <os.h>
#include <rmon.h>
#include "corefunc.h"

/*
 * thread3
 *
 * Tests for:
 *	osCreateThread (priority argument)
 *	osSetThreadPri (on runnable threads)
 *
 * Assumed working:
 *	osSetIntMask
 *	osGetIntMask
 *	osStartThread
 *	osCreateMesgQueue
 *	osSendMesg
 *	osRecvMesg
 *
 * Description:
 *	Check that osSetPriority does not affect interrupt mask
 *	Check that threads created with a higher priority run first
 *	Check that threads that lower their own priority cause a higher
 *		priority thread to run
 *	Check that raising a running thread's own priority does not cause
 *		a context switch
 *	Check that raising a thread's priority over that of the running
 *		thread allow them to run.
 *	Check that setting a priority equal to that of another thread
 *		of the same priority does not cause a yield
 *	Check that setting the priority of a thread to the same value
 *		has no effect.
 *	
 */

#define NUM_SLAVES	10
#define	NUM_LOG 	46

typedef struct {
    int			id;
    void		(*entry)(void *);
    OSPri		pri;
    u64			stack[STACKSIZE/sizeof(u64)];
    OSThread		thread;
} ThreadTabEntry;

static void slaveA(void *);
static void slaveB(void *);

static int logExecution(int);

static ThreadTabEntry threadTab[NUM_SLAVES] = {
    {  101, slaveA, 21 }, 
    {  102, slaveA, 22 }, 
    {  103, slaveA, 23 }, 
    {  104, slaveA, 24 }, 
    {  105, slaveA, 25 }, 
    {  106, slaveA, 26 }, 
    {  107, slaveA, 27 }, 
    {  108, slaveA, 28 }, 
    {  109, slaveA, 29 }, 
    {  110, slaveA, 30 }, 
};

static OSMesgQueue	slaveMesgQueue;
static OSMesg		slaveMesgBuf[NUM_SLAVES];

static OSThread		slave1Thread;
static char		slave1Stack[STACKSIZE];

static OSThread		slave2Thread;
static char		slave2Stack[STACKSIZE];

static int		logTab[NUM_LOG];
static int		*logPtr = logTab;

static int		expLogTab[NUM_LOG] = {
	100, 110, 109, 108, 107, 106, 105,
	104, 103, 102, 101, 100, 100, 100,
	101, 101, 100, 102, 102, 100, 103, 103, 100,
	104, 104, 100, 105, 105, 100, 106, 106, 100,
	107, 107, 100, 108, 108, 100, 109, 109, 100, 110, 110,  100,
	201, 202 };

int
thread3(void)
{
    OSIntMask savedMask, currentMask;
    ThreadTabEntry *t;
    int i;
    int addFailures, numFailures = 0;
    
    savedMask = osSetIntMask(OS_IM_ALL);

    /*
     * Set thread priority higher than any of the threads
     * the master is about to spawn.
     */
    osSetThreadPri(NULL, 40);

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

    osCreateMesgQueue(&slaveMesgQueue, slaveMesgBuf, NUM_SLAVES);

    for (t = threadTab; t < &threadTab[NUM_SLAVES]; t++) {
    	osCreateThread(&t->thread, t->id, t->entry, t,
		       t->stack+STACKSIZE/sizeof(u64), t->pri);
    }

    for (t = threadTab; t < &threadTab[NUM_SLAVES]; t++) {
    	osStartThread(&t->thread);
    }

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

    /*
     * Lower master's priority and allow slaves to run.
     */
    osSetThreadPri(NULL, 20);

    if (logExecution(100))
	numFailures++;

    /*
     * Raise master's priority and check that it still runs.
     */

    osSetThreadPri(NULL, 30);

    if (logExecution(100))
	numFailures++;

    /*
     * Lower priority so it is lower than any of the slave priorities
     * in the thread table.
     */

    osSetThreadPri(NULL, 20);

    if (logExecution(100))
	numFailures++;

    /*
     * Raise slave priorities and check that they run.
     */

    for (t = threadTab; t < &threadTab[NUM_SLAVES]; t++) {
	osSetThreadPri(&t->thread, t->pri);

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

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

    /*
     * Now check that setting the priority of a thread to the same value
     * has no effect.
     */
    osCreateThread(&slave1Thread, 201, slaveB, (void *)201,
		   slave1Stack+STACKSIZE, 10);
    osStartThread(&slave1Thread);

    osCreateThread(&slave2Thread, 202, slaveB, (void *)202,
		   slave2Stack+STACKSIZE, 10);
    osStartThread(&slave2Thread);

    osSetThreadPri(&slave1Thread, 10);

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

    /*
     * Verify everybody ran when they were supposed to.
     */
    if (logPtr != &logTab[NUM_LOG]) {
	osSyncPrintf("thread3: log table underflow\n");
	numFailures++;
    }
    for (i = 0; i < logPtr - logTab; i++) {
	if (expLogTab[i] != logTab[i]) {
	    osSyncPrintf("thread3: 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("thread3: expected interrupt mask 0x%x, actual 0x%x\n",
		OS_IM_ALL, currentMask);
	numFailures++;
    }
    return(numFailures);
}

static void
slaveA(void *arg)
{
    ThreadTabEntry *t = arg;
    OSIntMask currentMask;
    int numFailures = 0;

    /*
     * As a sanity check, check interrupt mask
     */
    currentMask = osGetIntMask();
    if (OS_IM_ALL != currentMask) {
    	osSyncPrintf("thread3: expected interrupt mask 0x%x, actual 0x%x\n",
    		OS_IM_ALL, currentMask);
    	numFailures++;
    }

    if (logExecution(t->id))
	numFailures++;

    /*
     * Lower itself (for check that higher priority threads run)
     */
    osSetThreadPri(NULL, 10);

    /*
     * Check the setting of priority did not affect interrupt mask
     */
    currentMask = osGetIntMask();
    if (OS_IM_ALL != currentMask) {
    	osSyncPrintf("thread3: expected interrupt mask 0x%x, actual 0x%x\n",
    		OS_IM_ALL, currentMask);
    	numFailures++;
    }

    if (logExecution(t->id))
	numFailures++;

    /*
     * Lower priority again to that of master
     */
    osSetThreadPri(NULL, 20);

    if (logExecution(t->id))
	numFailures++;

    /*
     * Check interrupt one more time for paranoia's sake.
     */
    currentMask = osGetIntMask();
    if (OS_IM_ALL != currentMask) {
    	osSyncPrintf("thread3: expected interrupt mask 0x%x, actual 0x%x\n",
    		OS_IM_ALL, currentMask);
    	numFailures++;
    }

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

static void
slaveB(void *arg)
{
    int id;
    int numFailures = 0;

    id = (int)arg;

    if (logExecution(id))
	numFailures++;

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

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