Control a robot over the internet using UDP and a Wifly module (WiFi).

Dependencies:   Motor TextLCD WiflyInterface mbed-rtos mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers rt_Mutex.c Source File

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_Conf.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