atomqueue.c File Reference

#include <stdio.h>
#include <string.h>
#include "atom.h"
#include "atomqueue.h"
#include "atomtimer.h"

Data Structures

struct  queue_timer

Typedefs

typedef struct queue_timer QUEUE_TIMER

Functions

uint8_t atomQueueCreate (ATOM_QUEUE *qptr, uint8_t *buff_ptr, uint32_t unit_size, uint32_t max_num_msgs)
uint8_t atomQueueDelete (ATOM_QUEUE *qptr)
uint8_t atomQueueGet (ATOM_QUEUE *qptr, int32_t timeout, uint8_t *msgptr)
uint8_t atomQueuePut (ATOM_QUEUE *qptr, int32_t timeout, uint8_t *msgptr)

Detailed Description

Queue library.

This module implements a queue / message-passing library with the following features:

Flexible blocking APIs
Threads which wish to make a call which may block can choose whether to block, block with timeout, or not block and return a relevent status code.
Interrupt-safe calls
All APIs can be called from interrupt context. Any calls which could potentially block have optional parameters to prevent blocking if you wish to call them from interrupt context. Any attempt to make a call which would block from interrupt context will be automatically and safely prevented.
Priority-based queueing
Where multiple threads are blocking on a queue, they are woken in order of the threads' priorities. Where multiple threads of the same priority are blocking, they are woken in FIFO order.
Configurable queue sizes
Queues can be created with any sized message, and any number of stored messages.
Smart queue deletion
Where a queue is deleted while threads are blocking on it, all blocking threads are woken and returned a status code to indicate the reason for being woken.


Usage instructions:

All queue objects must be initialised before use by calling atomQueueCreate(). Once initialised atomQueueGet() and atomQueuePut() are used to send and receive messages via the queue respectively.

Messages can be added to a queue by calling atomQueuePut(). If the queue is full the caller will block until space becomes available (by a message being removed from the queue). Optionally a non-blocking call can be made in which case the call will return with a status code indicating that the queue is full. This allows messages to be posted from interrupt handlers or threads which you do not wish to block, providing it is not fatal that the call could fail if the queue was full.

Messages can be received from the queue by calling atomQueueGet(). This will return the first message available in the queue in FIFO order. If the queue is empty then the call will block. Optionally, a non-blocking call can be made in which case the call will return with a status code indicating that the queue is full. This allows messages to be received by interrupt handlers or threads which you do not wish to block.

A queue which is no longer required can be deleted using atomQueueDelete(). This function automatically wakes up any threads which are waiting on the deleted queue.


Typedef Documentation

typedef struct queue_timer QUEUE_TIMER

Function Documentation

uint8_t atomQueueCreate ( ATOM_QUEUE qptr,
uint8_t *  buff_ptr,
uint32_t  unit_size,
uint32_t  max_num_msgs 
)

atomQueueCreate

Initialises a queue object.

Must be called before calling any other queue library routines on a queue. Objects can be deleted later using atomQueueDelete().

Does not allocate storage, the caller provides the queue object.

Callers pass in their own buffer area for storing the queue messages while in transit between threads. The provided storage must be large enough to store (unit_size * max_num_mgs) bytes. i.e. the storage area will be used for up to max_num_msgs messages each of size unit_size.

Queues use a fixed-size message.

This function can be called from interrupt context.

Parameters:
[in] qptr Pointer to queue object
[in] buff_ptr Pointer to buffer storage area
[in] unit_size Size in bytes of each queue message
[in] max_num_msgs Maximum number of messages in the queue
Return values:
ATOM_OK Success
ATOM_ERR_PARAM Bad parameters

References ATOM_ERR_PARAM, ATOM_OK, atom_queue::buff_ptr, atom_queue::getSuspQ, atom_queue::insert_index, atom_queue::max_num_msgs, atom_queue::num_msgs_stored, atom_queue::putSuspQ, atom_queue::remove_index, uint8_t, and atom_queue::unit_size.

