Lab Checkoff
Dependencies: SDFileSystem TextLCD mbed-rtos mbed wave_player FATFileSystem
rt_Mutex.c
00001 /*---------------------------------------------------------------------------- 00002 * RL-ARM - RTX 00003 *---------------------------------------------------------------------------- 00004 * Name: RT_MUTEX.C 00005 * Purpose: Implements mutex synchronization objects 00006 * Rev.: V4.60 00007 *---------------------------------------------------------------------------- 00008 * 00009 * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH 00010 * All rights reserved. 00011 * Redistribution and use in source and binary forms, with or without 00012 * modification, are permitted provided that the following conditions are met: 00013 * - Redistributions of source code must retain the above copyright 00014 * notice, this list of conditions and the following disclaimer. 00015 * - Redistributions in binary form must reproduce the above copyright 00016 * notice, this list of conditions and the following disclaimer in the 00017 * documentation and/or other materials provided with the distribution. 00018 * - Neither the name of ARM nor the names of its contributors may be used 00019 * to endorse or promote products derived from this software without 00020 * specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00023 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00024 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00025 * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE 00026 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00027 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00028 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00029 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00030 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00031 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 * POSSIBILITY OF SUCH DAMAGE. 00033 *---------------------------------------------------------------------------*/ 00034 00035 #include "rt_TypeDef.h" 00036 #include "RTX_Config.h" 00037 #include "rt_List.h" 00038 #include "rt_Task.h" 00039 #include "rt_Mutex.h" 00040 #include "rt_HAL_CM.h" 00041 00042 00043 /*---------------------------------------------------------------------------- 00044 * Functions 00045 *---------------------------------------------------------------------------*/ 00046 00047 00048 /*--------------------------- rt_mut_init -----------------------------------*/ 00049 00050 void rt_mut_init (OS_ID mutex) { 00051 /* Initialize a mutex object */ 00052 P_MUCB p_MCB = mutex; 00053 00054 p_MCB->cb_type = MUCB; 00055 p_MCB->prio = 0; 00056 p_MCB->level = 0; 00057 p_MCB->p_lnk = NULL; 00058 p_MCB->owner = NULL; 00059 } 00060 00061 00062 /*--------------------------- rt_mut_delete ---------------------------------*/ 00063 00064 #ifdef __CMSIS_RTOS 00065 OS_RESULT rt_mut_delete (OS_ID mutex) { 00066 /* Delete a mutex object */ 00067 P_MUCB p_MCB = mutex; 00068 P_TCB p_TCB; 00069 00070 /* Restore owner task's priority. */ 00071 if (p_MCB->level != 0) { 00072 p_MCB->owner->prio = p_MCB->prio; 00073 if (p_MCB->owner != os_tsk.run) { 00074 rt_resort_prio (p_MCB->owner); 00075 } 00076 } 00077 00078 while (p_MCB->p_lnk != NULL) { 00079 /* A task is waiting for mutex. */ 00080 p_TCB = rt_get_first ((P_XCB)p_MCB); 00081 rt_ret_val(p_TCB, 0/*osOK*/); 00082 rt_rmv_dly(p_TCB); 00083 p_TCB->state = READY; 00084 rt_put_prio (&os_rdy, p_TCB); 00085 } 00086 00087 if (os_rdy.p_lnk && (os_rdy.p_lnk->prio > os_tsk.run->prio)) { 00088 /* preempt running task */ 00089 rt_put_prio (&os_rdy, os_tsk.run); 00090 os_tsk.run->state = READY; 00091 rt_dispatch (NULL); 00092 } 00093 00094 p_MCB->cb_type = 0; 00095 00096 return (OS_R_OK); 00097 } 00098 #endif 00099 00100 00101 /*--------------------------- rt_mut_release --------------------------------*/ 00102 00103 OS_RESULT rt_mut_release (OS_ID mutex) { 00104 /* Release a mutex object */ 00105 P_MUCB p_MCB = mutex; 00106 P_TCB p_TCB; 00107 00108 if (p_MCB->level == 0 || p_MCB->owner != os_tsk.run) { 00109 /* Unbalanced mutex release or task is not the owner */ 00110 return (OS_R_NOK); 00111 } 00112 if (--p_MCB->level != 0) { 00113 return (OS_R_OK); 00114 } 00115 /* Restore owner task's priority. */ 00116 os_tsk.run->prio = p_MCB->prio; 00117 if (p_MCB->p_lnk != NULL) { 00118 /* A task is waiting for mutex. */ 00119 p_TCB = rt_get_first ((P_XCB)p_MCB); 00120 #ifdef __CMSIS_RTOS 00121 rt_ret_val(p_TCB, 0/*osOK*/); 00122 #else 00123 rt_ret_val(p_TCB, OS_R_MUT); 00124 #endif 00125 rt_rmv_dly (p_TCB); 00126 /* A waiting task becomes the owner of this mutex. */ 00127 p_MCB->level = 1; 00128 p_MCB->owner = p_TCB; 00129 p_MCB->prio = p_TCB->prio; 00130 /* Priority inversion, check which task continues. */ 00131 if (os_tsk.run->prio >= rt_rdy_prio()) { 00132 rt_dispatch (p_TCB); 00133 } 00134 else { 00135 /* Ready task has higher priority than running task. */ 00136 rt_put_prio (&os_rdy, os_tsk.run); 00137 rt_put_prio (&os_rdy, p_TCB); 00138 os_tsk.run->state = READY; 00139 p_TCB->state = READY; 00140 rt_dispatch (NULL); 00141 } 00142 } 00143 else { 00144 /* Check if own priority raised by priority inversion. */ 00145 if (rt_rdy_prio() > os_tsk.run->prio) { 00146 rt_put_prio (&os_rdy, os_tsk.run); 00147 os_tsk.run->state = READY; 00148 rt_dispatch (NULL); 00149 } 00150 } 00151 return (OS_R_OK); 00152 } 00153 00154 00155 /*--------------------------- rt_mut_wait -----------------------------------*/ 00156 00157 OS_RESULT rt_mut_wait (OS_ID mutex, U16 timeout) { 00158 /* Wait for a mutex, continue when mutex is free. */ 00159 P_MUCB p_MCB = mutex; 00160 00161 if (p_MCB->level == 0) { 00162 p_MCB->owner = os_tsk.run; 00163 p_MCB->prio = os_tsk.run->prio; 00164 goto inc; 00165 } 00166 if (p_MCB->owner == os_tsk.run) { 00167 /* OK, running task is the owner of this mutex. */ 00168 inc:p_MCB->level++; 00169 return (OS_R_OK); 00170 } 00171 /* Mutex owned by another task, wait until released. */ 00172 if (timeout == 0) { 00173 return (OS_R_TMO); 00174 } 00175 /* Raise the owner task priority if lower than current priority. */ 00176 /* This priority inversion is called priority inheritance. */ 00177 if (p_MCB->prio < os_tsk.run->prio) { 00178 p_MCB->owner->prio = os_tsk.run->prio; 00179 rt_resort_prio (p_MCB->owner); 00180 } 00181 if (p_MCB->p_lnk != NULL) { 00182 rt_put_prio ((P_XCB)p_MCB, os_tsk.run); 00183 } 00184 else { 00185 p_MCB->p_lnk = os_tsk.run; 00186 os_tsk.run->p_lnk = NULL; 00187 os_tsk.run->p_rlnk = (P_TCB)p_MCB; 00188 } 00189 rt_block(timeout, WAIT_MUT); 00190 return (OS_R_TMO); 00191 } 00192 00193 00194 /*---------------------------------------------------------------------------- 00195 * end of file 00196 *---------------------------------------------------------------------------*/ 00197 00198
Generated on Fri Jul 15 2022 13:41:34 by 1.7.2