tinyOS  v1.00
tSem.c
Go to the documentation of this file.
1 
14 #include "tSem.h"
15 #include "tinyOS.h"
16 
17 #if !defined(TINYOS_ENABLE_SEM) || TINYOS_ENABLE_SEM == 1
18 
24 void tSemInit (tSem *sem, uint32_t startCount, uint32_t maxCount) {
26 
27  sem->maxCount = maxCount;
28  if (maxCount == 0) {
29  sem->count = startCount;
30  } else {
31  sem->count = (startCount > maxCount) ? maxCount : startCount;
32  }
33 }
34 
41 uint32_t tSemWait (tSem *sem, uint32_t waitTicks) {
42  uint32_t status = tTaskEnterCritical();
43 
44  // 首先检查信号量计数是否大于0
45  if (sem->count > 0) {
46  // 如果大于0的话,消耗掉一个,然后正常退出
47  --sem->count;
48  tTaskExitCritical(status);
49  return tErrorNoError;
50  } else {
51  // 然后将任务插入事件队列中
52  tEventWait(&sem->event, currentTask, (void *) 0, tEventTypeSem, waitTicks);
53  tTaskExitCritical(status);
54 
55  // 最后再执行一次事件调度,以便于切换到其它任务
56  tTaskSched();
57 
58  // 当由于等待超时或者计数可用时,执行会返回到这里,然后取出等待结构
60  }
61 }
62 
68 uint32_t tSemNoWaitGet (tSem *sem) {
69  uint32_t status = tTaskEnterCritical();
70 
71  // 首先检查信号量计数是否大于0
72  if (sem->count > 0) {
73  // 如果大于0的话,消耗掉一个,然后正常退出
74  --sem->count;
75  tTaskExitCritical(status);
76  return tErrorNoError;
77  } else {
78  // 否则,返回资源不可用
79  tTaskExitCritical(status);
81  }
82 }
83 
88 void tSemNotify (tSem *sem) {
89  uint32_t status = tTaskEnterCritical();
90 
91  // 检查是否有任务等待
92  if (tEventWaitCount(&sem->event) > 0) {
93  // 如果有的话,则直接唤醒位于队列首部(最先等待)的任务
94  tTask *task = tEventWakeUp(&sem->event, (void *) 0, tErrorNoError);
95 
96  // 如果这个任务的优先级更高,就执行调度,切换过去
97  if (task->prio < currentTask->prio) {
98  tTaskSched();
99  }
100  } else {
101  // 如果没有任务等待的话,增加计数
102  ++sem->count;
103 
104  // 如果这个计数超过了最大允许的计数,则递减
105  if ((sem->maxCount != 0) && (sem->count > sem->maxCount)) {
106  sem->count = sem->maxCount;
107  }
108  }
109 
110  tTaskExitCritical(status);
111 }
112 
118 void tSemGetInfo (tSem *sem, tSemInfo *info) {
119  uint32_t status = tTaskEnterCritical();
120 
121  // 拷贝需要的信息
122  info->count = sem->count;
123  info->maxCount = sem->maxCount;
124  info->taskCount = tEventWaitCount(&sem->event);
125 
126  tTaskExitCritical(status);
127 }
128 
134 uint32_t tSemDestroy (tSem *sem) {
135  uint32_t status = tTaskEnterCritical();
136 
137  // 清空事件控制块中的任务
138  uint32_t count = tEventRemoveAll(&sem->event, (void *) 0, tErrorDel);
139  sem->count = 0;
140  tTaskExitCritical(status);
141 
142  // 清空过程中可能有任务就绪,执行一次调度
143  if (count > 0) {
144  tTaskSched();
145  }
146  return count;
147 }
148 
149 #endif
150 
Definition: tSem.h:24
uint32_t maxCount
Definition: tSem.h:27
uint32_t taskCount
Definition: tSem.h:34
Definition: tTask.h:31
uint32_t count
Definition: tSem.h:32
uint32_t tEventRemoveAll(tEvent *event, void *msg, uint32_t result)
Definition: tEvent.c:163
void tSemInit(tSem *sem, uint32_t startCount, uint32_t maxCount)
Definition: tSem.c:24
tTaskCritical_t tTaskEnterCritical(void)
Definition: tSwitch.c:36
void tSemGetInfo(tSem *sem, tSemInfo *info)
Definition: tSem.c:118
uint32_t tSemDestroy(tSem *sem)
Definition: tSem.c:134
uint32_t tSemWait(tSem *sem, uint32_t waitTicks)
Definition: tSem.c:41
uint32_t tEventWaitCount(tEvent *event)
Definition: tEvent.c:206
void tTaskSched(void)
任务调度接口。通过它来选择下一个具体的任务,然后切换至该任务运行。
Definition: tCore.c:126
uint32_t tSemNoWaitGet(tSem *sem)
Definition: tSem.c:68
void tEventInit(tEvent *event, tEventType type)
Definition: tEvent.c:21
tEvent event
Definition: tSem.h:25
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
Definition: tSem.h:31
void tSemNotify(tSem *sem)
Definition: tSem.c:88
tTask * currentTask
当前任务:记录当前是哪个任务正在运行
Definition: tCore.c:17
uint32_t count
Definition: tSem.h:26
tTask * tEventWakeUp(tEvent *event, void *msg, uint32_t result)
Definition: tEvent.c:68
uint32_t maxCount
Definition: tSem.h:33
uint32_t waitEventResult
Definition: tTask.h:59