This is a brief introduction about how a message queue in ThreadX is like.
For every message queue, there is a unique ID and a Name assigned to it.
There are several pointers helping to manage the queue:
- Start, points to the start of the message queue
- End, points to the end of the message queue
- Read, points to the begin of a message to be read
- write, points to the begin of address where the next message can be written into
The Message Size keeps the size of a message in the queue.
There is also a Suspension List maintained for the message queue, which is actually a double link list, keeping track of the information of all the suspended threads.
The meanings of Capacity, Enqueued, Available Storage, Suspended Count and Send Notify are put in the graph below.
After initialization the Read and Write pointers are set to the begin of the message queue, and upon read/write to the queue, move torwards the end of the queue. Once the pointers run across the end of the queue, they will be set back to the begin of the queue. Therefore the message queue is actually a circular buffer for fixed size of messages.
The Suspension List is a list of the ThreadX thread structs, and is shared by read/write suspended threads.
It appears to be a design flaw to put read and write suspended threads in the same queue, while the truth is that it will never happen that both read and write suspended threads reside in the same suspension list. Because when a thread tries to write to the message queue and is suspended, the message queue must be full and there is no space to put more messages.
In this case any thread that tries to read from the queue will not be suspended. When a reading thread is suspended the story is pretty much the same. So it is safe here to use a single list for both read and write suspended threads (actually, either read or write suspended threads).
When a thread is suspended on the message queue, the corresponding thread struct will be stored in the Suspension List by adding the struct after the tail of the list. Thus the suspension list is a FIFO. ThreadX provides a "front send" command that allows to raise the priority of a "send" so that the message written to the queue will be moved to the front of the queue, and will be read at the next "receive" command. In many applications this "front send" command is eliminated because this method breaks the FIFO charateristics of the message queue, introducing potential issues.
Why the Suspension List is a double link list? What we need is only insert and remove a pending thread, right? A single link list would already suffice.
Good question. I don't know yet, but my guess is that this is because the message queue doesn't define a new thread struct, but directly uses the widely used common thread struct. For the common thread struct, it will make it a bit faster when traversing the suspended thread list if it is a double link list. However, I haven't seen in the code where the system gets benefits from the double link list design.
Please let me know if you have something to share here =)