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