00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00041 #include <avr/interrupt.h>
00042 #include <stddef.h>
00043
00044 #include "otos_cfg.h"
00045 #include "otos_def.h"
00046 #include "types.h"
00047 #include "task.h"
00048 #include "mutex.h"
00049 #include "time.h"
00050
00051
00052
00066 uint8_t otosTestAndSet(uint8_t* pLock)
00067 {
00068 uint8_t stat;
00069 uint8_t iStat;
00070
00071
00072 iStat = SREG;
00073 cli();
00074 stat = *pLock;
00075 *pLock = 1;
00076 SREG = iStat;
00077
00078 return stat;
00079 }
00080
00081
00104 uint8_t otosLockMutex(OtosMutex* pMutex, uint32_t timeout)
00105 {
00106 uint8_t lock;
00107
00108
00109
00110 lock = otosTestAndSet(&pMutex->lock);
00111
00112 if (lock == 0)
00113 {
00114 pMutex->pOwner = g_pRunningTask;
00115 return MUTEX_SUCCESS;
00116 }
00117
00118 if (timeout == 0)
00119 {
00120 return MUTEX_ALREADY_LOCKED;
00121 }
00122 else
00123 {
00124 cli();
00125 g_pRunningTask->pWaitMutex = pMutex;
00126 g_pRunningTask->sleepTicks = (timeout == INFINITE) ? 0 : timeout;
00127 otosBlock();
00128 cli();
00129 if (g_pRunningTask->pWaitMutex)
00130 {
00131 g_pRunningTask->pWaitMutex = NULL;
00132 sei();
00133 return MUTEX_TIMEOUT;
00134 }
00135 else
00136 {
00137 pMutex->lock = 1;
00138 pMutex->pOwner = g_pRunningTask;
00139 sei();
00140 return MUTEX_SUCCESS;
00141 }
00142 }
00143 }
00144
00145
00161 uint8_t otosUnlockMutex(OtosMutex* pMutex)
00162 {
00163 OtosTask* pTmp;
00164 OtosTask* pNextTask;
00165 uint8_t dispatch;
00166 uint8_t unlock = 1;
00167
00168 if (pMutex->pOwner != g_pRunningTask)
00169 return MUTEX_NOT_OWNER;
00170
00171 dispatch = ISR_NOT_ACTIVE();
00172 cli();
00173
00174
00175 pTmp = g_pBlockedQueue;
00176 while (pTmp != NULL)
00177 {
00178 pNextTask = pTmp->pNext;
00179
00180 if (pTmp->pWaitMutex == pMutex)
00181 {
00182 pTmp->pWaitMutex = NULL;
00183 pTmp->sleepTicks = 0;
00184 pMutex->pOwner = pTmp;
00185 unlock = 0;
00186 otosWakeup(pTmp);
00187 break;
00188 }
00189
00190 pTmp = pNextTask;
00191 }
00192
00193 if (unlock)
00194 pMutex->lock = 0;
00195
00196 if (dispatch)
00197 otosScheduler(SCHED_NORM);
00198 else
00199 g_performDispatch = TRUE;
00200
00201 return MUTEX_SUCCESS;
00202 }
00203