Arrow / Mbed OS DAPLink Reset
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers rt_Mutex.c Source File

rt_Mutex.c

Go to the documentation of this file.
00001 /**
00002  * @file    rt_Mutex.c
00003  * @brief   
00004  *
00005  * DAPLink Interface Firmware
00006  * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved
00007  * SPDX-License-Identifier: Apache-2.0
00008  *
00009  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00010  * not use this file except in compliance with the License.
00011  * You may obtain a copy of the License at
00012  *
00013  * http://www.apache.org/licenses/LICENSE-2.0
00014  *
00015  * Unless required by applicable law or agreed to in writing, software
00016  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00017  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00018  * See the License for the specific language governing permissions and
00019  * limitations under the License.
00020  */
00021 
00022 #include "rt_TypeDef.h"
00023 #include "RTX_Config.h"
00024 #include "rt_List.h"
00025 #include "rt_Task.h"
00026 #include "rt_Mutex.h"
00027 
00028 
00029 /*----------------------------------------------------------------------------
00030  *      Functions
00031  *---------------------------------------------------------------------------*/
00032 
00033 
00034 /*--------------------------- rt_mut_init -----------------------------------*/
00035 
00036 void rt_mut_init (OS_ID mutex) {
00037   /* Initialize a mutex object */
00038   P_MUCB p_MCB = mutex;
00039 
00040   p_MCB->cb_type = MUCB;
00041   p_MCB->prio    = 0;
00042   p_MCB->level   = 0;
00043   p_MCB->p_lnk   = NULL;
00044   p_MCB->owner   = NULL;
00045 }
00046 
00047 
00048 /*--------------------------- rt_mut_release --------------------------------*/
00049 
00050 OS_RESULT rt_mut_release (OS_ID mutex) {
00051   /* Release a mutex object */
00052   P_MUCB p_MCB = mutex;
00053   P_TCB p_TCB;
00054 
00055   if (p_MCB->level == 0 || p_MCB->owner != os_tsk.run) {
00056     /* Unbalanced mutex release or task is not the owner */
00057     return (OS_R_NOK);
00058   }
00059   if (--p_MCB->level != 0) {
00060     return (OS_R_OK);
00061   }
00062   /* Restore owner task's priority. */
00063   os_tsk.run->prio = p_MCB->prio;
00064   if (p_MCB->p_lnk != NULL) {
00065     /* A task is waiting for mutex. */
00066     p_TCB = rt_get_first ((P_XCB)p_MCB);
00067     p_TCB->ret_val = OS_R_MUT;
00068     rt_rmv_dly (p_TCB);
00069     /* A waiting task becomes the owner of this mutex. */
00070     p_MCB->level     = 1;
00071     p_MCB->owner     = p_TCB;
00072     p_MCB->prio      = p_TCB->prio;
00073     /* Priority inversion, check which task continues. */
00074     if (os_tsk.run->prio >= rt_rdy_prio()) {
00075       rt_dispatch (p_TCB);
00076     }
00077     else {
00078       /* Ready task has higher priority than running task. */
00079       rt_put_prio (&os_rdy, os_tsk.run);
00080       rt_put_prio (&os_rdy, p_TCB);
00081       os_tsk.run->state = READY;
00082       p_TCB->state      = READY;
00083       rt_dispatch (NULL);
00084     }
00085     os_tsk.run->ret_val = OS_R_OK;
00086   }
00087   else {
00088     /* Check if own priority raised by priority inversion. */
00089     if (rt_rdy_prio() > os_tsk.run->prio) {
00090       rt_put_prio (&os_rdy, os_tsk.run);
00091       os_tsk.run->state = READY;
00092       rt_dispatch (NULL);
00093       os_tsk.run->ret_val = OS_R_OK;
00094     }
00095   }
00096   return (OS_R_OK);
00097 }
00098 
00099 
00100 /*--------------------------- rt_mut_wait -----------------------------------*/
00101 
00102 OS_RESULT rt_mut_wait (OS_ID mutex, U16 timeout) {
00103   /* Wait for a mutex, continue when mutex is free. */
00104   P_MUCB p_MCB = mutex;
00105 
00106   if (p_MCB->level == 0) {
00107     p_MCB->owner = os_tsk.run;
00108     p_MCB->prio  = os_tsk.run->prio;
00109     goto inc;
00110   }
00111   if (p_MCB->owner == os_tsk.run) {
00112     /* OK, running task is the owner of this mutex. */
00113 inc:p_MCB->level++;
00114     return (OS_R_OK);
00115   }
00116   /* Mutex owned by another task, wait until released. */
00117   if (timeout == 0) {
00118     return (OS_R_TMO);
00119   }
00120   /* Raise the owner task priority if lower than current priority. */
00121   /* This priority inversion is called priority inheritance.       */
00122   if (p_MCB->prio < os_tsk.run->prio) {
00123     p_MCB->owner->prio = os_tsk.run->prio;
00124     rt_resort_prio (p_MCB->owner);
00125   }
00126   if (p_MCB->p_lnk != NULL) {
00127     rt_put_prio ((P_XCB)p_MCB, os_tsk.run);
00128   }
00129   else {
00130     p_MCB->p_lnk = os_tsk.run;
00131     os_tsk.run->p_lnk  = NULL;
00132     os_tsk.run->p_rlnk = (P_TCB)p_MCB;
00133   }
00134   rt_block(timeout, WAIT_MUT);
00135   return (OS_R_TMO);
00136 }
00137 
00138 
00139 /*----------------------------------------------------------------------------
00140  * end of file
00141  *---------------------------------------------------------------------------*/
00142