Example #1
0
/**
 * \b test_thread_func
 *
 * Entry point for test thread.
 *
 * @param[in] param Unused (optional thread entry parameter)
 *
 * @return None
 */
static void test_thread_func (uint32_t param)
{
    uint8_t status;

    /* Compiler warnings */
    param = param;

    /*
     * Take mutex2 so that main thread can test mutex APIs on a mutex
     * which it does not own.
     */
    status = atomMutexGet(&mutex2, 0);
    if (status != ATOM_OK)
    {
        ATOMLOG (_STR("Mutex get (%d)\n"), status);
    }
    else
    {
        /* We took ownership of mutex2, set g_owned to notify success */
        g_owned = 1;
    }

    /* Wait forever */
    while (1)
    {
        atomTimerDelay (SYSTEM_TICKS_PER_SEC);
    }
}
Example #2
0
/**
 * \b test_thread_func
 *
 * Entry point for test thread.
 *
 * @param[in] param Unused (optional thread entry parameter)
 *
 * @return None
 */
static void test_thread_func (uint32_t param)
{
    uint8_t status;

    /* Compiler warnings */
    param = param;

    /* Block on the mutex */
    if ((status = atomMutexGet (&mutex1, 0)) != ATOM_OK)
    {
        /* Error getting mutex, notify the status code */
        ATOMLOG (_STR("G%d\n"), status);
    }

    /* Got the mutex */
    else
    {
        /* Set shared_data to signify that we think we have the mutex */
        shared_data = 1;
    }

    /* Loop forever */
    while (1)
    {
        atomTimerDelay (SYSTEM_TICKS_PER_SEC);
    }
}
Example #3
0
void uartProcess_thread_func (uint32_t param)
{
  volatile uint32_t use=0,free=0;
  while (1)
  {
    //wait forever
    if (atomSemGet(&uart3Rxsem, 0) == ATOM_OK)
    {
      #ifdef GPS
        atomMutexGet (&gpsDatamutex,0);
        for (uint8_t i=0;i<rxDataBuff.len;i++)
        {
          GPSData.buff[i] = rxDataBuff.buff[i];
        }
        atomMutexPut (&gpsDatamutex);
        atomSemPut (&gpsDatasem);
      #endif      
      
      #ifdef CLI
        //UART send data to cli
        for (uint8_t i=0;i<rxDataBuff.len;i++)
        {
          cmdData.buff[i] = rxDataBuff.buff[i];
        }
        cmdData.bufflen = rxDataBuff.len;
        atomSemPut (&cmdShellsem);
      #endif
      
      //get the used RAM
      atomThreadStackCheck (&uartProcess_tcb, (uint32_t*)&use, (uint32_t*)&free);
      taskState.taskRAMMax[uartProcess_tcb.threadNum][0]=(uint16_t)use;
      taskState.taskRAMMax[uartProcess_tcb.threadNum][1]=(uint16_t)free;
    }
  }
}
Example #4
0
/**
 * \b testCallback
 *
 * Attempt an atomMutexGet() on mutex1 from interrupt context.
 * Should receive an ATOM_ERR_CONTEXT error. Sets g_result if passes.
 *
 * @param[in] cb_data Not used
 */
static void testCallback (POINTER cb_data)
{
    /* Check the return value from atomMutexGet() */
    if (atomMutexGet(&mutex1, 0) == ATOM_ERR_CONTEXT)
    {
        /* Received the error we expected, set g_result to notify success */
        g_result = 1;
    }
    else
    {
        /* Did not get expected error, don't set g_result signifying fail */
    }

}
//TODO: Think better way to do I/O.
//I/O thread?
int uart_getchar(FILE *stream)
{
  char ret = 0;

  loop_until_bit_is_set(REG_UCSRA, RXC0);
  if (atomMutexGet(&uart_rx_mutex, 0) == ATOM_OK)
    {
      ret = REG_UDR;

      atomMutexPut(&uart_rx_mutex);
    }

  return ret;
}
Example #6
0
/**
 * \b test_thread_func
 *
 * Entry point for test thread. The same thread entry point is used for all
 * four test threads.
 *
 * @param[in] param Unused (optional thread entry parameter)
 *
 * @return None
 */
