tinyOS  v1.00
tMutex.c
Go to the documentation of this file.
1 
14 #include "tMutex.h"
15 #include "tinyOS.h"
16 
17 #if !defined(TINYOS_ENABLE_MUTEX) || TINYOS_ENABLE_MUTEX == 1
18 
23 void tMutexInit (tMutex *mutex) {
25 
26  mutex->lockedCount = 0;
27  mutex->owner = (tTask *) 0;
28  mutex->ownerOriginalPrio = TINYOS_PRO_COUNT;
29 }
30 
37 uint32_t tMutexWait (tMutex *mutex, uint32_t waitTicks) {
38  uint32_t status = tTaskEnterCritical();
39 
40  if (mutex->lockedCount <= 0) {
41  // 如果没有锁定,则使用当前任务锁定
42  mutex->owner = currentTask;
44  mutex->lockedCount++;
45 
46  tTaskExitCritical(status);
47  return tErrorNoError;
48  } else {
49  // 信号量已经被锁定
50  if (mutex->owner == currentTask) {
51  // 如果是信号量的拥有者再次wait,简单增加计数
52  mutex->lockedCount++;
53 
54  tTaskExitCritical(status);
55  return tErrorNoError;
56  } else {
57  // 如果是信号量拥有者之外的任务wait,则要检查下是否需要使用
58  // 优先级继承方式处理
59  if (currentTask->prio < mutex->owner->prio) {
60  tTask *owner = mutex->owner;
61 
62  // 如果当前任务的优先级比拥有者优先级更高,则使用优先级继承
63  // 提升原拥有者的优先
64  if (owner->state == TINYOS_TASK_STATE_RDY) {
65  // 任务处于就绪状态时,更改任务在就绪表中的位置
66  tTaskSchedUnRdy(owner);
67  owner->prio = currentTask->prio;
68  tTaskSchedRdy(owner);
69  } else {
70  // 其它状态,只需要修改优先级
71  owner->prio = currentTask->prio;
72  }
73  }
74 
75  // 当前任务进入等待队列中
76  tEventWait(&mutex->event, currentTask, (void *) 0, tEventTypeMutex, waitTicks);
77  tTaskExitCritical(status);
78 
79  // 执行调度, 切换至其它任务
80  tTaskSched();
82  }
83  }
84 }
85 
91 uint32_t tMutexNoWaitGet (tMutex *mutex) {
92  uint32_t status = tTaskEnterCritical();
93 
94  if (mutex->lockedCount <= 0) {
95  // 如果没有锁定,则使用当前任务锁定
96  mutex->owner = currentTask;
98  mutex->lockedCount++;
99 
100  tTaskExitCritical(status);
101  return tErrorNoError;
102  } else {
103  // 信号量已经被锁定
104  if (mutex->owner == currentTask) {
105  // 如果是信号量的拥有者再次wait,简单增加计数
106  mutex->lockedCount++;
107 
108  tTaskExitCritical(status);
109  return tErrorNoError;
110  }
111 
112  tTaskExitCritical(status);
114  }
115 }
116 
122 uint32_t tMutexNotify (tMutex *mutex) {
123  uint32_t status = tTaskEnterCritical();
124 
125  if (mutex->lockedCount <= 0) {
126  // 锁定计数为0,信号量未被锁定,直接退出
127  tTaskExitCritical(status);
128  return tErrorNoError;
129  }
130 
131  if (mutex->owner != currentTask) {
132  // 不是拥有者释放,认为是非法
133  tTaskExitCritical(status);
134  return tErrorOwner;
135  }
136 
137  if (--mutex->lockedCount > 0) {
138  // 减1后计数仍不为0, 直接退出,不需要唤醒等待的任务
139  tTaskExitCritical(status);
140  return tErrorNoError;
141  }
142 
143  // 是否有发生优先级继承
144  if (mutex->ownerOriginalPrio != mutex->owner->prio) {
145  // 有发生优先级继承,恢复拥有者的优先级
146  if (mutex->owner->state == TINYOS_TASK_STATE_RDY) {
147  // 任务处于就绪状态时,更改任务在就绪表中的位置
148  tTaskSchedUnRdy(mutex->owner);
150  tTaskSchedRdy(mutex->owner);
151  } else {
152  // 其它状态,只需要修改优先级
154  }
155  }
156 
157  // 检查是否有任务等待
158  if (tEventWaitCount(&mutex->event) > 0) {
159  // 如果有的话,则直接唤醒位于队列首部(最先等待)的任务
160  tTask *task = tEventWakeUp(&mutex->event, (void *) 0, tErrorNoError);
161 
162  mutex->owner = task;
163  mutex->ownerOriginalPrio = task->prio;
164  mutex->lockedCount++;
165 
166  // 如果这个任务的优先级更高,就执行调度,切换过去
167  if (task->prio < currentTask->prio) {
168  tTaskSched();
169  }
170  }
171  tTaskExitCritical(status);
172  return tErrorNoError;
173 }
174 
180 uint32_t tMutexDestroy (tMutex *mutex) {
181  uint32_t count = 0;
182  uint32_t status = tTaskEnterCritical();
183 
184  // 信号量是否已经被锁定,未锁定时没有任务等待,不必处理
185  if (mutex->lockedCount > 0) {
186  // 是否有发生优先级继承?如果发生,需要恢复拥有者的原优先级
187  if (mutex->ownerOriginalPrio != mutex->owner->prio) {
188  // 有发生优先级继承,恢复拥有者的优先级
189  if (mutex->owner->state == TINYOS_TASK_STATE_RDY) {
190  // 任务处于就绪状态时,更改任务在就绪表中的位置
191  tTaskSchedUnRdy(mutex->owner);
192  mutex->owner->prio = mutex->ownerOriginalPrio;
193  tTaskSchedRdy(mutex->owner);
194  } else {
195  // 其它状态,只需要修改优先级
196  mutex->owner->prio = mutex->ownerOriginalPrio;
197  }
198  }
199 
200  // 然后,清空事件控制块中的任务
201  count = tEventRemoveAll(&mutex->event, (void *) 0, tErrorDel);
202 
203  // 清空过程中可能有任务就绪,执行一次调度
204  if (count > 0) {
205  tTaskSched();
206  }
207  }
208 
209  tTaskExitCritical(status);
210  return count;
211 }
212 
218 void tMutexGetInfo (tMutex *mutex, tMutexInfo *info) {
219  uint32_t status = tTaskEnterCritical();
220 
221  // 拷贝需要的信息
222  info->taskCount = tEventWaitCount(&mutex->event);
223  info->ownerPrio = mutex->ownerOriginalPrio;
224  if (mutex->owner != (tTask *) 0) {
225  info->inheritedPrio = mutex->owner->prio;
226  } else {
227  info->inheritedPrio = TINYOS_PRO_COUNT;
228  }
229  info->owner = mutex->owner;
230  info->lockedCount = mutex->lockedCount;
231 
232  tTaskExitCritical(status);
233 }
234 
235 #endif
236 
void tMutexGetInfo(tMutex *mutex, tMutexInfo *info)
Definition: tMutex.c:218
Definition: tTask.h:31
uint32_t inheritedPrio
Definition: tMutex.h:37
uint32_t taskCount
Definition: tMutex.h:34
uint32_t tEventRemoveAll(tEvent *event, void *msg, uint32_t result)
Definition: tEvent.c:163
uint32_t tMutexNotify(tMutex *mutex)
Definition: tMutex.c:122
tTaskCritical_t tTaskEnterCritical(void)
Definition: tSwitch.c:36
uint32_t ownerOriginalPrio
Definition: tMutex.h:29
uint32_t tMutexWait(tMutex *mutex, uint32_t waitTicks)
Definition: tMutex.c:37
tTask * owner
Definition: tMutex.h:28
uint32_t tEventWaitCount(tEvent *event)
Definition: tEvent.c:206
void tTaskSched(void)
任务调度接口。通过它来选择下一个具体的任务,然后切换至该任务运行。
Definition: tCore.c:126
uint32_t lockedCount
Definition: tMutex.h:40
uint32_t ownerPrio
Definition: tMutex.h:36
void tEventInit(tEvent *event, tEventType type)
Definition: tEvent.c:21
void tTaskExitCritical(tTaskCritical_t status)
Definition: tSwitch.c:47
uint32_t prio
Definition: tTask.h:45
void tEventWait(tEvent *event, tTask *task, void *msg, uint32_t state, uint32_t timeout)
Definition: tEvent.c:35
tEvent event
Definition: tMutex.h:25
uint32_t tMutexDestroy(tMutex *mutex)
Definition: tMutex.c:180
tTask * owner
Definition: tMutex.h:39
#define TINYOS_TASK_STATE_RDY
Definition: tTask.h:17
void tTaskSchedRdy(tTask *task)
将任务设置为就绪状态
Definition: tCore.c:93
uint32_t lockedCount
Definition: tMutex.h:27
uint32_t state
Definition: tTask.h:47
tTask * currentTask
当前任务:记录当前是哪个任务正在运行
Definition: tCore.c:17
void tMutexInit(tMutex *mutex)
Definition: tMutex.c:23
uint32_t tMutexNoWaitGet(tMutex *mutex)
Definition: tMutex.c:91
void tTaskSchedUnRdy(tTask *task)
将任务从就绪列表中移除
Definition: tCore.c:102
Definition: tMutex.h:24
tTask * tEventWakeUp(tEvent *event, void *msg, uint32_t result)
Definition: tEvent.c:68
uint32_t waitEventResult
Definition: tTask.h:59