]> git.donarmstrong.com Git - qmk_firmware.git/blob - tool/mbed/mbed-sdk/libraries/rtos/rtx/TARGET_CORTEX_M/rt_Mutex.c
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[qmk_firmware.git] / tool / mbed / mbed-sdk / libraries / rtos / rtx / TARGET_CORTEX_M / rt_Mutex.c
1 /*----------------------------------------------------------------------------
2  *      RL-ARM - RTX
3  *----------------------------------------------------------------------------
4  *      Name:    RT_MUTEX.C
5  *      Purpose: Implements mutex synchronization objects
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_List.h"
38 #include "rt_Task.h"
39 #include "rt_Mutex.h"
40 #include "rt_HAL_CM.h"
41
42
43 /*----------------------------------------------------------------------------
44  *      Functions
45  *---------------------------------------------------------------------------*/
46
47
48 /*--------------------------- rt_mut_init -----------------------------------*/
49
50 void rt_mut_init (OS_ID mutex) {
51   /* Initialize a mutex object */
52   P_MUCB p_MCB = mutex;
53
54   p_MCB->cb_type = MUCB;
55   p_MCB->prio    = 0;
56   p_MCB->level   = 0;
57   p_MCB->p_lnk   = NULL;
58   p_MCB->owner   = NULL;
59 }
60
61
62 /*--------------------------- rt_mut_delete ---------------------------------*/
63
64 #ifdef __CMSIS_RTOS
65 OS_RESULT rt_mut_delete (OS_ID mutex) {
66   /* Delete a mutex object */
67   P_MUCB p_MCB = mutex;
68   P_TCB  p_TCB;
69
70   /* Restore owner task's priority. */
71   if (p_MCB->level != 0) {
72     p_MCB->owner->prio = p_MCB->prio;
73     if (p_MCB->owner != os_tsk.run) {
74       rt_resort_prio (p_MCB->owner);
75     }
76   }
77
78   while (p_MCB->p_lnk != NULL) {
79     /* A task is waiting for mutex. */
80     p_TCB = rt_get_first ((P_XCB)p_MCB);
81     rt_ret_val(p_TCB, 0/*osOK*/);
82     rt_rmv_dly(p_TCB);
83     p_TCB->state = READY;
84     rt_put_prio (&os_rdy, p_TCB);
85   }
86
87   if (os_rdy.p_lnk && (os_rdy.p_lnk->prio > os_tsk.run->prio)) {
88     /* preempt running task */
89     rt_put_prio (&os_rdy, os_tsk.run);
90     os_tsk.run->state = READY;
91     rt_dispatch (NULL);
92   }
93
94   p_MCB->cb_type = 0;
95
96   return (OS_R_OK);
97 }
98 #endif
99
100
101 /*--------------------------- rt_mut_release --------------------------------*/
102
103 OS_RESULT rt_mut_release (OS_ID mutex) {
104   /* Release a mutex object */
105   P_MUCB p_MCB = mutex;
106   P_TCB  p_TCB;
107
108   if (p_MCB->level == 0 || p_MCB->owner != os_tsk.run) {
109     /* Unbalanced mutex release or task is not the owner */
110     return (OS_R_NOK);
111   }
112   if (--p_MCB->level != 0) {
113     return (OS_R_OK);
114   }
115   /* Restore owner task's priority. */
116   os_tsk.run->prio = p_MCB->prio;
117   if (p_MCB->p_lnk != NULL) {
118     /* A task is waiting for mutex. */
119     p_TCB = rt_get_first ((P_XCB)p_MCB);
120 #ifdef __CMSIS_RTOS
121     rt_ret_val(p_TCB, 0/*osOK*/);
122 #else
123     rt_ret_val(p_TCB, OS_R_MUT);
124 #endif
125     rt_rmv_dly (p_TCB);
126     /* A waiting task becomes the owner of this mutex. */
127     p_MCB->level     = 1;
128     p_MCB->owner     = p_TCB;
129     p_MCB->prio      = p_TCB->prio;
130     /* Priority inversion, check which task continues. */
131     if (os_tsk.run->prio >= rt_rdy_prio()) {
132       rt_dispatch (p_TCB);
133     }
134     else {
135       /* Ready task has higher priority than running task. */
136       rt_put_prio (&os_rdy, os_tsk.run);
137       rt_put_prio (&os_rdy, p_TCB);
138       os_tsk.run->state = READY;
139       p_TCB->state      = READY;
140       rt_dispatch (NULL);
141     }
142   }
143   else {
144     /* Check if own priority raised by priority inversion. */
145     if (rt_rdy_prio() > os_tsk.run->prio) {
146       rt_put_prio (&os_rdy, os_tsk.run);
147       os_tsk.run->state = READY;
148       rt_dispatch (NULL);
149     }
150   }
151   return (OS_R_OK);
152 }
153
154
155 /*--------------------------- rt_mut_wait -----------------------------------*/
156
157 OS_RESULT rt_mut_wait (OS_ID mutex, U16 timeout) {
158   /* Wait for a mutex, continue when mutex is free. */
159   P_MUCB p_MCB = mutex;
160
161   if (p_MCB->level == 0) {
162     p_MCB->owner = os_tsk.run;
163     p_MCB->prio  = os_tsk.run->prio;
164     goto inc;
165   }
166   if (p_MCB->owner == os_tsk.run) {
167     /* OK, running task is the owner of this mutex. */
168 inc:p_MCB->level++;
169     return (OS_R_OK);
170   }
171   /* Mutex owned by another task, wait until released. */
172   if (timeout == 0) {
173     return (OS_R_TMO);
174   }
175   /* Raise the owner task priority if lower than current priority. */
176   /* This priority inversion is called priority inheritance.       */
177   if (p_MCB->prio < os_tsk.run->prio) {
178     p_MCB->owner->prio = os_tsk.run->prio;
179     rt_resort_prio (p_MCB->owner);
180   }
181   if (p_MCB->p_lnk != NULL) {
182     rt_put_prio ((P_XCB)p_MCB, os_tsk.run);
183   }
184   else {
185     p_MCB->p_lnk = os_tsk.run;
186     os_tsk.run->p_lnk  = NULL;
187     os_tsk.run->p_rlnk = (P_TCB)p_MCB;
188   }
189   rt_block(timeout, WAIT_MUT);
190   return (OS_R_TMO);
191 }
192
193
194 /*----------------------------------------------------------------------------
195  * end of file
196  *---------------------------------------------------------------------------*/
197