static void test_thread_func (uint32_t param)
{
    uint32_t loop_cnt;
    uint8_t status;
    CRITICAL_STORE;

    /* Compiler warnings */
    param = param;

    /* Run a Get/Put pair many times */
    loop_cnt = NUM_TEST_LOOPS;
    while (loop_cnt--)
    {
        if ((status = atomMutexGet (&mutex1, 0)) != ATOM_OK)
        {
            /* Error getting mutex, notify the status code */
            ATOMLOG (_STR("G%d\n"), status);
            CRITICAL_START ();
            g_failures++;
            CRITICAL_END ();
            break;
        }
        else if ((status = atomMutexPut (&mutex1)) != ATOM_OK)
        {
            /* Error putting mutex, notify the status code */
            ATOMLOG (_STR("P%d\n"), status);
            CRITICAL_START ();
            g_failures++;
            CRITICAL_END ();
            break;
        }
    }

    /* Post sem1 to notify the main thread we're finished */
    if (atomSemPut (&sem1) != ATOM_OK)
    {
        ATOMLOG (_STR("Sem1 putfail\n"));
        CRITICAL_START ();
        g_failures++;
        CRITICAL_END ();
    }

    /* Loop forever */
    while (1)
    {
        atomTimerDelay (SYSTEM_TICKS_PER_SEC);
    }
}
Example #7
0
/**
 * \b uart_read
 *
 * Simple polled UART read.
 *
 * @param[in] ptr Pointer to receive buffer
 * @param[in] len Max bytes to read
 *
 * @retval Number of bytes read
 *
 */
int uart_read (char *ptr, int len)
{
    int todo = 0;

    /* Check we are initialised */
    if (initialised == FALSE)
    {
        uart_init();
    }

    /* Check parameters */
    if ((ptr == NULL) || (len == 0))
    {
        return 0;
    }

    /* Block thread on private access to the UART */
    if (atomMutexGet(&uart_mutex, 0) == ATOM_OK)
    {
        /* Wait for not-empty */
        while(UART_FR(UART0_ADDR) & UART_FR_RXFE)
            ;

        /* Read first byte */
        *ptr++ = UART_DR(UART0_ADDR);

        /* Loop over remaining bytes until empty */
        for (todo = 1; todo < len; todo++)
        {
            /* Quit if receive FIFO empty */
            if(UART_FR(UART0_ADDR) & UART_FR_RXFE)
            {
                break;
            }

            /* Read next byte */
            *ptr++ = UART_DR(UART0_ADDR);
        }

        /* Return mutex access */
        atomMutexPut(&uart_mutex);
    }

    /* Return number of bytes read */
    return todo;
}
/*
 * Send character c down the UART Tx, wait until tx holding register
 * is empty.
 */
int uart_putchar(char c, FILE *stream)
{

  /* Block on private access to the UART */
  if (atomMutexGet(&uart_tx_mutex, 0) == ATOM_OK)
    {
      /* Convert \n to \r\n */
      if (c == '\n')
        uart_putchar('\r', stream);

      /* Wait until the UART is ready then send the character out */
      loop_until_bit_is_set(REG_UCSRA, BIT_UDRE);
      REG_UDR = c;

      /* Return mutex access */
      atomMutexPut(&uart_tx_mutex);
    }

  return 0;
}
Example #9
0
/**
 * \b test_thread_func
 *
 * Entry point for test thread.
 *
 * @param[in] param Unused (optional thread entry parameter)
 *
 * @return None
 */
static void test_thread_func (uint32_t param)
{
    uint8_t status;

    /* Compiler warnings */
    param = param;

    /* Repeatedly attempt to get the mutex and set shared_data to 1 */
    while (1)
    {
        /* Block on the mutex */
        if ((status = atomMutexGet (&mutex1, 0)) != ATOM_OK)
        {
            /* Error getting mutex, notify the status code */
            ATOMLOG (_STR("G%d\n"), status);
            break;
        }

        /* Got the mutex */
        else
        {
            /* Set shared_data to signify that we think we have the mutex */
            shared_data = 1;

            /* Release the mutex allowing the main thread to take it again */
            if ((status = atomMutexPut (&mutex1)) != ATOM_OK)
            {
                /* Error putting mutex, notify the status code */
                ATOMLOG (_STR("P%d\n"), status);
                break;
            }
        }

    }

    /* Loop forever - we only reach here on error */
    while (1)
    {
        atomTimerDelay (SYSTEM_TICKS_PER_SEC);
    }
}
Example #10
0
/**
 * \b test_thread_func
 *
 * Entry point for test thread. The same thread entry point is used for all
 * four test threads, with the thread number/ID (1-4) passed as the entry
 * point parameter.
 *
 * @param[in] param Thread number (1,2,3,4)
 *
 * @return None
 */