uint8_t atomQueueDelete ( ATOM_QUEUE qptr  ) 

atomQueueDelete

Deletes a queue object.

Any threads currently suspended on the queue will be woken up with return status ATOM_ERR_DELETED. If called at thread context then the scheduler will be called during this function which may schedule in one of the woken threads depending on relative priorities.

This function can be called from interrupt context, but loops internally waking up all threads blocking on the queue, so the potential execution cycles cannot be determined in advance.

Parameters:
[in] qptr Pointer to queue object
Return values:
ATOM_OK Success
ATOM_ERR_QUEUE Problem putting a woken thread on the ready queue
ATOM_ERR_TIMER Problem cancelling a timeout on a woken thread

Only call the scheduler if we are in thread context, otherwise it will be called on exiting the ISR by atomIntExit().

References ATOM_ERR_DELETED, ATOM_ERR_PARAM, ATOM_ERR_QUEUE, ATOM_ERR_TIMER, ATOM_OK, atomCurrentContext(), atomSched(), atomTimerCancel(), CRITICAL_END, CRITICAL_START, CRITICAL_STORE, FALSE, atom_queue::getSuspQ, atom_queue::putSuspQ, atom_tcb::suspend_timo_cb, atom_tcb::suspend_wake_status, tcbDequeueHead(), tcbEnqueuePriority(), tcbReadyQ, TRUE, and uint8_t.

uint8_t atomQueueGet ( ATOM_QUEUE qptr,
int32_t  timeout,
uint8_t *  msgptr 
)

atomQueueGet

Attempt to retrieve a message from a queue.

Retrieves one message at a time. Messages are copied into the passed msgptr storage area which should be large enough to contain one message of unit_size bytes. Where multiple messages are in the queue, messages are retrieved in FIFO order.

If the queue is currently empty, the call will do one of the following depending on the timeout value specified:

timeout == 0 : Call will block until a message is available
timeout > 0 : Call will block until a message or the specified timeout
timeout == -1 : Return immediately if no message is on the queue

If a maximum timeout value is specified (timeout > 0), and no message is present on the queue for the specified number of system ticks, the call will return with ATOM_TIMEOUT.

This function can only be called from interrupt context if the timeout parameter is -1 (in which case it does not block).

Parameters:
[in] qptr Pointer to queue object
[in] timeout Max system ticks to block (0 = forever, -1 = no block)
[out] msgptr Pointer to which the received message will be copied
Return values:
ATOM_OK Success
ATOM_TIMEOUT Queue wait timed out before being woken
ATOM_WOULDBLOCK Called with timeout == -1 but queue was empty
ATOM_ERR_DELETED Queue was deleted while suspended
ATOM_ERR_CONTEXT Not called in thread context and attempted to block
ATOM_ERR_PARAM Bad parameter
ATOM_ERR_QUEUE Problem putting the thread on the suspend queue
ATOM_ERR_TIMER Problem registering the timeout

Fill out the data needed by the callback to wake us up.

Store the timer details in the TCB so that we can cancel the timer callback if the queue is put before the timeout occurs.

Current thread now blocking, schedule in a new one. We already know we are in thread context so can call the scheduler from here.

Normal atomQueuePut() wakeups will set ATOM_OK status, while timeouts will set ATOM_TIMEOUT and queue deletions will set ATOM_ERR_DELETED.

Check suspend_wake_status. If it is ATOM_OK then we were woken because a message has been put on the queue and we can now copy it out. Otherwise we were woken because we timed out waiting for a message, or the queue was deleted, so we should just quit.

The scheduler may now make a policy decision to thread switch if we are currently in thread context. If we are in interrupt context it will be handled by atomIntExit().

