예제 #1
0
/**
 * \b test_start
 *
 * Start queue test.
 *
 * This tests basic operation of queues.
 *
 * Messages are posted to and received from the queue and checked
 * against expected values. To ensure correct ordering, queue posts
 * and receives are done in blocks of different amounts, such that
 * there will already be different numbers of messages in the queue
 * whenever messages are posted and received.
 *
 * We test using 4-byte messages.
 *
 * @retval Number of failures
 */
uint32_t test_start (void)
{
    int failures, tx_count, rx_count;
    uint32_t msg;

    /* Default to zero failures */
    failures = 0;

    /* Create test queue */
    if (atomQueueCreate (&queue1, (uint8_t *)&queue1_storage[0], sizeof(queue1_storage[0]), QUEUE_ENTRIES) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating test queue\n"));
        failures++;
    }

    else
    {
        /* Reset tx/rx counts */
        tx_count = rx_count = 0;

        /* Post 2 messages to the queue */
        for (; tx_count < 2; tx_count++)
        {
            msg = test_values[tx_count];
            if (atomQueuePut (&queue1, 0, (uint8_t *)&msg) != ATOM_OK)
            {
                ATOMLOG (_STR("Failed post\n"));
                failures++;
            }
        }

        /* Receive 1 message from the queue */
        for (; rx_count < 2; rx_count++)
        {
            if (atomQueueGet (&queue1, 0, (uint8_t *)&msg) != ATOM_OK)
            {
                ATOMLOG (_STR("Failed get\n"));
                failures++;
            }
            else if (msg != test_values[rx_count])
            {
                ATOMLOG (_STR("Val%d\n"), rx_count);
                failures++;
            }
        }

        /* Post 3 messages to the queue */
        for (; tx_count < 5; tx_count++)
        {
            msg = test_values[tx_count];
            if (atomQueuePut (&queue1, 0, (uint8_t *)&msg) != ATOM_OK)
            {
                ATOMLOG (_STR("Failed post\n"));
                failures++;
            }
        }

        /* Receive 2 messages from the queue */
        for (; rx_count < 3; rx_count++)
        {
            if (atomQueueGet (&queue1, 0, (uint8_t *)&msg) != ATOM_OK)
            {
                ATOMLOG (_STR("Failed get\n"));
                failures++;
            }
            else if (msg != test_values[rx_count])
            {
                ATOMLOG (_STR("Val%d\n"), rx_count);
                failures++;
            }
        }

        /* Post 5 messages to the queue */
        for (; tx_count < 10; tx_count++)
        {
            msg = test_values[tx_count];
            if (atomQueuePut (&queue1, 0, (uint8_t *)&msg) != ATOM_OK)
            {
                ATOMLOG (_STR("Failed post\n"));
                failures++;
            }
        }

        /* Receive 3 messages from the queue */
        for (; rx_count < 6; rx_count++)
        {
            if (atomQueueGet (&queue1, 0, (uint8_t *)&msg) != ATOM_OK)
            {
                ATOMLOG (_STR("Failed get\n"));
                failures++;
            }
            else if (msg != test_values[rx_count])
            {
                ATOMLOG (_STR("Val%d\n"), rx_count);
                failures++;
            }
        }

        /* Post 2 messages to the queue */
        for (; tx_count < 12; tx_count++)
        {
            msg = test_values[tx_count];
            if (atomQueuePut (&queue1, 0, (uint8_t *)&msg) != ATOM_OK)
            {
                ATOMLOG (_STR("Failed post\n"));
                failures++;
            }
        }

        /* Receive 6 messages from the queue */
        for (; rx_count < 12; rx_count++)
        {
            if (atomQueueGet (&queue1, 0, (uint8_t *)&msg) != ATOM_OK)
            {
                ATOMLOG (_STR("Failed get\n"));
                failures++;
            }
            else if (msg != test_values[rx_count])
            {
                ATOMLOG (_STR("Val%d\n"), rx_count);
                failures++;
            }
        }
    }

    /* Quit */
    return failures;
}
예제 #2
0
/**
 * \b test_start
 *
 * Start queue test.
 *
 * This test exercises queue deletion, waking threads blocking on a queue
 * in atomQueuePut() if the queue is deleted.
 *
 * Deletion wakeups are tested twice: once for a thread which is blocking
 * in atomQueuePut() with a timeout and once for a thread which is
 * blocking in atomQueuePut() with no timeout.
 *
 * Deletion of threads blocking in atomQueueGet() are tested in queue2.c.
 *
 * @retval Number of failures
 */
