Ejemplo n.º 1
0
/**
 * \b test_start
 *
 * Start semaphore test.
 *
 * This tests basic counting semaphore operation between two threads.
 *
 * A semaphore is created with a count of 10. A second thread then
 * ensures that it can decrement the semaphore 10 times before
 * it can no longer be decremented.
 *
 * @retval Number of failures
 */
uint32_t test_start (void)
{
    int failures;

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

    /* Create sem with count ten for second thread to decrement */
    if (atomSemCreate (&sem1, INITIAL_SEM_COUNT) != ATOM_OK) {
        ATOMLOG (_STR("Error creating test semaphore 1\n"));
        failures++;
    }
    /* Create sem to receive test-passed notification */
    else if (atomSemCreate (&sem2, 0) != ATOM_OK) {
        ATOMLOG (_STR("Error creating test semaphore 1\n"));
        failures++;
    } else {
        /* Check that sem2 doesn't already have a positive count */
        if (atomSemGet (&sem2, -1) != ATOM_WOULDBLOCK) {
            ATOMLOG (_STR("Sem2 already put\n"));
            failures++;
        }

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

        /*
         * The second thread has now been created and will attempt to
         * decrement sem1 ten times, then finally check that it cannot
         * decrement it any further. If this passes then the second
         * thread will post sem2 to notify us that the test has passed.
         */
        else {
            /* Give the second thread one second to post sem2 */
            if (atomSemGet (&sem2, SYSTEM_TICKS_PER_SEC) != ATOM_OK) {
                ATOMLOG (_STR("Sem2 not posted\n"));
                failures++;
            }

        }

        /* Delete semaphores, test finished */
        if (atomSemDelete (&sem1) != ATOM_OK) {
            ATOMLOG (_STR("Delete failed\n"));
            failures++;
        }
        if (atomSemDelete (&sem2) != 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;

}
Ejemplo n.º 2
0
/**
 * \b test_start
 *
 * Start semaphore test.
 *
 * This test exercises the semaphore creation and deletion APIs, including
 * waking threads blocking on a semaphore if the semaphore is deleted.
 * Deletion wakeups are tested twice: once for a thread which is blocking
 * with a timeout and once for a thread which is blocking with no timeout.
 *
 * @retval Number of failures
 */
uint32_t test_start (void)
{
    int failures;
    uint32_t i;
    uint8_t status;

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

    /* Test creation and deletion of semaphores: good values */
    for (i = 0; i < 1000; i++)
    {
        if (atomSemCreate (&sem1, 0) == ATOM_OK)
        {
            if (atomSemDelete (&sem1) == ATOM_OK)
            {
                /* Success */
            }
            else
            {
                /* Fail */
                ATOMLOG (_STR("Error deleting semaphore\n"));
                failures++;
                break;
            }
        }
        else
        {
            /* Fail */
            ATOMLOG (_STR("Error creating semaphore\n"));
            failures++;
            break;
        }
    }

    /* Test creation and deletion of semaphores: creation checks */
    if (atomSemCreate (NULL, 0) != ATOM_OK)
    {
        /* Success */
    }
    else
    {
        /* Fail */
        ATOMLOG (_STR("Bad semaphore creation checks\n"));
        failures++;
    }

    /* Test creation and deletion of semaphores: deletion checks */
    if (atomSemDelete (NULL) != ATOM_OK)
    {
        /* Success */
    }
    else
    {
        /* Fail */
        ATOMLOG (_STR("Bad semaphore deletion checks\n"));
        failures++;
    }

    /* Test wakeup of threads on semaphore deletion (thread blocking with no timeout) */
    if (atomSemCreate (&sem1, 0) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating test semaphore 1\n"));
        failures++;
    }

    else if (atomSemCreate (&sem2, 0) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating test semaphore 2\n"));
        failures++;
    }

    else 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 two semaphores. sem1 is for the other thread
         * to wait on, which we will delete from this thread. We want
         * to see that the other thread is woken up if its semaphore
         * is deleted. This is indicated through sem2 being posted
         * back to us.
         */

        /* Wait for the other thread to start blocking on sem1 */
        if (atomTimerDelay(SYSTEM_TICKS_PER_SEC) != ATOM_OK)
        {
            ATOMLOG (_STR("Failed timer delay\n"));
            failures++;
        }
        else
        {
            /* The other thread will be blocking on sem1 now, delete sem1 */
            if (atomSemDelete(&sem1) != ATOM_OK)
            {
                ATOMLOG (_STR("Failed sem1 delete\n"));
                failures++;
            }
            else
            {
                /* Sem1 deleted. The thread should now wake up and post sem2. */
                if ((status = atomSemGet (&sem2, (5*SYSTEM_TICKS_PER_SEC))) != ATOM_OK)
                {
                    ATOMLOG (_STR("Notify fail (%d)\n"), status);
                    failures++;
                }
                else
                {
                    /* Success */

                    /* Clean up the last remaining semaphore */
                    if (atomSemDelete (&sem2) != ATOM_OK)
                    {
                        ATOMLOG (_STR("Failed sem2 delete\n"));
                        failures++;
                    }
                }
            }
        }
    }

    /* Test wakeup of threads on semaphore deletion (thread blocking with timeout) */
    if (atomSemCreate (&sem1, 0) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating test semaphore 1\n"));
        failures++;
    }
    else if (atomSemCreate (&sem2, 0) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating test semaphore 2\n"));
        failures++;
    }
    else 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 two semaphores. sem1 is for the other thread
         * to wait on, which we will delete from this thread. We want
         * to see that the other thread is woken up if its semaphore
         * is deleted. This is indicated through sem2 being posted
         * back to us.
         */

        /* Wait for the other thread to start blocking on sem1 */
        if (atomTimerDelay(SYSTEM_TICKS_PER_SEC) != ATOM_OK)
        {
            ATOMLOG (_STR("Failed timer delay\n"));
            failures++;
        }
        else
        {
            /* The other thread will be blocking on sem1 now, delete sem1 */
            if (atomSemDelete(&sem1) != ATOM_OK)
            {
                ATOMLOG (_STR("Failed sem1 delete\n"));
                failures++;
            }
            else
            {
                /* Sem1 deleted. The thread should now wake up and post sem2. */
                if ((status = atomSemGet (&sem2, (5*SYSTEM_TICKS_PER_SEC))) != ATOM_OK)
                {
                    ATOMLOG (_STR("Notify fail (%d)\n"), status);
                    failures++;
                }
                else
                {
                    /* Success */

                    /* Clean up the last remaining semaphore */
                    if (atomSemDelete (&sem2) != ATOM_OK)
                    {
                        ATOMLOG (_STR("Failed sem2 delete\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;
}
Ejemplo n.º 3
0
/**
 * \b test_start
 *
 * Start semaphore test.
 *
 * This tests usage of a semaphore for basic mutual exclusion type
 * operation. Note that Atomthreads has a more fully-featured real
 * mutex implementation in the mutex module.
 *
 * The semaphore sem1 is initialised with a count of 1. Whichever
 * thread holds this semaphore can then modify the global variable
 * "shared_data".
 *
 * The main thread first takes the "mutex" sem1, then creates a
 * second thread. The second thread should block on the sem1 mutex
 * until the main thread releases it. The test checks that the
 * global "shared_data" is not modified by the second thread
 * until the main thread releases the mutex.
 *
 * @retval Number of failures
 */
uint32_t test_start (void)
{
    int failures;
    int i;

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

    /* Create sem with count one for mutex purposes */
    if (atomSemCreate (&sem1, 1) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating test semaphore 1\n"));
        failures++;
    }
    else
    {
        /* Initialise the shared_data to zero */
        shared_data = 0;

        /* Take the mutex to ensure only this thread can modify shared_data */
        if (atomSemGet (&sem1, 0) != ATOM_OK)
        {
            ATOMLOG (_STR("Error taking mutex\n"));
            failures++;
        }

        /* Create second thread */
        else if (atomThreadCreate(&tcb[0], TEST_THREAD_PRIO, 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++;
        }

        /*
         * The second thread has now been created and should block on
         * the "mutex" sem1 (which now has count zero) until we release
         * it. We wait a while and check that shared_data has not been
         * modified.
         */
        for (i = 0; i < 4; i++)
        {
            /*
             * Sleep for a while to give the second thread a chance to
             * modify shared_data, thought it shouldn't until we
             * release the mutex.
             */
            atomTimerDelay (SYSTEM_TICKS_PER_SEC/4);

            /* Check shared data. The second thread always sets it to one. */
            if (shared_data != 0)
            {
                ATOMLOG (_STR("Shared data modified\n"));
                failures++;
                break;
            }
        }

        /* Check successful so far */
        if (failures == 0)
        {
            /*
             * Release the mutex, which will allow the second thread to
             * wake and start modifying shared_data.
             */
            if (atomSemPut (&sem1) != ATOM_OK)
            {
                ATOMLOG (_STR("Failed release\n"));
                failures++;
            }

            /*
             * Wait a little while then check that shared_data has
             * been modified.
             */
            atomTimerDelay (SYSTEM_TICKS_PER_SEC/4);
            if (shared_data != 1)
            {
                ATOMLOG (_STR("Expected modify\n"));
                failures++;
            }

            /*
             * Release and take the mutex again a few times to ensure
             * that the mutex continues to protect shared_data.
             */
            for (i = 0; i < 4; i++)
            {
                /*
                 * Take the mutex again, to prevent second thread accessing
                 * shared_data.
                 */
                if (atomSemGet (&sem1, SYSTEM_TICKS_PER_SEC) != ATOM_OK)
                {
                    ATOMLOG (_STR("Retake %d\n"), i);
                    failures++;
                    break;
                }
                else
                {
                    /*
                     * Set shared_data to 0 and wait to ensure that the
                     * second thread doesn't modify it while we have the
                     * mutex again.
                     */
                    shared_data = 0;

                    /* Wait a while to give second thread potential to run */
                    atomTimerDelay(SYSTEM_TICKS_PER_SEC/4);

                    /*
                     * Check that shared_data has not been modified while we
                     * own the mutex.
                     */
                    if (shared_data != 0)
                    {
                        /* Thread is still modifying the data */
                        ATOMLOG (_STR("Still modifying\n"));
                        failures++;
                        break;
                    }

                    /*
                     * Release the mutex, which will allow the second thread to
                     * wake and start modifying shared_data again.
                     */
                    if (atomSemPut (&sem1) != ATOM_OK)
                    {
                        ATOMLOG (_STR("Failed release\n"));
                        failures++;
                    }

                }
            }
        }

        /* Delete semaphore, test finished */
        if (atomSemDelete (&sem1) != 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;

}
Ejemplo n.º 4
0
/**
 * \b test_start
 *
 * Start mutex test.
 *
 * Stress-tests mutex Get and Put operations. Four threads are created which are
 * continually Getting and Putting the same mutex, with no time delays between
 * each Get/Put.
 *
 * @retval Number of g_failures
 */
uint32_t test_start (void)
{
    CRITICAL_STORE;
    int finish_cnt;

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

    /* Create mutex to stress */
    if (atomMutexCreate (&mutex1) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating mutex\n"));
        g_failures++;
    }
    /* Create sem to receive thread-finished notification */
    else if (atomSemCreate (&sem1, 0) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating sem\n"));
        g_failures++;
    }
    else
    {
        /* Take ownership of the mutex to ensure all threads wait for now */
        if (atomMutexGet (&mutex1, 0) != ATOM_OK)
        {
            ATOMLOG (_STR("Error taking mutex\n"));
            g_failures++;
        }

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

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

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

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

        /* Release ownership of the mutex to kick the threads off */
        if (atomMutexPut (&mutex1) != ATOM_OK)
        {
            ATOMLOG (_STR("Error putting mutex\n"));
            g_failures++;
        }

        /*
         * All four threads will now be performing Gets/Puts on mutex1.
         * When they have finished they will post sem1, so we wait
         * until sem1 is posted four times.
         */
        finish_cnt = 0;
        while (1)
        {
            /*
             * Attempt to Get sem1. When we have managed to get
             * the semaphore four times, it must have been posted
             * by all four threads.
             */
            if (atomSemGet (&sem1, 0) == ATOM_OK)
            {
                /* Increment our count of finished threads */
                finish_cnt++;

                /* Check if all four threads have now posted sem1 */
                if (finish_cnt == 4)
                {
                    break;
                }
            }
        }

        /* Delete OS objects, test finished */
        if (atomMutexDelete (&mutex1) != ATOM_OK)
        {
            ATOMLOG (_STR("Delete failed\n"));
            CRITICAL_START ();
            g_failures++;
            CRITICAL_END ();
        }
        if (atomSemDelete (&sem1) != ATOM_OK)
        {
            ATOMLOG (_STR("Delete failed\n"));
            CRITICAL_START ();
            g_failures++;
            CRITICAL_END ();
        }
    }

    /* 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"));
                g_failures++;
            }
            else
            {
                /* Check the thread did not use up to the end of stack */
                if (free_bytes == 0)
                {
                    ATOMLOG (_STR("StackOverflow %d\n"), thread);
                    g_failures++;
                }

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

    /* Quit */
    return g_failures;

}
Ejemplo n.º 5
0
/**
 * \b test_start
 *
 * Start semaphore test.
 *
 * With multiple threads blocking on a single semaphore, this test confirms that
 * they are woken in order when the semaphore 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 semaphore).
 *
 * To test this we create four threads which all wait on a single semaphore.
 * 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 semaphore in the
 * above order (the semaphore is initialised with count 0 to ensure any
 * threads calling atomSemGet() will block).
 *
 * 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;
    int i;

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

    /* Create sem with count zero (so that all threads will block) */
    if (atomSemCreate (&sem1, 0) != ATOM_OK) {
        ATOMLOG (_STR("Error creating test semaphore 1\n"));
        failures++;
    } else {
        /* Create Thread 1 (lower priority thread A) */
        if (atomThreadCreate(&tcb[0], TEST_THREAD_PRIO+1, test_thread_func, 1,
                             &test_thread_stack[0][TEST_THREAD_STACK_SIZE - 1],
                             TEST_THREAD_STACK_SIZE) != ATOM_OK) {
            /* Fail */
            ATOMLOG (_STR("Error creating test thread\n"));
            failures++;
        }

        /* Delay to ensure the thread will start blocking on the semaphore */
        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][TEST_THREAD_STACK_SIZE - 1],
                             TEST_THREAD_STACK_SIZE) != ATOM_OK) {
            /* Fail */
            ATOMLOG (_STR("Error creating test thread\n"));
            failures++;
        }

        /* Delay to ensure the thread will start blocking on the semaphore */
        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][TEST_THREAD_STACK_SIZE - 1],
                             TEST_THREAD_STACK_SIZE) != ATOM_OK) {
            /* Fail */
            ATOMLOG (_STR("Error creating test thread\n"));
            failures++;
        }

        /* Delay to ensure the thread will start blocking on the semaphore */
        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][TEST_THREAD_STACK_SIZE - 1],
                             TEST_THREAD_STACK_SIZE) != ATOM_OK) {
            /* Fail */
            ATOMLOG (_STR("Error creating test thread\n"));
            failures++;
        }

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

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

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

        /*
         * Wake the four threads up in order, leaving some time between
         * each wake up for them to deal with global data in a
         * thread-safe fashion.
         */
        for (i = 0; i < 4; i++) {
            /* Post semaphore to wake one of the threads up */
            if (atomSemPut (&sem1) != ATOM_OK) {
                ATOMLOG (_STR("Post fail\n"));
                failures++;
            }

            /* Sleep to give the thread time to manipulate global data */
            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 semaphore, test finished */
        if (atomSemDelete (&sem1) != 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;

}
Ejemplo n.º 6
0
/**
 * \b test_start
 *
 * Start semaphore test.
 *
 * This test verifies the semaphore deletion API, by deleting a semaphore
 * 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 semaphore deletion */
    if (atomSemCreate (&sem1, 0) != ATOM_OK) {
        ATOMLOG (_STR("Error creating test semaphore 1\n"));
        failures++;
    }

    else {
        /* 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 sem1 */
            atomTimerDelay (SYSTEM_TICKS_PER_SEC/4);

            /* Delete sem1 now that all three threads should be blocking */
            if (atomSemDelete (&sem1) != 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;
}