1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** POSIX wrapper for THREADX */
16 /** */
17 /** */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 /* Include necessary system files. */
23
24 #include "tx_api.h" /* Threadx API */
25 #include "pthread.h" /* Posix API */
26 #include "px_int.h" /* Posix helper functions */
27
28
29 /**************************************************************************/
30 /* */
31 /* FUNCTION RELEASE */
32 /* */
33 /* posix_arrange_msg PORTABLE C */
34 /* 6.2.0 */
35 /* AUTHOR */
36 /* */
37 /* William E. Lamie, Microsoft Corporation */
38 /* */
39 /* DESCRIPTION */
40 /* */
41 /* Return the oldest, highest priority message from the queue. */
42 /* */
43 /* INPUT */
44 /* */
45 /* Queue queue descriptor */
46 /* *pMsgPrio If not NULL, priority of message */
47 /* */
48 /* OUTPUT */
49 /* */
50 /* OK Always return successful */
51 /* */
52 /* CALLS */
53 /* */
54 /* None */
55 /* */
56 /* CALLED BY */
57 /* */
58 /* POSIX internal Code */
59 /* */
60 /* RELEASE HISTORY */
61 /* */
62 /* DATE NAME DESCRIPTION */
63 /* */
64 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
65 /* 10-31-2022 Scott Larson Modified comments, */
66 /* fixed message swap logic, */
67 /* resulting in version 6.2.0 */
68 /* */
69 /**************************************************************************/
posix_arrange_msg(TX_QUEUE * Queue,ULONG * pMsgPrio)70 ULONG posix_arrange_msg(TX_QUEUE *Queue, ULONG *pMsgPrio)
71 {
72 ULONG* q_read; /* to store read ptr of the queue */
73 ULONG* temp_q = TX_NULL; /* temp storage for the message pointer */
74 ULONG numMsgs; /* no of messages queued */
75 ULONG msg; /* temp variable for thr for loop */
76 ULONG priority; /* priority of the message */
77 ULONG maxPrio; /* max. priority of the messages in queue*/
78 ULONG number2; /* messages */
79 ULONG minNo; /* oldest message in the same priority */
80 ULONG swap; /* temp.variable for the swapping of the */
81 /* messages */
82
83 /* initialize the priority to the lowest priority. */
84 maxPrio = 0;
85 minNo = 0;
86
87 /* Copy read pointer to the temporary variable. */
88 q_read = Queue -> tx_queue_read;
89
90 /* Copy no. of messages in the queue to the temporary variable. */
91 numMsgs = Queue -> tx_queue_enqueued;
92
93 /* If there is 0 or 1 message, no rearranging is needed. */
94 if (numMsgs < 2)
95 {
96 return(OK);
97 }
98
99 for (msg = 0; msg < numMsgs; msg++)
100 {
101 /* Advance q_read to read the priority of the message. */
102 q_read = q_read + TX_POSIX_QUEUE_PRIORITY_OFFSET;
103
104 /* Priority of the message queued. */
105 priority = *q_read;
106
107 /* check with maxpriority. */
108 if (priority > maxPrio)
109 {
110 /* copy read pointer to temporary pointer. */
111 temp_q = q_read-TX_POSIX_QUEUE_PRIORITY_OFFSET;
112
113 /* increment read pointer to point to order. */
114 q_read++;
115
116 /* copy FIFO order to the message */
117 minNo = *q_read;
118
119 /* Found higher priority message. */
120 maxPrio = priority;
121
122 q_read++;
123 }
124
125 /* if more than one message of the same priority is in the queue
126 then check if this the oldest message. */
127 else if (priority == maxPrio)
128 {
129 /* increment read pointer to point to read FIFO order */
130 q_read++;
131
132 /* copy number to the local variable. */
133 number2 = *q_read;
134
135 /* Go to next message. */
136 q_read++;
137
138 /* find the oldest of the messages in this priority level. */
139 if( number2 < minNo )
140 {
141 /* founder older one */
142 minNo = number2;
143 /* copy read pointer to temporary buffer. */
144 temp_q = q_read - (TX_POSIX_MESSAGE_SIZE);
145 }
146 }
147
148 else
149 {
150 /* Not highest priority, go to next message. */
151 q_read = q_read + (TX_POSIX_MESSAGE_SIZE - TX_POSIX_QUEUE_PRIORITY_OFFSET);
152 }
153
154 /* Determine if we are at the end. */
155 if (q_read >= Queue -> tx_queue_end)
156 {
157 /* Yes, wrap around to the beginning. */
158 q_read = Queue -> tx_queue_start;
159 }
160 }
161
162 /* Output priority if non-null */
163 if (pMsgPrio != NULL)
164 {
165 /* copy message priority. */
166 *pMsgPrio = maxPrio;
167 }
168
169 /* All messages checked, temp_q holds address of oldest highest priority message
170 and maxPrio holds the highest priority. */
171 /* Get the current queue read pointer */
172 q_read = Queue -> tx_queue_read;
173
174 if((temp_q != TX_NULL) && (temp_q != q_read))
175 {
176 /* Swap the messages. */
177 for (msg = 0; msg < TX_POSIX_MESSAGE_SIZE; msg++)
178 {
179 swap = *temp_q;
180 *temp_q = *q_read;
181 *q_read = swap;
182 temp_q++;
183 q_read++;
184 }
185 }
186
187 return(OK);
188 }
189