uint32_t test_start (void)
{
    int failures, i;
    uint8_t msg;

    /* Default to zero failures */
    failures = 0;

    /* Set a test value for posting to the queue */
    msg = 0x66;

    /* Test wakeup of threads on queue deletion (thread blocking with no timeout) */
    g_result = 0;
    if (atomQueueCreate (&queue1, &queue1_storage[0], sizeof(uint8_t), QUEUE_ENTRIES) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating test queue\n"));
        failures++;
    }

    /* Successful queue creation */
    else
    {
        /* Fill up all entries */
        for (i = 0; i < QUEUE_ENTRIES; i++)
        {
            if (atomQueuePut (&queue1, 0, &msg) != ATOM_OK)
            {
                ATOMLOG (_STR("Error filling queue\n"));
                failures++;
            }
        }

        /* Create a test thread that will block because the queue is full */
        if (atomThreadCreate(&tcb[0], TEST_THREAD_PRIO, test1_thread_func, 0,
                  &test_thread_stack[0][TEST_THREAD_STACK_SIZE - 1],
                  TEST_THREAD_STACK_SIZE) != ATOM_OK)
        {
            /* Fail */
            ATOMLOG (_STR("Error creating test thread 1\n"));
            failures++;
        }
        else
        {

            /*
             * We have created and filled a queue. We want to see that the other
             * thread is woken up if its queue is deleted. This is indicated
             * through g_result being set.
             */

            /* Wait for the other thread to start blocking on queue1 */
            if (atomTimerDelay(SYSTEM_TICKS_PER_SEC) != ATOM_OK)
            {
                ATOMLOG (_STR("Failed timer delay\n"));
                failures++;
            }
            else
            {
                /* The other thread will be blocking on queue1 now, delete queue1 */
                if (atomQueueDelete(&queue1) != ATOM_OK)
                {
                    ATOMLOG (_STR("Failed queue1 delete\n"));
                    failures++;
                }
                else
                {
                    /* Queue1 deleted. The thread should now wake up and set g_result. */
                    atomTimerDelay (SYSTEM_TICKS_PER_SEC);
                    if (g_result == 0)
                    {
                        ATOMLOG (_STR("Notify fail\n"));
                        failures++;
                    }
                    else
                    {
                        /* Success */
                    }
                }
            }
        }
    }

    /* Test wakeup of threads on semaphore deletion (thread blocking with timeout) */
    g_result = 0;
    if (atomQueueCreate (&queue1, &queue1_storage[0], sizeof(uint8_t), QUEUE_ENTRIES) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating test queue\n"));
        failures++;
    }

    /* Successful queue creation */
    else
    {
        /* Fill up all entries */
        for (i = 0; i < QUEUE_ENTRIES; i++)
        {
            if (atomQueuePut (&queue1, 0, &msg) != ATOM_OK)
            {
                ATOMLOG (_STR("Error filling queue\n"));
                failures++;
            }
        }

        /* Create a test thread that will block because the queue is full */
        if (atomThreadCreate(&tcb[1], TEST_THREAD_PRIO, test2_thread_func, 0,
                  &test_thread_stack[1][TEST_THREAD_STACK_SIZE - 1],
                  TEST_THREAD_STACK_SIZE) != ATOM_OK)
        {
            /* Fail */
            ATOMLOG (_STR("Error creating test thread 2\n"));
            failures++;
        }
        else
        {

            /*
             * We have created and filled a queue. We want to see that the other
             * thread is woken up if its queue is deleted. This is indicated
             * through g_result being set.
             */

            /* Wait for the other thread to start blocking on queue1 */
            if (atomTimerDelay(SYSTEM_TICKS_PER_SEC) != ATOM_OK)
            {
                ATOMLOG (_STR("Failed timer delay\n"));
                failures++;
            }
            else
            {
                /* The other thread will be blocking on queue1 now, delete queue1 */
                if (atomQueueDelete(&queue1) != ATOM_OK)
                {
                    ATOMLOG (_STR("Failed queue1 delete\n"));
                    failures++;
                }
                else
                {
                    /* Queue1 deleted. The thread should now wake up and set g_result. */
                    atomTimerDelay (SYSTEM_TICKS_PER_SEC);
                    if (g_result == 0)
                    {
                        ATOMLOG (_STR("Notify fail\n"));
                        failures++;
                    }
                    else
                    {
                        /* Success */
                    }
                }
            }
        }
    }

    /* Check thread stack usage (if enabled) */
#ifdef ATOM_STACK_CHECKING
    {
        uint32_t used_bytes, free_bytes;
        int thread;

        /* Check all threads */
        for (thread = 0; thread < NUM_TEST_THREADS; thread++)
        {
            /* Check thread stack usage */
            if (atomThreadStackCheck (&tcb[thread], &used_bytes, &free_bytes) != ATOM_OK)
            {
                ATOMLOG (_STR("StackCheck\n"));
                failures++;
            }
            else
            {
                /* Check the thread did not use up to the end of stack */
                if (free_bytes == 0)
                {
                    ATOMLOG (_STR("StackOverflow %d\n"), thread);
                    failures++;
                }

                /* Log the stack usage */
#ifdef TESTS_LOG_STACK_USAGE
                ATOMLOG (_STR("StackUse:%d\n"), (int)used_bytes);
#endif
            }
        }
    }
#endif

    /* Quit */
    return failures;
}
예제 #3
0
/**
 * \b test_start
 *
 * Start queue test.
 *
 * This tests basic operation of queues.
 *
 * The main test thread creates a second thread and posts
 * a series of messages to the second thread. The message
 * values are checked against the expected values.
 *
 * We test using 4-byte messages.
 *
 * @retval Number of failures
 */
