]> git.donarmstrong.com Git - qmk_firmware.git/blob - tool/mbed/mbed-sdk/libraries/rtos/rtx/TARGET_CORTEX_M/rt_List.c
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[qmk_firmware.git] / tool / mbed / mbed-sdk / libraries / rtos / rtx / TARGET_CORTEX_M / rt_List.c
1 /*----------------------------------------------------------------------------
2  *      RL-ARM - RTX
3  *----------------------------------------------------------------------------
4  *      Name:    RT_LIST.C
5  *      Purpose: Functions for the management of different lists
6  *      Rev.:    V4.60
7  *----------------------------------------------------------------------------
8  *
9  * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
10  * All rights reserved.
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions are met:
13  *  - Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  *  - Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *  - Neither the name of ARM  nor the names of its contributors may be used
19  *    to endorse or promote products derived from this software without
20  *    specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
26  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *---------------------------------------------------------------------------*/
34
35 #include "rt_TypeDef.h"
36 #include "RTX_Conf.h"
37 #include "rt_System.h"
38 #include "rt_List.h"
39 #include "rt_Task.h"
40 #include "rt_Time.h"
41 #include "rt_HAL_CM.h"
42
43 /*----------------------------------------------------------------------------
44  *      Global Variables
45  *---------------------------------------------------------------------------*/
46
47 /* List head of chained ready tasks */
48 struct OS_XCB  os_rdy;
49 /* List head of chained delay tasks */
50 struct OS_XCB  os_dly;
51
52
53 /*----------------------------------------------------------------------------
54  *      Functions
55  *---------------------------------------------------------------------------*/
56
57
58 /*--------------------------- rt_put_prio -----------------------------------*/
59
60 void rt_put_prio (P_XCB p_CB, P_TCB p_task) {
61   /* Put task identified with "p_task" into list ordered by priority.       */
62   /* "p_CB" points to head of list; list has always an element at end with  */
63   /* a priority less than "p_task->prio".                                   */
64   P_TCB p_CB2;
65   U32 prio;
66   BOOL sem_mbx = __FALSE;
67
68   if (p_CB->cb_type == SCB || p_CB->cb_type == MCB || p_CB->cb_type == MUCB) {
69     sem_mbx = __TRUE;
70   }
71   prio = p_task->prio;
72   p_CB2 = p_CB->p_lnk;
73   /* Search for an entry in the list */
74   while (p_CB2 != NULL && prio <= p_CB2->prio) {
75     p_CB = (P_XCB)p_CB2;
76     p_CB2 = p_CB2->p_lnk;
77   }
78   /* Entry found, insert the task into the list */
79   p_task->p_lnk = p_CB2;
80   p_CB->p_lnk = p_task;
81   if (sem_mbx) {
82     if (p_CB2 != NULL) {
83       p_CB2->p_rlnk = p_task;
84     }
85     p_task->p_rlnk = (P_TCB)p_CB;
86   }
87   else {
88     p_task->p_rlnk = NULL;
89   }
90 }
91
92
93 /*--------------------------- rt_get_first ----------------------------------*/
94
95 P_TCB rt_get_first (P_XCB p_CB) {
96   /* Get task at head of list: it is the task with highest priority. */
97   /* "p_CB" points to head of list. */
98   P_TCB p_first;
99
100   p_first = p_CB->p_lnk;
101   p_CB->p_lnk = p_first->p_lnk;
102   if (p_CB->cb_type == SCB || p_CB->cb_type == MCB || p_CB->cb_type == MUCB) {
103     if (p_first->p_lnk != NULL) {
104       p_first->p_lnk->p_rlnk = (P_TCB)p_CB;
105       p_first->p_lnk = NULL;
106     }
107     p_first->p_rlnk = NULL;
108   }
109   else {
110     p_first->p_lnk = NULL;
111   }
112   return (p_first);
113 }
114
115
116 /*--------------------------- rt_put_rdy_first ------------------------------*/
117
118 void rt_put_rdy_first (P_TCB p_task) {
119   /* Put task identified with "p_task" at the head of the ready list. The   */
120   /* task must have at least a priority equal to highest priority in list.  */
121   p_task->p_lnk = os_rdy.p_lnk;
122   p_task->p_rlnk = NULL;
123   os_rdy.p_lnk = p_task;
124 }
125
126
127 /*--------------------------- rt_get_same_rdy_prio --------------------------*/
128
129 P_TCB rt_get_same_rdy_prio (void) {
130   /* Remove a task of same priority from ready list if any exists. Other-   */
131   /* wise return NULL.                                                      */
132   P_TCB p_first;
133
134   p_first = os_rdy.p_lnk;
135   if (p_first->prio == os_tsk.run->prio) {
136     os_rdy.p_lnk = os_rdy.p_lnk->p_lnk;
137     return (p_first);
138   }
139   return (NULL);
140 }
141
142
143 /*--------------------------- rt_resort_prio --------------------------------*/
144
145 void rt_resort_prio (P_TCB p_task) {
146   /* Re-sort ordered lists after the priority of 'p_task' has changed.      */
147   P_TCB p_CB;
148
149   if (p_task->p_rlnk == NULL) {
150     if (p_task->state == READY) {
151       /* Task is chained into READY list. */
152       p_CB = (P_TCB)&os_rdy;
153       goto res;
154     }
155   }
156   else {
157     p_CB = p_task->p_rlnk;
158     while (p_CB->cb_type == TCB) {
159       /* Find a header of this task chain list. */
160       p_CB = p_CB->p_rlnk;
161     }
162 res:rt_rmv_list (p_task);
163     rt_put_prio ((P_XCB)p_CB, p_task);
164   }
165 }
166
167
168 /*--------------------------- rt_put_dly ------------------------------------*/
169
170 void rt_put_dly (P_TCB p_task, U16 delay) {
171   /* Put a task identified with "p_task" into chained delay wait list using */
172   /* a delay value of "delay".                                              */
173   P_TCB p;
174   U32 delta,idelay = delay;
175
176   p = (P_TCB)&os_dly;
177   if (p->p_dlnk == NULL) {
178     /* Delay list empty */
179     delta = 0;
180     goto last;
181   }
182   delta = os_dly.delta_time;
183   while (delta < idelay) {
184     if (p->p_dlnk == NULL) {
185       /* End of list found */
186 last: p_task->p_dlnk = NULL;
187       p->p_dlnk = p_task;
188       p_task->p_blnk = p;
189       p->delta_time = (U16)(idelay - delta);
190       p_task->delta_time = 0;
191       return;
192     }
193     p = p->p_dlnk;
194     delta += p->delta_time;
195   }
196   /* Right place found */
197   p_task->p_dlnk = p->p_dlnk;
198   p->p_dlnk = p_task;
199   p_task->p_blnk = p;
200   if (p_task->p_dlnk != NULL) {
201     p_task->p_dlnk->p_blnk = p_task;
202   }
203   p_task->delta_time = (U16)(delta - idelay);
204   p->delta_time -= p_task->delta_time;
205 }
206
207
208 /*--------------------------- rt_dec_dly ------------------------------------*/
209
210 void rt_dec_dly (void) {
211   /* Decrement delta time of list head: remove tasks having a value of zero.*/
212   P_TCB p_rdy;
213
214   if (os_dly.p_dlnk == NULL) {
215     return;
216   }
217   os_dly.delta_time--;
218   while ((os_dly.delta_time == 0) && (os_dly.p_dlnk != NULL)) {
219     p_rdy = os_dly.p_dlnk;
220     if (p_rdy->p_rlnk != NULL) {
221       /* Task is really enqueued, remove task from semaphore/mailbox */
222       /* timeout waiting list. */
223       p_rdy->p_rlnk->p_lnk = p_rdy->p_lnk;
224       if (p_rdy->p_lnk != NULL) {
225         p_rdy->p_lnk->p_rlnk = p_rdy->p_rlnk;
226         p_rdy->p_lnk = NULL;
227       }
228       p_rdy->p_rlnk = NULL;
229     }
230     rt_put_prio (&os_rdy, p_rdy);
231     os_dly.delta_time = p_rdy->delta_time;
232     if (p_rdy->state == WAIT_ITV) {
233       /* Calculate the next time for interval wait. */
234       p_rdy->delta_time = p_rdy->interval_time + (U16)os_time;
235     }
236     p_rdy->state   = READY;
237     os_dly.p_dlnk = p_rdy->p_dlnk;
238     if (p_rdy->p_dlnk != NULL) {
239       p_rdy->p_dlnk->p_blnk =  (P_TCB)&os_dly;
240       p_rdy->p_dlnk = NULL;
241     }
242     p_rdy->p_blnk = NULL;
243   }
244 }
245
246
247 /*--------------------------- rt_rmv_list -----------------------------------*/
248
249 void rt_rmv_list (P_TCB p_task) {
250   /* Remove task identified with "p_task" from ready, semaphore or mailbox  */
251   /* waiting list if enqueued.                                              */
252   P_TCB p_b;
253
254   if (p_task->p_rlnk != NULL) {
255     /* A task is enqueued in semaphore / mailbox waiting list. */
256     p_task->p_rlnk->p_lnk = p_task->p_lnk;
257     if (p_task->p_lnk != NULL) {
258       p_task->p_lnk->p_rlnk = p_task->p_rlnk;
259     }
260     return;
261   }
262
263   p_b = (P_TCB)&os_rdy;
264   while (p_b != NULL) {
265     /* Search the ready list for task "p_task" */
266     if (p_b->p_lnk == p_task) {
267       p_b->p_lnk = p_task->p_lnk;
268       return;
269     }
270     p_b = p_b->p_lnk;
271   }
272 }
273
274
275 /*--------------------------- rt_rmv_dly ------------------------------------*/
276
277 void rt_rmv_dly (P_TCB p_task) {
278   /* Remove task identified with "p_task" from delay list if enqueued.      */
279   P_TCB p_b;
280
281   p_b = p_task->p_blnk;
282   if (p_b != NULL) {
283     /* Task is really enqueued */
284     p_b->p_dlnk = p_task->p_dlnk;
285     if (p_task->p_dlnk != NULL) {
286       /* 'p_task' is in the middle of list */
287       p_b->delta_time += p_task->delta_time;
288       p_task->p_dlnk->p_blnk = p_b;
289       p_task->p_dlnk = NULL;
290     }
291     else {
292       /* 'p_task' is at the end of list */
293       p_b->delta_time = 0;
294     }
295     p_task->p_blnk = NULL;
296   }
297 }
298
299
300 /*--------------------------- rt_psq_enq ------------------------------------*/
301
302 void rt_psq_enq (OS_ID entry, U32 arg) {
303   /* Insert post service request "entry" into ps-queue. */
304   U32 idx;
305
306   idx = rt_inc_qi (os_psq->size, &os_psq->count, &os_psq->first);
307   if (idx < os_psq->size) {
308     os_psq->q[idx].id  = entry;
309     os_psq->q[idx].arg = arg;
310   }
311   else {
312     os_error (OS_ERR_FIFO_OVF);
313   }
314 }
315
316
317 /*----------------------------------------------------------------------------
318  * end of file
319  *---------------------------------------------------------------------------*/
320