Пример #1
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;
}
Пример #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.
 *
 * 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;

}