Are the Queue APIs thread-safe?

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

I just wanted to know if these APIs are guaranteed thread safe by the ThreadX RTOS?

/** @} */

/*****************************************************************************/

/** @addtogroup queues       Queues

*  @ingroup rtos

*

* Queue management functionss

*

*

*  @{

*/

/*****************************************************************************/

/** Initialises a queue

*

* Initialises a FIFO queue

*

* @param queue : a pointer to the queue handle to be initialised

* @param name  : a text string name for the queue (NULL is allowed)

* @param message_size : size in bytes of objects that will be held in the queue

* @param number_of_messages : depth of the queue - i.e. max number of objects in the queue

*

* @return    WICED_SUCCESS : on success.

* @return    WICED_ERROR   : if an error occurred

*/

wiced_result_t wiced_rtos_init_queue( wiced_queue_t* queue, const char* name, uint32_t message_size, uint32_t number_of_messages );

/** Pushes an object onto a queue

*

* Pushes an object onto a queue

*

* @param queue : a pointer to the queue handle

* @param message : the object to be added to the queue. Size is assumed to be

*                  the size specified in @ref wiced_rtos_init_queue

* @param timeout_ms: the number of milliseconds to wait before returning

*

* @return    WICED_SUCCESS : on success.

* @return    WICED_ERROR   : if an error or timeout occurred

*/

wiced_result_t wiced_rtos_push_to_queue( wiced_queue_t* queue, void* message, uint32_t timeout_ms );

/** Pops an object off a queue

*

* Pops an object off a queue

*

* @param queue : a pointer to the queue handle

* @param message : pointer to a buffer that will receive the object being

*                  popped off the queue. Size is assumed to be

*                  the size specified in @ref wiced_rtos_init_queue , hence

*                  you must ensure the buffer is long enough or memory

*                  corruption will result

* @param timeout_ms: the number of milliseconds to wait before returning

*

* @return    WICED_SUCCESS : on success.

* @return    WICED_ERROR   : if an error or timeout occurred

*/

wiced_result_t wiced_rtos_pop_from_queue( wiced_queue_t* queue, void* message, uint32_t timeout_ms );

/** De-initialise a queue

*

* Deletes a queue created with @ref wiced_rtos_init_queue

*

* @param queue : a pointer to the queue handle

*

* @return    WICED_SUCCESS : on success.

* @return    WICED_ERROR   : if an error occurred

*/

wiced_result_t wiced_rtos_deinit_queue( wiced_queue_t* queue );

/** Check if a queue is empty

*

* @param queue : a pointer to the queue handle

*

* @return    WICED_SUCCESS : queue is empty.

* @return    WICED_ERROR   : queue is not empty.

*/

wiced_result_t wiced_rtos_is_queue_empty( wiced_queue_t* queue );

/** Check if a queue is full

*

* @param queue : a pointer to the queue handle

*

* @return    WICED_SUCCESS : queue is full.

* @return    WICED_ERROR   : queue is not full.

*/

wiced_result_t wiced_rtos_is_queue_full( wiced_queue_t* queue );

/** Get the queue occupancy

*

* @param queue : a pointer to the queue handle

* @param count : pointer to integer for storing occupancy count

*

* @return    WICED_SUCCESS : on success.

* @return    WICED_ERROR   : if an error occurred

*/

wiced_result_t wiced_rtos_get_queue_occupancy( wiced_queue_t* queue, uint32_t *count );

0 Likes
1 Solution
Anonymous
Not applicable

AFAIK they are. From ThreadX user guide:

Message queues are the primary means of inter- thread communication in ThreadX.

Messages are copied to a queue by tx_queue_send and are copied from a queue by tx_queue_receive. The only exception to this is when a thread is suspended while waiting for a message on an empty queue. In this case, the next message sent to the queue is placed directly into the thread’s destination area.

I never experienced race-conditions while using queues.

View solution in original post

7 Replies
Anonymous
Not applicable

AFAIK they are. From ThreadX user guide:

Message queues are the primary means of inter- thread communication in ThreadX.

Messages are copied to a queue by tx_queue_send and are copied from a queue by tx_queue_receive. The only exception to this is when a thread is suspended while waiting for a message on an empty queue. In this case, the next message sent to the queue is placed directly into the thread’s destination area.

I never experienced race-conditions while using queues.

Anonymous
Not applicable

Thanks Olivier.

0 Likes

Can you explain why the pointer dereference without any protection is thread safe?

e.g.

wiced_result_t wiced_rtos_get_queue_occupancy( wiced_queue_t* queue, uint32_t *count )

{

    *count = queue->handle.tx_queue_enqueued;

    return WICED_SUCCESS;

}

0 Likes
Anonymous
Not applicable

Well it isn't, but that's not ThreadX API. I suppose to have a "safer" implementation, we'd need to call tx_queue_info_get and retrieve available_storage value.

0 Likes

olivierdufour wrote:

Well it isn't, but that's not ThreadX API. I suppose to have a "safer" implementation, we'd need to call tx_queue_info_get and retrieve available_storage value.

The ThreadX's APIs are supposed to be thread safe.

However, WICED's API implementation does not.

0 Likes
Anonymous
Not applicable

I don't totally agree with you. For other functions, calls are direct to ThreadX API, so there shouldn't be any issue.

For the sole example of get_queue_occupancy, there might be an issue, but I'm not convinced.

The value you will get might be good, or greater than the actual value, but that shouldn't be a problem (you're only reading it, not writing it).

Since it's a single word read, there is no chance the data will be partially wrong, but it could be outdated when you process it.

0 Likes

Assume the push to queue has below logic:

lock

do the real work of handling push queue

set queue->handle.tx_queue_enqueued

unlock

Now you have a implementation of wiced_rtos_get_queue_occupancy

by just getting  queue->handle.tx_queue_enqueued without locking.

It's possible you got wrong value while the

"real work of handling push queue" is in progress but

queue->handle.tx_queue_enqueued is not updated.

So you don't get a partially wrong value, you just get a wrong value.