thread7.c 9.22 KB
#include <os.h>
#include <rmon.h>
#include "corefunc.h"

/*
 * thread7
 *
 * Tests for:
 *	osSetThreadPri (on blocked threads)
 *
 * Assumed working:
 *	osCreateThread
 *	osStartThread
 *	osSetThreadPri
 *	osYieldThread
 *	osCreateMesgQueue
 *	osSendMesg
 *	osRecvMesg
 *	osGetIntMask
 *	osSetIntMask
 *
 * Description:
 *	Check that osThreadPri applied on threads blocked on message
 *		send/receive have no effect when priorities do not change.
 *	Check that osThreadPri applied on threads blocked on message receive
 *		change queue order when relative priorities change.
 *	Check that osThreadPri applied on threads blocked on message send
 *		change queue order when relative priorities change.
 *	Check that osSetThreadPri does not affect interrupt mask.
 */

#define	NUM_SLAVES	2
#define	MAX_MESSAGES	2

static void		slaveRecv(void *);
static void		slaveSend(void *);

static OSMesgQueue	mesgQueue;
static OSMesg		mesgBuf[MAX_MESSAGES];

static OSMesgQueue	slaveMesgQueue;
static OSMesg		slaveMesgBuf[NUM_SLAVES];

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

int
thread7(void)
{
    OSIntMask savedMask, currentMask;
    OSMesg actualMesg, expectedMesg;
    int i, j, k;
    int addFailures, numFailures = 0;

    savedMask = osSetIntMask(OS_IM_ALL);

    /*
     * Set master priority to the same as the slaves' initial priority.
     */
    osSetThreadPri(NULL, 10);

    /*
     * Create a message queue of fixed size, and push the read/write
     * pointers to various locations in the circular buffer, but
     * leave the message queue empty.
     */
    for (i = 0; i < MAX_MESSAGES+1; i++) {
	osCreateMesgQueue(&mesgQueue, mesgBuf, MAX_MESSAGES);

        for (j = 0; j < i; j++) {
	    (void)osSendMesg(&mesgQueue, (OSMesg)NULL, OS_MESG_BLOCK);
	    (void)osRecvMesg(&mesgQueue, (OSMesg *)NULL, OS_MESG_BLOCK);
	}

	osCreateMesgQueue(&slaveMesgQueue, slaveMesgBuf, NUM_SLAVES);

	/*
	 * Create and start up two threads of the same priority
	 * that will block on a message receive.
	 */
	osCreateThread(&slave1Thread, 101, slaveRecv, (void *)0x11111111,
		       slave1Stack+STACKSIZE, 10);
	osStartThread(&slave1Thread);

	osCreateThread(&slave2Thread, 102, slaveRecv, (void *)0x22222222,
		       slave2Stack+STACKSIZE, 10);

	osStartThread(&slave2Thread);

	osYieldThread();


	/*
	 * Send two messages to unblock the slaves.
	 */
	expectedMesg = (OSMesg)0x11111111;
	(void)osSendMesg(&mesgQueue, expectedMesg, OS_MESG_BLOCK);

	expectedMesg = (OSMesg)0x22222222;
	(void)osSendMesg(&mesgQueue, expectedMesg, OS_MESG_BLOCK);

	/*
	 * Now change the priority of the first thread -
	 * this should have  no effect.
	 */

	osSetThreadPri(&slave1Thread, 10);

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

	osYieldThread();

	/*
	 * Send two more messages.
	 */

	expectedMesg = (OSMesg)0x22222222;
	(void)osSendMesg(&mesgQueue, expectedMesg, OS_MESG_BLOCK);

	expectedMesg = (OSMesg)0x11111111;
	(void)osSendMesg(&mesgQueue, expectedMesg, OS_MESG_BLOCK);

	/*
	 * This time, up the priority of the second slave. This should switch
	 * the relative order of the threads in the queue of blocked threads.
	 */
	osSetThreadPri(&slave2Thread, 20);

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

	/*
	 * Reap results.
	 */
	for (k = 0; k < NUM_SLAVES; k++) {
	    (void)osRecvMesg(&slaveMesgQueue, (OSMesg *)&addFailures,
			OS_MESG_BLOCK);
	    numFailures += addFailures;
	}
    }

    /*
     * Create a message queue of fixed size, and push the read/write
     * pointers to various locations in the circular buffer, but
     * leave the message queue full.
     */
    for (i = 0; i < MAX_MESSAGES+1; i++) {
	osCreateMesgQueue(&mesgQueue, mesgBuf, MAX_MESSAGES);

        for (j = 0; j < i; j++) {
	    (void)osSendMesg(&mesgQueue, (OSMesg)NULL, OS_MESG_BLOCK);
	    (void)osRecvMesg(&mesgQueue, (OSMesg *)NULL, OS_MESG_BLOCK);
	}
	for (j = 0; j < MAX_MESSAGES; j++) {
	    expectedMesg = (OSMesg)((j<<24)|(j<<16)|(j<<8)|j);
	    (void)osSendMesg(&mesgQueue, expectedMesg, OS_MESG_BLOCK);
	}

	osCreateMesgQueue(&slaveMesgQueue, slaveMesgBuf, NUM_SLAVES);

	/*
	 * Create and start up two threads of the same priority
	 * that will block on a message send.
	 */
	osCreateThread(&slave1Thread, 101, slaveSend, (void *)0x11111111,
		       slave1Stack+STACKSIZE, 10);
	osStartThread(&slave1Thread);

	osCreateThread(&slave2Thread, 102, slaveSend, (void *)0x22222222,
		       slave2Stack+STACKSIZE, 10);

	osStartThread(&slave2Thread);

	osYieldThread();

	/*
	 * The following call should have no effect.
	 */
	osSetThreadPri(&slave1Thread, 10);

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

	/*
	 * Empty out (and check) message queue.
	 */
	for (j = 0; j < MAX_MESSAGES; j++) {
	    expectedMesg = (OSMesg)((j<<24)|(j<<16)|(j<<8)|j);
	    (void)osRecvMesg(&mesgQueue, &actualMesg, OS_MESG_NOBLOCK);
	    if (expectedMesg != actualMesg) {
		osSyncPrintf("thread7: expected message 0x%x, actual 0x%x\n",
			expectedMesg, actualMesg);
		numFailures++;
	    }
	}

	/*
	 * Yield to let slaves send messages: first slave1, then slave 2.
	 */
	osYieldThread();

	expectedMesg = (OSMesg)0x11111111;
	(void)osRecvMesg(&mesgQueue, &actualMesg, OS_MESG_NOBLOCK);
	if (expectedMesg != actualMesg) {
	    osSyncPrintf("thread7: expected message 0x%x, actual 0x%x\n",
		   expectedMesg, actualMesg);
	    numFailures++;
	}

	expectedMesg = (OSMesg)0x22222222;
	(void)osRecvMesg(&mesgQueue, &actualMesg, OS_MESG_NOBLOCK);
	if (expectedMesg != actualMesg) {
	    osSyncPrintf("thread7: expected message 0x%x, actual 0x%x\n",
		   expectedMesg, actualMesg);
	    numFailures++;
	}

	/*
	 * Fill up the message queue again.
	 */
	for (j = 0; j < MAX_MESSAGES; j++) {
	    expectedMesg = (OSMesg)((j<<24)|(j<<16)|(j<<8)|j);
	    (void)osSendMesg(&mesgQueue, expectedMesg, OS_MESG_BLOCK);
	}

	osYieldThread();

	/*
	 * This time, up the priority of the second slave. This should switch
	 * the relative order of the threads in the queue of blocked threads.
	 */
	osSetThreadPri(&slave2Thread, 20);

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

	/*
	 * Empty out (and check) message queue.
	 */
	for (j = 0; j < MAX_MESSAGES; j++) {
	    expectedMesg = (OSMesg)((j<<24)|(j<<16)|(j<<8)|j);
	    (void)osRecvMesg(&mesgQueue, &actualMesg, OS_MESG_NOBLOCK);
	    if (expectedMesg != actualMesg) {
		osSyncPrintf("thread7: expected message 0x%x, actual 0x%x\n",
			expectedMesg, actualMesg);
		numFailures++;
	    }
	}

	/*
	 * This time we should get slave2's message, then slave1.
	 */
	osYieldThread();

	expectedMesg = (OSMesg)0x22222222;
	(void)osRecvMesg(&mesgQueue, &actualMesg, OS_MESG_NOBLOCK);
	if (expectedMesg != actualMesg) {
	    osSyncPrintf("thread7: expected message 0x%x, actual 0x%x\n",
		   expectedMesg, actualMesg);
	    numFailures++;
	}

	expectedMesg = (OSMesg)0x11111111;
	(void)osRecvMesg(&mesgQueue, &actualMesg, OS_MESG_NOBLOCK);
	if (expectedMesg != actualMesg) {
	    osSyncPrintf("thread7: expected message 0x%x, actual 0x%x\n",
		   expectedMesg, actualMesg);
	    numFailures++;
	}

	/*
	 * Reap results.
	 */
	for (k = 0; k < NUM_SLAVES; k++) {
	    (void)osRecvMesg(&slaveMesgQueue, (OSMesg *)&addFailures,
			OS_MESG_BLOCK);
	    numFailures += addFailures;
	}
    }

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

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

    expectedMesg = (OSMesg)arg;

    /*
     * Receive a message, which will block.
     */
    (void)osRecvMesg(&mesgQueue, &actualMesg, OS_MESG_BLOCK);
    if (expectedMesg != actualMesg) {
	osSyncPrintf("thread7: expected message 0x%x, actual 0x%x\n",
	       expectedMesg, actualMesg);
	numFailures++;
    }

    osYieldThread();

    /*
     * Receive a second message, which will also block.
     */
    (void)osRecvMesg(&mesgQueue, &actualMesg, OS_MESG_BLOCK);
    if (expectedMesg != actualMesg) {
	osSyncPrintf("thread7: expected message 0x%x, actual 0x%x\n",
	       expectedMesg, actualMesg);
	numFailures++;
    }

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

static void
slaveSend(void *arg)
{
    OSMesg expectedMesg;
    int numFailures = 0;

    expectedMesg = (OSMesg)arg;

    /*
     * Send a message, which will block.
     */
    (void)osSendMesg(&mesgQueue, expectedMesg, OS_MESG_BLOCK);

    osYieldThread();

    /*
     * Send a second message, which will also block.
     */
    (void)osSendMesg(&mesgQueue, expectedMesg, OS_MESG_BLOCK);

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