Official mbed Real Time Operating System based on the RTX implementation of the CMSIS-RTOS API open standard.

Fork of mbed-rtos by mbed official

Committer:
emilmont
Date:
Tue Apr 30 10:51:19 2013 +0000
Revision:
11:db1fc233faa9
Parent:
6:350b53afb889
In the Keil MDK toolchain "RTX_Config.h" is a special system library header file

Who changed what in which revision?

UserRevisionLine numberNew contents of line
emilmont 6:350b53afb889 1 /*----------------------------------------------------------------------------
emilmont 6:350b53afb889 2 * RL-ARM - RTX
emilmont 6:350b53afb889 3 *----------------------------------------------------------------------------
emilmont 6:350b53afb889 4 * Name: RT_MUTEX.C
emilmont 6:350b53afb889 5 * Purpose: Implements mutex synchronization objects
emilmont 6:350b53afb889 6 * Rev.: V4.60
emilmont 6:350b53afb889 7 *----------------------------------------------------------------------------
emilmont 6:350b53afb889 8 *
emilmont 6:350b53afb889 9 * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
emilmont 6:350b53afb889 10 * All rights reserved.
emilmont 6:350b53afb889 11 * Redistribution and use in source and binary forms, with or without
emilmont 6:350b53afb889 12 * modification, are permitted provided that the following conditions are met:
emilmont 6:350b53afb889 13 * - Redistributions of source code must retain the above copyright
emilmont 6:350b53afb889 14 * notice, this list of conditions and the following disclaimer.
emilmont 6:350b53afb889 15 * - Redistributions in binary form must reproduce the above copyright
emilmont 6:350b53afb889 16 * notice, this list of conditions and the following disclaimer in the
emilmont 6:350b53afb889 17 * documentation and/or other materials provided with the distribution.
emilmont 6:350b53afb889 18 * - Neither the name of ARM nor the names of its contributors may be used
emilmont 6:350b53afb889 19 * to endorse or promote products derived from this software without
emilmont 6:350b53afb889 20 * specific prior written permission.
emilmont 6:350b53afb889 21 *
emilmont 6:350b53afb889 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
emilmont 6:350b53afb889 23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
emilmont 6:350b53afb889 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
emilmont 6:350b53afb889 25 * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
emilmont 6:350b53afb889 26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
emilmont 6:350b53afb889 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
emilmont 6:350b53afb889 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
emilmont 6:350b53afb889 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
emilmont 6:350b53afb889 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
emilmont 6:350b53afb889 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
emilmont 6:350b53afb889 32 * POSSIBILITY OF SUCH DAMAGE.
emilmont 6:350b53afb889 33 *---------------------------------------------------------------------------*/
emilmont 6:350b53afb889 34
emilmont 6:350b53afb889 35 #include "rt_TypeDef.h"
emilmont 11:db1fc233faa9 36 #include "RTX_Conf.h"
emilmont 6:350b53afb889 37 #include "rt_List.h"
emilmont 6:350b53afb889 38 #include "rt_Task.h"
emilmont 6:350b53afb889 39 #include "rt_Mutex.h"
emilmont 6:350b53afb889 40 #include "rt_HAL_CM.h"
emilmont 6:350b53afb889 41
emilmont 6:350b53afb889 42
emilmont 6:350b53afb889 43 /*----------------------------------------------------------------------------
emilmont 6:350b53afb889 44 * Functions
emilmont 6:350b53afb889 45 *---------------------------------------------------------------------------*/
emilmont 6:350b53afb889 46
emilmont 6:350b53afb889 47
emilmont 6:350b53afb889 48 /*--------------------------- rt_mut_init -----------------------------------*/
emilmont 6:350b53afb889 49
emilmont 6:350b53afb889 50 void rt_mut_init (OS_ID mutex) {
emilmont 6:350b53afb889 51 /* Initialize a mutex object */
emilmont 6:350b53afb889 52 P_MUCB p_MCB = mutex;
emilmont 6:350b53afb889 53
emilmont 6:350b53afb889 54 p_MCB->cb_type = MUCB;
emilmont 6:350b53afb889 55 p_MCB->prio = 0;
emilmont 6:350b53afb889 56 p_MCB->level = 0;
emilmont 6:350b53afb889 57 p_MCB->p_lnk = NULL;
emilmont 6:350b53afb889 58 p_MCB->owner = NULL;
emilmont 6:350b53afb889 59 }
emilmont 6:350b53afb889 60
emilmont 6:350b53afb889 61
emilmont 6:350b53afb889 62 /*--------------------------- rt_mut_delete ---------------------------------*/
emilmont 6:350b53afb889 63
emilmont 6:350b53afb889 64 #ifdef __CMSIS_RTOS
emilmont 6:350b53afb889 65 OS_RESULT rt_mut_delete (OS_ID mutex) {
emilmont 6:350b53afb889 66 /* Delete a mutex object */
emilmont 6:350b53afb889 67 P_MUCB p_MCB = mutex;
emilmont 6:350b53afb889 68 P_TCB p_TCB;
emilmont 6:350b53afb889 69
emilmont 6:350b53afb889 70 /* Restore owner task's priority. */
emilmont 6:350b53afb889 71 if (p_MCB->level != 0) {
emilmont 6:350b53afb889 72 p_MCB->owner->prio = p_MCB->prio;
emilmont 6:350b53afb889 73 if (p_MCB->owner != os_tsk.run) {
emilmont 6:350b53afb889 74 rt_resort_prio (p_MCB->owner);
emilmont 6:350b53afb889 75 }
emilmont 6:350b53afb889 76 }
emilmont 6:350b53afb889 77
emilmont 6:350b53afb889 78 while (p_MCB->p_lnk != NULL) {
emilmont 6:350b53afb889 79 /* A task is waiting for mutex. */
emilmont 6:350b53afb889 80 p_TCB = rt_get_first ((P_XCB)p_MCB);
emilmont 6:350b53afb889 81 rt_ret_val(p_TCB, 0/*osOK*/);
emilmont 6:350b53afb889 82 rt_rmv_dly(p_TCB);
emilmont 6:350b53afb889 83 p_TCB->state = READY;
emilmont 6:350b53afb889 84 rt_put_prio (&os_rdy, p_TCB);
emilmont 6:350b53afb889 85 }
emilmont 6:350b53afb889 86
emilmont 6:350b53afb889 87 if (os_rdy.p_lnk && (os_rdy.p_lnk->prio > os_tsk.run->prio)) {
emilmont 6:350b53afb889 88 /* preempt running task */
emilmont 6:350b53afb889 89 rt_put_prio (&os_rdy, os_tsk.run);
emilmont 6:350b53afb889 90 os_tsk.run->state = READY;
emilmont 6:350b53afb889 91 rt_dispatch (NULL);
emilmont 6:350b53afb889 92 }
emilmont 6:350b53afb889 93
emilmont 6:350b53afb889 94 p_MCB->cb_type = 0;
emilmont 6:350b53afb889 95
emilmont 6:350b53afb889 96 return (OS_R_OK);
emilmont 6:350b53afb889 97 }
emilmont 6:350b53afb889 98 #endif
emilmont 6:350b53afb889 99
emilmont 6:350b53afb889 100
emilmont 6:350b53afb889 101 /*--------------------------- rt_mut_release --------------------------------*/
emilmont 6:350b53afb889 102
emilmont 6:350b53afb889 103 OS_RESULT rt_mut_release (OS_ID mutex) {
emilmont 6:350b53afb889 104 /* Release a mutex object */
emilmont 6:350b53afb889 105 P_MUCB p_MCB = mutex;
emilmont 6:350b53afb889 106 P_TCB p_TCB;
emilmont 6:350b53afb889 107
emilmont 6:350b53afb889 108 if (p_MCB->level == 0 || p_MCB->owner != os_tsk.run) {
emilmont 6:350b53afb889 109 /* Unbalanced mutex release or task is not the owner */
emilmont 6:350b53afb889 110 return (OS_R_NOK);
emilmont 6:350b53afb889 111 }
emilmont 6:350b53afb889 112 if (--p_MCB->level != 0) {
emilmont 6:350b53afb889 113 return (OS_R_OK);
emilmont 6:350b53afb889 114 }
emilmont 6:350b53afb889 115 /* Restore owner task's priority. */
emilmont 6:350b53afb889 116 os_tsk.run->prio = p_MCB->prio;
emilmont 6:350b53afb889 117 if (p_MCB->p_lnk != NULL) {
emilmont 6:350b53afb889 118 /* A task is waiting for mutex. */
emilmont 6:350b53afb889 119 p_TCB = rt_get_first ((P_XCB)p_MCB);
emilmont 6:350b53afb889 120 #ifdef __CMSIS_RTOS
emilmont 6:350b53afb889 121 rt_ret_val(p_TCB, 0/*osOK*/);
emilmont 6:350b53afb889 122 #else
emilmont 6:350b53afb889 123 rt_ret_val(p_TCB, OS_R_MUT);
emilmont 6:350b53afb889 124 #endif
emilmont 6:350b53afb889 125 rt_rmv_dly (p_TCB);
emilmont 6:350b53afb889 126 /* A waiting task becomes the owner of this mutex. */
emilmont 6:350b53afb889 127 p_MCB->level = 1;
emilmont 6:350b53afb889 128 p_MCB->owner = p_TCB;
emilmont 6:350b53afb889 129 p_MCB->prio = p_TCB->prio;
emilmont 6:350b53afb889 130 /* Priority inversion, check which task continues. */
emilmont 6:350b53afb889 131 if (os_tsk.run->prio >= rt_rdy_prio()) {
emilmont 6:350b53afb889 132 rt_dispatch (p_TCB);
emilmont 6:350b53afb889 133 }
emilmont 6:350b53afb889 134 else {
emilmont 6:350b53afb889 135 /* Ready task has higher priority than running task. */
emilmont 6:350b53afb889 136 rt_put_prio (&os_rdy, os_tsk.run);
emilmont 6:350b53afb889 137 rt_put_prio (&os_rdy, p_TCB);
emilmont 6:350b53afb889 138 os_tsk.run->state = READY;
emilmont 6:350b53afb889 139 p_TCB->state = READY;
emilmont 6:350b53afb889 140 rt_dispatch (NULL);
emilmont 6:350b53afb889 141 }
emilmont 6:350b53afb889 142 }
emilmont 6:350b53afb889 143 else {
emilmont 6:350b53afb889 144 /* Check if own priority raised by priority inversion. */
emilmont 6:350b53afb889 145 if (rt_rdy_prio() > os_tsk.run->prio) {
emilmont 6:350b53afb889 146 rt_put_prio (&os_rdy, os_tsk.run);
emilmont 6:350b53afb889 147 os_tsk.run->state = READY;
emilmont 6:350b53afb889 148 rt_dispatch (NULL);
emilmont 6:350b53afb889 149 }
emilmont 6:350b53afb889 150 }
emilmont 6:350b53afb889 151 return (OS_R_OK);
emilmont 6:350b53afb889 152 }
emilmont 6:350b53afb889 153
emilmont 6:350b53afb889 154
emilmont 6:350b53afb889 155 /*--------------------------- rt_mut_wait -----------------------------------*/
emilmont 6:350b53afb889 156
emilmont 6:350b53afb889 157 OS_RESULT rt_mut_wait (OS_ID mutex, U16 timeout) {
emilmont 6:350b53afb889 158 /* Wait for a mutex, continue when mutex is free. */
emilmont 6:350b53afb889 159 P_MUCB p_MCB = mutex;
emilmont 6:350b53afb889 160
emilmont 6:350b53afb889 161 if (p_MCB->level == 0) {
emilmont 6:350b53afb889 162 p_MCB->owner = os_tsk.run;
emilmont 6:350b53afb889 163 p_MCB->prio = os_tsk.run->prio;
emilmont 6:350b53afb889 164 goto inc;
emilmont 6:350b53afb889 165 }
emilmont 6:350b53afb889 166 if (p_MCB->owner == os_tsk.run) {
emilmont 6:350b53afb889 167 /* OK, running task is the owner of this mutex. */
emilmont 6:350b53afb889 168 inc:p_MCB->level++;
emilmont 6:350b53afb889 169 return (OS_R_OK);
emilmont 6:350b53afb889 170 }
emilmont 6:350b53afb889 171 /* Mutex owned by another task, wait until released. */
emilmont 6:350b53afb889 172 if (timeout == 0) {
emilmont 6:350b53afb889 173 return (OS_R_TMO);
emilmont 6:350b53afb889 174 }
emilmont 6:350b53afb889 175 /* Raise the owner task priority if lower than current priority. */
emilmont 6:350b53afb889 176 /* This priority inversion is called priority inheritance. */
emilmont 6:350b53afb889 177 if (p_MCB->prio < os_tsk.run->prio) {
emilmont 6:350b53afb889 178 p_MCB->owner->prio = os_tsk.run->prio;
emilmont 6:350b53afb889 179 rt_resort_prio (p_MCB->owner);
emilmont 6:350b53afb889 180 }
emilmont 6:350b53afb889 181 if (p_MCB->p_lnk != NULL) {
emilmont 6:350b53afb889 182 rt_put_prio ((P_XCB)p_MCB, os_tsk.run);
emilmont 6:350b53afb889 183 }
emilmont 6:350b53afb889 184 else {
emilmont 6:350b53afb889 185 p_MCB->p_lnk = os_tsk.run;
emilmont 6:350b53afb889 186 os_tsk.run->p_lnk = NULL;
emilmont 6:350b53afb889 187 os_tsk.run->p_rlnk = (P_TCB)p_MCB;
emilmont 6:350b53afb889 188 }
emilmont 6:350b53afb889 189 rt_block(timeout, WAIT_MUT);
emilmont 6:350b53afb889 190 return (OS_R_TMO);
emilmont 6:350b53afb889 191 }
emilmont 6:350b53afb889 192
emilmont 6:350b53afb889 193
emilmont 6:350b53afb889 194 /*----------------------------------------------------------------------------
emilmont 6:350b53afb889 195 * end of file
emilmont 6:350b53afb889 196 *---------------------------------------------------------------------------*/
emilmont 6:350b53afb889 197