Figure 4: Debugging with a concurrent error-finding task. Function myEthernetProcessing stores Ethernet frames in a cicular buffer and function myEthernetError examines them.

extern int mutex_give (Mutex*);
extern int mutex_take (Mutex*, int); 
unsigned long rolloverCount = 0;
unsigned short packetCount = 0;
unsigned char myPacket [NUM_PACKETS] [ETHERNET_FRAME_SIZE]; 
Mutex myErrorMutex;
bool findErrors = true;

// This function runs in the first task processing 
// Ethernet frames 
void 
myEthernetProcessing (unsigned char *newFrame, size_t frameSize)
{
    // Ignore null pointers
    if (NULL == newFrame)
        return;

    // Clear the next frame storage area
    memset (myPacket [packetCount], 0x0, ETHERNET_FRAME_SIZE);

    // Keep a copy of each frame
    memcpy (myPacket [packetCount], newFrame, 
        frameSize > ETHERNET_FRAME_SIZE ? 
            ETHERNET_FRAME_SIZE : frameSize);

    // Increment the counter, rollover as needed
    if (NUM_PACKETS == ++packetCount) {
        packetCount = 0;
        ++rolloverCount;
    }

    // Wake the error-finding task
    mutex_give (&myErrorMutex);

    // Regular myEthernetProcessing()
    ...
}

// The function that runs in a separate task looking for errors
void myEthernetError ()
{
    // Check that we are still supposed to be running
    while (findErrors) {
        const int timeout = 30;

        // Wait for 'timeout' seconds for a new wakeup
        int mutexRet = mutex_take (&myErrorMutex, timeout);

        // Check for a timeout
        if (MUTEX_TIMEOUT != mutexRet) {

            // Do the error finding
            ...
        }
    }
}