uint32_t test_start (void)
{
    int failures, count;
    int num_entries;
    uint32_t msg;

    /* Default to zero failures */
    failures = 0;
    g_result = 0;

    /* Create test queue */
    if (atomQueueCreate (&queue1, (uint8_t *)&queue1_storage[0], sizeof(queue1_storage[0]), QUEUE_ENTRIES) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating test queue\n"));
        failures++;
    }

    /* Create a test thread that will block because the queue is empty */
    else if (atomThreadCreate(&tcb[0], TEST_THREAD_PRIO + 1, test1_thread_func, 0,
              &test_thread_stack[0][0],
              TEST_THREAD_STACK_SIZE, TRUE) != ATOM_OK)
    {
        /* Fail */
        ATOMLOG (_STR("Error creating test thread 1\n"));
        failures++;
    }
    else
    {

        /*
         * We have created an empty queue and a thread which should now
         * be blocking on the queue. The test thread is lower priority
         * than us.
         */

        /* Wait for the other thread to start blocking on queue1 */
        if (atomTimerDelay(SYSTEM_TICKS_PER_SEC) != ATOM_OK)
        {
            ATOMLOG (_STR("Failed timer delay\n"));
            failures++;
        }
        else
        {
            /*
             * Post all entries in the test array to the queue.
             * Because the second thread is lower priority than
             * us, we will post 8 messages until the queue is
             * full without waking up the second thread at all.
             * At that point, we will block and the second
             * thread will remove one message from the queue.
             * With a spare entry in the queue, this thread
             * will wake up again and post another message.
             * This will continue until this thread has posted
             * all messages, at which point the second thread
             * will drain all remaining messages from the
             * queue.
             *
             * Through this scheme we are able to test posting
             * to the queue at all possible fill levels.
             */
            num_entries = sizeof(test_values) / sizeof(test_values[0]);
            for (count = 0; count < num_entries; count++)
            {
                /* Increment through and post all test values to the queue */
                msg = test_values[count];
                if (atomQueuePut (&queue1, 0, (uint8_t *)&msg) != ATOM_OK)
                {
                    ATOMLOG (_STR("Failed post\n"));
                    failures++;
                }
            }

            /* Sleep a while for the second thread to finish */
            atomTimerDelay (SYSTEM_TICKS_PER_SEC);

            /* Check that the second thread has found all test values */
            if (g_result != 1)
            {
                ATOMLOG (_STR("Bad test vals\n"));
                failures++;
            }
        }
    }

    /* Check thread stack usage (if enabled) */
#ifdef ATOM_STACK_CHECKING
    {
        uint32_t used_bytes, free_bytes;
        int thread;

        /* Check all threads */
        for (thread = 0; thread < NUM_TEST_THREADS; thread++)
        {
            /* Check thread stack usage */
            if (atomThreadStackCheck (&tcb[thread], &used_bytes, &free_bytes) != ATOM_OK)
            {
                ATOMLOG (_STR("StackCheck\n"));
                failures++;
            }
            else
            {
                /* Check the thread did not use up to the end of stack */
                if (free_bytes == 0)
                {
                    ATOMLOG (_STR("StackOverflow %d\n"), thread);
                    failures++;
                }

                /* Log the stack usage */
#ifdef TESTS_LOG_STACK_USAGE
                ATOMLOG (_STR("StackUse:%d\n"), (int)used_bytes);
#endif
            }
        }
    }
#endif

    /* Quit */
    return failures;
}
예제 #4
0
/**
 * \b test_start
 *
 * Start queue test.
 *
 * This test verifies the queue deletion API, by deleting a queue
 * on which multiple threads are blocking, and checking that all three
 * are woken up with an appropriate error code.
 *
 * @retval Number of failures
 */