References ATOM_ERR_CONTEXT, ATOM_ERR_PARAM, ATOM_ERR_QUEUE, ATOM_ERR_TIMER, ATOM_OK, ATOM_WOULDBLOCK, atomCurrentContext(), atomSched(), atomTimerRegister(), atom_timer::cb_data, atom_timer::cb_func, atom_timer::cb_ticks, CRITICAL_END, CRITICAL_START, CRITICAL_STORE, FALSE, atom_queue::getSuspQ, atom_queue::num_msgs_stored, POINTER, queue_timer::queue_ptr, atom_tcb::suspend_timo_cb, atom_tcb::suspend_wake_status, atom_tcb::suspended, queue_timer::suspQ, queue_timer::tcb_ptr, tcbDequeueEntry(), tcbEnqueuePriority(), TRUE, and uint8_t.

uint8_t atomQueuePut ( ATOM_QUEUE qptr,
int32_t  timeout,
uint8_t *  msgptr 
)

atomQueuePut

Attempt to put a message onto a queue.

Sends one message at a time. Messages are copied from the passed msgptr storage area which should contain a message of unit_size bytes.

If the queue is currently full, the call will do one of the following depending on the timeout value specified:

timeout == 0 : Call will block until space is available
timeout > 0 : Call will block until space or the specified timeout
timeout == -1 : Return immediately if the queue is full

If a maximum timeout value is specified (timeout > 0), and no space is available on the queue for the specified number of system ticks, the call will return with ATOM_TIMEOUT.

This function can only be called from interrupt context if the timeout parameter is -1 (in which case it does not block and may fail to post a message if the queue is full).

Parameters:
[in] qptr Pointer to queue object
[in] timeout Max system ticks to block (0 = forever, -1 = no block)
[out] msgptr Pointer from which the message should be copied out
Return values:
ATOM_OK Success
ATOM_WOULDBLOCK Called with timeout == -1 but queue was full
ATOM_TIMEOUT Queue wait timed out before being woken
ATOM_ERR_DELETED Queue was deleted while suspended
ATOM_ERR_CONTEXT Not called in thread context and attempted to block
ATOM_ERR_PARAM Bad parameter
ATOM_ERR_QUEUE Problem putting the thread on the suspend queue
ATOM_ERR_TIMER Problem registering the timeout

Fill out the data needed by the callback to wake us up.

Store the timer details in the TCB so that we can cancel the timer callback if a message is removed from the queue before the timeout occurs.

Current thread now blocking, schedule in a new one. We already know we are in thread context so can call the scheduler from here.

Normal atomQueueGet() wakeups will set ATOM_OK status, while timeouts will set ATOM_TIMEOUT and queue deletions will set ATOM_ERR_DELETED.

Check suspend_wake_status. If it is ATOM_OK then we were woken because a message has been removed from the queue and we can now add ours. Otherwise we were woken because we timed out waiting for a message, or the queue was deleted, so we should just quit.

The scheduler may now make a policy decision to thread switch if we are currently in thread context. If we are in interrupt context it will be handled by atomIntExit().

References ATOM_ERR_CONTEXT, ATOM_ERR_PARAM, ATOM_ERR_QUEUE, ATOM_ERR_TIMER, ATOM_OK, ATOM_WOULDBLOCK, atomCurrentContext(), atomSched(), atomTimerRegister(), atom_timer::cb_data, atom_timer::cb_func, atom_timer::cb_ticks, CRITICAL_END, CRITICAL_START, CRITICAL_STORE, FALSE, atom_queue::max_num_msgs, atom_queue::num_msgs_stored, POINTER, atom_queue::putSuspQ, queue_timer::queue_ptr, atom_tcb::suspend_timo_cb, atom_tcb::suspend_wake_status, atom_tcb::suspended, queue_timer::suspQ, queue_timer::tcb_ptr, tcbDequeueEntry(), tcbEnqueuePriority(), TRUE, and uint8_t.


Generated on Fri Jun 4 01:00:01 2010 for atomthreads by  doxygen 1.6.1