static void test_thread_func (uint32_t param)
{
    uint8_t thread_id;

    /* Thread ID is passed through the function parameter */
    thread_id = (uint8_t)param;

    /*
     * Wait for mutex1 to be posted. At creation of all test threads the mutex
     * is owned by the parent thread, so all four threads will block here.
     */
    if (atomMutexGet (&mutex1, 0) != ATOM_OK)
    {
        ATOMLOG (_STR("Get fail\n"));
    }
    else
    {
        /*
         * Store our thread ID in the array using the current
         * wake_cnt order. The threads are holding ownership
         * of a mutex here, which provides protection for this
         * global data.
         */
        wake_order[wake_cnt++] = thread_id;

        /* Release the mutex so that the next thread wakes up */
        if (atomMutexPut (&mutex1) != ATOM_OK)
        {
            ATOMLOG (_STR("Put fail\n"));
        }

    }

    /* Loop forever */
    while (1)
    {
        atomTimerDelay (SYSTEM_TICKS_PER_SEC);
    }
}
Example #11
0
/**
 * \b uart_write
 *
 * Simple polled UART write.
 *
 * @param[in] ptr Pointer to write buffer
 * @param[in] len Number of bytes to write
 *
 * @retval Number of bytes written
 */
int uart_write (const char *ptr, int len)
{
    int todo;

    /* Check we are initialised */
    if (initialised == FALSE)
    {
        uart_init();
    }

    /* Check parameters */
    if ((ptr == NULL) || (len == 0))
    {
        return 0;
    }

    /* Block thread on private access to the UART */
    if (atomMutexGet(&uart_mutex, 0) == ATOM_OK)
    {
        /* Loop through all bytes to write */
        for (todo = 0; todo < len; todo++)
        {
            /* Wait for empty */
            while(UART_FR(UART0_ADDR) & UART_FR_TXFF)
                ;

            /* Write byte to UART */
            UART_DR(UART0_ADDR) = *ptr++;
        }

        /* Return mutex access */
        atomMutexPut(&uart_mutex);
    }

    /* Return bytes-written count */
    return len;
}
void clock_update_func (uint32_t data)
{
	while(1) {
		// Increment time (global variables protected by mutex lock)
		if (atomMutexGet(&clock_mutex, 0) == ATOM_OK) {

			g_sec++;
			if (g_sec > 59) {
				g_sec = 0;
				g_min++;
				if (g_min > 59) {
					g_min = 0;
					g_hour++;
					if (g_hour > 23)
						g_hour = 0;
				}
			}
			
		}
		atomMutexPut(&clock_mutex);
		atomTimerDelay(100);

	}
}
Example #13
0
/**
 * \b test_start
 *
 * Start mutex test.
 *
 * This test exercises the atomMutexGet() and atomMutexPut() APIs including
 * forcing the various error indications which can be returned from the
 * APIs to ensure that handling for these corner cases have been correctly
 * implemented.
 *
 * @retval Number of failures
 */