uint32_t test_start (void)
{
    int failures;
    int i;

    /* Default to zero failures */
    failures = 0;

    /* Initialise pass status for all three threads to FALSE */
    for (i = 0; i < 3; i++) {
        pass_flag[i] = FALSE;
    }

    /* Test wakeup of three threads on queue deletion */
    if (atomQueueCreate (&queue1, &queue1_storage[0], sizeof(queue1_storage[0]), QUEUE_ENTRIES) != ATOM_OK) {
        ATOMLOG (_STR("Error creating Q\n"));
        failures++;
    }

    else {
        /* The queue is empty so all three test threads will block */

        /* Create test thread 1 */
        if (atomThreadCreate(&tcb[0], TEST_THREAD_PRIO, test_thread_func, 0,
                             &test_thread_stack[0][TEST_THREAD_STACK_SIZE - 1],
                             TEST_THREAD_STACK_SIZE) != ATOM_OK) {
            /* Fail */
            ATOMLOG (_STR("Error creating test thread 1\n"));
            failures++;
        }

        /* Create test thread 2 */
        else if (atomThreadCreate(&tcb[1], TEST_THREAD_PRIO, test_thread_func, 1,
                                  &test_thread_stack[1][TEST_THREAD_STACK_SIZE - 1],
                                  TEST_THREAD_STACK_SIZE) != ATOM_OK) {
            /* Fail */
            ATOMLOG (_STR("Error creating test thread 2\n"));
            failures++;
        }

        /* Create test thread 3 */
        else if (atomThreadCreate(&tcb[2], TEST_THREAD_PRIO, test_thread_func, 2,
                                  &test_thread_stack[2][TEST_THREAD_STACK_SIZE - 1],
                                  TEST_THREAD_STACK_SIZE) != ATOM_OK) {
            /* Fail */
            ATOMLOG (_STR("Error creating test thread 3\n"));
            failures++;
        }

        /* Test threads now created */
        else {
            /* Wait a while for threads to start blocking on queue1 */
            atomTimerDelay (SYSTEM_TICKS_PER_SEC/4);

            /* Delete queue1 now that all three threads should be blocking */
            if (atomQueueDelete (&queue1) != ATOM_OK) {
                ATOMLOG (_STR("Delete fail\n"));
                failures++;
            } else {
                /* Wait a while for all three threads to wake up */
                atomTimerDelay (SYSTEM_TICKS_PER_SEC/4);

                /* Check that all three threads have passed */
                if ((pass_flag[0] != TRUE) || (pass_flag[1] != TRUE) || (pass_flag[2] != TRUE)) {
                    ATOMLOG (_STR("Thread fail\n"));
                    failures++;
                }
            }
        }
    }

    /* Check thread stack usage (if enabled) */
#ifdef ATOM_STACK_CHECKING
    {
        uint32_t used_bytes, free_bytes;
        int thread;

        /* Check all threads */
        for (thread = 0; thread < NUM_TEST_THREADS; thread++) {
            /* Check thread stack usage */
            if (atomThreadStackCheck (&tcb[thread], &used_bytes, &free_bytes) != ATOM_OK) {
                ATOMLOG (_STR("StackCheck\n"));
                failures++;
            } else {
                /* Check the thread did not use up to the end of stack */
                if (free_bytes == 0) {
                    ATOMLOG (_STR("StackOverflow %d\n"), thread);
                    failures++;
                }

                /* Log the stack usage */
#ifdef TESTS_LOG_STACK_USAGE
                ATOMLOG (_STR("StackUse:%d\n"), (int)used_bytes);
#endif
            }
        }
    }
#endif

    /* Quit */
    return failures;
}
예제 #5
0
/**
 * \b test_start
 *
 * Start queue test.
 *
 * With multiple threads blocking on a single queue, this test confirms that
 * they are woken in order when the queue is posted. The correct order for
 * waking is that the higher priority threads are woken first, followed by the
 * lower priority threads. Where multiple threads of the same priority are
 * waiting, the threads are woken in FIFO order (the order in which they started
 * waiting on the queue).
 *
 * To test this we create four threads which all wait on a single queue.
 * One pair of threads are running at high priority, with the other pair at a
 * lower priority:
 *
 * Thread 1: low prio thread A
 * Thread 2: low prio thread B
 * Thread 3: high prio thread A
 * Thread 4: high prio thread B
 *
 * The threads are forced to start blocking on the same queue in the
 * above order.
 *
 * We expect to see them woken up in the following order:
 *  3, 4, 1, 2
 *
 * This proves the multiple blocking thread ordering in terms of both
 * the priority-queueing and same-priority-FIFO-queueing.
 *
 * @retval Number of failures
 */
