thread2.c 4.56 KB
#include <os.h>
#include <rmon.h>
#include "corefunc.h"

/*
 * thread2
 *
 * Tests for:
 *	osDestroyThread (on runnable threads)
 *
 * Assumed working:
 *	osCreateThread
 *	osYieldThread
 *	osCreateMesgQueue
 *	osSendMesg
 *	osRecvMesg
 *	osGetIntMask
 *	osSetIntMask
 *
 * Description:
 *	Check that osDestroyThread with NULL argument takes running thread
 *		off run queue.
 *	Check that osDestroyThread with non-NULL argument takes given thread
 *		off run queue.
 *	Check that osDestroyThread does not affect interrupt mask
 */

#define	NUM_LOG		5
#define	NUM_SLAVES	2

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

static int		logExecution(int);

static OSMesgQueue	slaveMesgQueue;
static OSMesg		slaveMesgBuf[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, 0 };

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

    savedMask = osSetIntMask(OS_IM_ALL);

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

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

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

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

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

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

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

    /*
     * The first slave has now run and destroyed itself.
     * The second slave has just yielded to the master.
     */

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

    /*
     * Terminate the second slave.  It should not run again.
     */
    osDestroyThread(&slave2Thread);

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

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

    for (i = 0; i < NUM_SLAVES; 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("thread2: log table underflow\n");
	numFailures++;
    }
    for (i = 0; i < logPtr - logTab; i++) {
	if (expLogTab[i] != logTab[i]) {
	    osSyncPrintf("thread2: 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("thread2: expected interrupt mask 0x%x, actual 0x%x\n",
		OS_IM_ALL, currentMask);
	numFailures++;
    }
    return(numFailures);
}

static void
slave1(void *arg)
{
    OSIntMask currentMask;
    int numFailures = 0;

    /*
     * The first slave will log its execution and then destroy itself.
     */
    if (logExecution(1))	/* 1 */
	numFailures++;

    /*
     * Have to send this now, since we shouldn't live beyond the destroy.
     */
    osSendMesg(&slaveMesgQueue, (OSMesg)numFailures, OS_MESG_BLOCK);

    osDestroyThread((OSThread *)NULL);

    (void)logExecution(1);	/* should not get here */
	numFailures++;
}

static void
slave2(void *arg)
{
    OSIntMask currentMask;
    int numFailures = 0;

    /*
     * The second slave will log its execution, and then yield to the
     * master which will terminate it.
     */

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

    /*
     * Have to send this now, since the master will destroy this slave
     * after it gains control at the yield below.
     */
    osSendMesg(&slaveMesgQueue, (OSMesg)numFailures, OS_MESG_BLOCK);

    osYieldThread();		/* let master run */

    (void)logExecution(2);	/* should not get here */
}

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