ON Semiconductor / mbed-os

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

Committer:
group-onsemi
Date:
Wed Jan 25 20:34:15 2017 +0000
Revision:
0:098463de4c5d
Initial commit

Who changed what in which revision?

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