uint32_t test_start (void)
{
    int failures;
    uint8_t status;
    ATOM_TIMER timer_cb;
    int count;

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

    /* Test parameter checks */
    if (atomMutexGet (NULL, 0) != ATOM_ERR_PARAM)
    {
        ATOMLOG (_STR("Get param failed\n"));
        failures++;
    }
    if (atomMutexPut (NULL) != ATOM_ERR_PARAM)
    {
        ATOMLOG (_STR("Put param failed\n"));
        failures++;
    }

    /* Test atomMutexGet() can not be called from interrupt context */
    g_result = 0;
    if (atomMutexCreate (&mutex1) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating test mutex1\n"));
        failures++;
    }
    else
    {
        /* Fill out the timer callback request structure */
        timer_cb.cb_func = testCallback;
        timer_cb.cb_data = NULL;
        timer_cb.cb_ticks = SYSTEM_TICKS_PER_SEC;

        /* Request the timer callback to run in one second */
        if (atomTimerRegister (&timer_cb) != ATOM_OK)
        {
            ATOMLOG (_STR("Error registering timer\n"));
            failures++;
        }

        /* Wait two seconds for g_result to be set indicating success */
        else
        {
            atomTimerDelay (2 * SYSTEM_TICKS_PER_SEC);
            if (g_result != 1)
            {
                ATOMLOG (_STR("Context check failed\n"));
                failures++;
            }
        }

        /* Delete the test mutex */
        if (atomMutexDelete (&mutex1) != ATOM_OK)
        {
            ATOMLOG (_STR("Mutex1 delete failed\n"));
            failures++;
        }
    }

    /* Create mutex1 which will be owned by us */
    if (atomMutexCreate (&mutex1) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating test mutex 1\n"));
        failures++;
    }

    /* Create mutex2 which will be owned by another thread */
    else if (atomMutexCreate (&mutex2) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating test mutex 2\n"));
        failures++;
    }

    /* Create a test thread, the sole purpose of which is to own mutex2 */
    g_owned = 0;
    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++;
    }

    /* Sleep until the test thread owns mutex2 */
    atomTimerDelay (SYSTEM_TICKS_PER_SEC);
    if (g_owned == 0)
    {
        ATOMLOG (_STR("Thread own fail\n"));
        failures++;
    }

    /* Test wait on mutex with timeout - should timeout while owned by another thread */
    if ((status = atomMutexGet (&mutex2, SYSTEM_TICKS_PER_SEC)) != ATOM_TIMEOUT)
    {
        ATOMLOG (_STR("Get %d\n"), status);
        failures++;
    }
    else
    {
        /* Success */
    }

    /* Test wait on mutex with no blocking - should return that owned by another thread */
    if ((status = atomMutexGet (&mutex2, -1)) != ATOM_WOULDBLOCK)
    {
        ATOMLOG (_STR("Wouldblock err %d\n"), status);
        failures++;
    }

    /* Test wait on mutex with no blocking when mutex is available */
    if (atomMutexGet (&mutex1, -1) != ATOM_OK)
    {
        ATOMLOG (_STR("Error taking mutex1\n"));
        failures++;
    }
    else
    {
        /* Relinquish ownership of mutex1 */
        if (atomMutexPut (&mutex1) != ATOM_OK)
        {
            ATOMLOG (_STR("Error posting mutex\n"));
            failures++;
        }
    }

    /* Test for lock count overflows with too many gets */
    count = 255;
    while (count--)
    {
        if (atomMutexGet (&mutex1, 0) != ATOM_OK)
        {
            ATOMLOG (_STR("Error getting mutex1\n"));
            failures++;
            break;
        }
    }

    /* The lock count should overflow this time */
    if (atomMutexGet (&mutex1, 0) != ATOM_ERR_OVF)
    {
        ATOMLOG (_STR("Error tracking overflow\n"));
        failures++;
    }
    else
    {
        /* Success */
    }

    /* Delete the test mutexes */
    if (atomMutexDelete (&mutex1) != ATOM_OK)
    {
        ATOMLOG (_STR("Error deleting mutex1\n"));
        failures++;
    }
    if (atomMutexDelete (&mutex2) != ATOM_OK)
    {
        ATOMLOG (_STR("Error deleting mutex2\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;
}
Example #14
0
/**
 * \b test_start
 *
 * Start mutex test.
 *
 * This tests the lock count of a mutex. The mutex object should
 * count the number of times a thread has locked the mutex and
 * not fully release it for use by another thread until it has
 * been released the same number of times it was locked.
*
 * @retval Number of failures
 */
uint32_t test_start (void)
{
    int failures;
    int i;

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

    /* Create mutex */
    if (atomMutexCreate (&mutex1) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating mutex\n"));
        failures++;
    }
    else
    {
        /* Initialise the shared_data to zero */
        shared_data = 0;

        /* Take the mutex several times */
        for (i = 0; i < TEST_LOCK_CNT; i++)
        {
            if (atomMutexGet (&mutex1, 0) != ATOM_OK)
            {
                ATOMLOG (_STR("Error taking mutex\n"));
                failures++;
                break;
            }

        }

        /* Create second thread */
        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 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 enough times.
             */
            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 TEST_LOCK_CNT-1 times, after which we
             * should still own the mutex (until we release one more time).
             */
            for (i = 0; i < TEST_LOCK_CNT-1; i++)
            {
                if (atomMutexPut (&mutex1) != ATOM_OK)
                {
                    ATOMLOG (_STR("Failed release\n"));
                    failures++;
                }

            }

            /*
             * Wait a little while then check that shared_data has
             * not been modified (we should still own the mutex).
             */
            atomTimerDelay (SYSTEM_TICKS_PER_SEC/4);
            if (shared_data != 0)
            {
                ATOMLOG (_STR("Expected unmodified\n"));
                failures++;
            }

            /*
             * Release the mutex one more time, after which we should no
             * longer own the mutex (and wake up the second thread).
             */
            if (atomMutexPut (&mutex1) != ATOM_OK)
            {
                ATOMLOG (_STR("Failed release\n"));
                failures++;
            }

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

        /*
         * Finally attempt to release the mutex one more time, while
         * we no longer own the mutex. Either the second thread will
         * have ownership of it, or no thread will have ownership.
         * In both cases we expect to get an ownership error when we
         * attempt to release it.
         */
        if (atomMutexPut (&mutex1) != ATOM_ERR_OWNERSHIP)
        {
            ATOMLOG (_STR("Failed locked+1 release\n"));
            failures++;
        }

        /* Delete mutex, test finished */
        if (atomMutexDelete (&mutex1) != 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;

}
Example #15
0
/**
 * \b test_start
 *
 * Start mutex test.
 *
 * This tests timeouts on a mutex. We make a thread block with timeout
 * on a mutex, and test that sufficient time has actually passed as
 * was requested by the timeout parameter.
 *
 * The main thread creates a second thread which will immediately take
 * ownership of the mutex. The test checks that the correct timeout
 * occurs when the first thread blocks on the mutex which is already
 * owned (by the second thread).
 *
 * @retval Number of failures
 */
uint32_t test_start (void)
{
    int failures;
    uint32_t start_time, end_time;

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

    /* Create mutex */
    if (atomMutexCreate (&mutex1) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating mutex\n"));
        failures++;
    }
    else
    {
        /* Initialise the shared_data to zero */
        shared_data = 0;

        /* Create second thread */
        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 take ownership
         * of the mutex. We wait a while and check that shared_data has been
         * modified, which proves to us that the thread has taken the mutex.
         */
        atomTimerDelay (SYSTEM_TICKS_PER_SEC/4);
        if (shared_data != 1)
        {
            ATOMLOG (_STR("Shared data unmodified\n"));
            failures++;
        }

        /* Check successful so far */
        if (failures == 0)
        {
            /* Take note of the start time */
            start_time = atomTimeGet();

            /* Block on the mutex with two second timeout */
            if (atomMutexGet (&mutex1, 2 * SYSTEM_TICKS_PER_SEC) != ATOM_TIMEOUT)
            {
                ATOMLOG (_STR("Failed get\n"));
                failures++;
            }

            /* Take note of the end time */
            end_time = atomTimeGet();

            /* Now check that two seconds have passed */
            if ((end_time < (start_time + (2 * SYSTEM_TICKS_PER_SEC)))
                || (end_time > (start_time + (2 * SYSTEM_TICKS_PER_SEC) + 1)))
            {
                ATOMLOG (_STR("Bad time\n"));
                failures++;
            }
        }

        /* Delete mutex, test finished */
        if (atomMutexDelete (&mutex1) != 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;

}
Example #16
0
/**
 * \b test_start
 *
 * Start mutex test.
 *
 * With multiple threads blocking on a single mutex, this test confirms that
 * they are woken in order when the mutex is released. 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 mutex).
 *
 * To test this we create four threads which all wait on a single mutex.
 * 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 mutex 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;

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

    /* Create mutex */
    if (atomMutexCreate (&mutex1) != ATOM_OK)
    {
        ATOMLOG (_STR("Error creating test mutex 1\n"));
        failures++;
    }

    /* Take ownership of the mutex so all threads will block to begin with */
    else if (atomMutexGet (&mutex1, 0) != ATOM_OK)
    {
        ATOMLOG (_STR("Get error\n"));
        failures++;
    }

    /* Start the threads */
    else
    {
        /* 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 mutex */
        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 mutex */
        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 mutex */
        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 mutex */
        atomTimerDelay (SYSTEM_TICKS_PER_SEC/4);

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

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

        /*
         * Release the mutex. This will wake up one of the threads blocking
         * on it. That thread will take ownership of the mutex, and note the
         * order at which it was woken, before releasing the mutex. This in
         * turn will wake up the next thread blocking on the mutex until all
         * four test threads have taken and released the mutex, noting their
         * wake order.
         */
        if (atomMutexPut (&mutex1) != ATOM_OK)
        {
            ATOMLOG (_STR("Post fail\n"));
            failures++;
        }

        /* Sleep to give all four threads time to complete */
        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 mutex, test finished */
        if (atomMutexDelete (&mutex1) != 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;

}
Example #17
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;

}