uint32_t test_start (void)
{
    int failures, count;
    uint8_t msg;

    /* Default to zero failures */
    failures = 0;

    /* Create empty queue */
    if (atomQueueCreate (&queue1, &queue1_storage[0], sizeof(uint8_t), QUEUE_ENTRIES) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating test q1\n"));
        failures++;
    }

    /* Start the threads */
    else
    {
        /*
         * The test threads all start by calling atomQueueGet() to receive
         * a message from the queue. Because the queue is empty, all test
         * threads should immediately block on the queue (until a message
         * is posted to it).
         */

        /* Create Thread 1 (lower priority thread A) */
        if (atomThreadCreate(&tcb[0], TEST_THREAD_PRIO+1, test_thread_func, 1,
              &test_thread_stack[0][0],
              TEST_THREAD_STACK_SIZE, TRUE) != ATOM_OK)
        {
            /* Fail */
            ATOMLOG (_STR("Error creating test thread\n"));
            failures++;
        }

        /* Delay to ensure the thread will start blocking on the queue */
        atomTimerDelay (SYSTEM_TICKS_PER_SEC/4);

        /* Create Thread 2 (lower priority thread B) */
        if (atomThreadCreate(&tcb[1], TEST_THREAD_PRIO+1, test_thread_func, 2,
              &test_thread_stack[1][0],
              TEST_THREAD_STACK_SIZE, TRUE) != ATOM_OK)
        {
            /* Fail */
            ATOMLOG (_STR("Error creating test thread\n"));
            failures++;
        }

        /* Delay to ensure the thread will start blocking on the queue */
        atomTimerDelay (SYSTEM_TICKS_PER_SEC/4);

        /* Create Thread 3 (higher priority thread A) */
        if (atomThreadCreate(&tcb[2], TEST_THREAD_PRIO, test_thread_func, 3,
              &test_thread_stack[2][0],
              TEST_THREAD_STACK_SIZE, TRUE) != ATOM_OK)
        {
            /* Fail */
            ATOMLOG (_STR("Error creating test thread\n"));
            failures++;
        }

        /* Delay to ensure the thread will start blocking on the queue */
        atomTimerDelay (SYSTEM_TICKS_PER_SEC/4);

        /* Create Thread 4 (higher priority thread B) */
        if (atomThreadCreate(&tcb[3], TEST_THREAD_PRIO, test_thread_func, 4,
              &test_thread_stack[3][0],
              TEST_THREAD_STACK_SIZE, TRUE) != ATOM_OK)
        {
            /* Fail */
            ATOMLOG (_STR("Error creating test thread\n"));
            failures++;
        }

        /* Delay to ensure the thread will start blocking on the queue */
        atomTimerDelay (SYSTEM_TICKS_PER_SEC/4);

        /* All four threads will now be blocking on queue1 */

        /*
         * Initialise wake count, used by threads to determine
         * what order they were woken in.
         */
        wake_cnt = 0;

        /* Loop waking all four threads */
        for (count = 0; count < 4; count++)
        {
            /*
             * Post a message to the queue. This will wake up one of the threads
             * blocking on it (because it is currently empty). That thread will
             * wake up, note the order at which it was woken, then go to sleep
             * forever leaving the queue empty again. This is done four times so
             * that all four threads are woken, noting their wake order.
             */
            msg = 0x66;
            if (atomQueuePut (&queue1, 0, &msg) != ATOM_OK)
            {
                ATOMLOG (_STR("Post fail\n"));
                failures++;
            }

            /*
             * Sleep to give the thread time to wake up and modify the shared
             * global data wake_cnt and wake_order[]. We deliberately do not
             * use a mutex for protecting access to this shared data, as we
             * are testing the queue module in isolation here.
             */
            atomTimerDelay (SYSTEM_TICKS_PER_SEC / 4);

        }

        /* All four threads now woken up, check they woke in correct order */
        if ((wake_order[0] != 3) && (wake_order[1] != 4)
            && (wake_order[2] != 1) && (wake_order[3] != 2))
        {
            ATOMLOG (_STR("Bad order %d,%d,%d,%d\n"),
                wake_order[0], wake_order[1], wake_order[2], wake_order[3]);
            failures++;
        }

        /* Delete queue, test finished */
        if (atomQueueDelete (&queue1) != ATOM_OK)
        {
            ATOMLOG (_STR("Delete failed\n"));
            failures++;
        }
    }

    /* Check thread stack usage (if enabled) */
#ifdef ATOM_STACK_CHECKING
    {
        uint32_t used_bytes, free_bytes;
        int thread;

        /* Check all threads */
        for (thread = 0; thread < NUM_TEST_THREADS; thread++)
        {
            /* Check thread stack usage */
            if (atomThreadStackCheck (&tcb[thread], &used_bytes, &free_bytes) != ATOM_OK)
            {
                ATOMLOG (_STR("StackCheck\n"));
                failures++;
            }
            else
            {
                /* Check the thread did not use up to the end of stack */
                if (free_bytes == 0)
                {
                    ATOMLOG (_STR("StackOverflow %d\n"), thread);
                    failures++;
                }

                /* Log the stack usage */
#ifdef TESTS_LOG_STACK_USAGE
                ATOMLOG (_STR("StackUse:%d\n"), (int)used_bytes);
#endif
            }
        }
    }
#endif

    /* Quit */
    return failures;

}