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