更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
Semaphore
Semaphore 的协作图:

结构体

struct  LosSemCB
 

函数

UINT32 LOS_SemCreate (UINT16 count, UINT32 *semHandle)
 Create a semaphore. 更多...
 
UINT32 LOS_BinarySemCreate (UINT16 count, UINT32 *semHandle)
 Create a binary semaphore. 更多...
 
UINT32 LOS_SemDelete (UINT32 semHandle)
 Delete a semaphore. 更多...
 
UINT32 LOS_SemPend (UINT32 semHandle, UINT32 timeout)
 Request a semaphore. 更多...
 
UINT32 LOS_SemPost (UINT32 semHandle)
 Release a semaphore. 更多...
 

详细描述

函数说明

◆ LOS_BinarySemCreate()

UINT32 LOS_BinarySemCreate ( UINT16  count,
UINT32 semHandle 
)

Create a binary semaphore.

Description:
This API is used to create a binary semaphore control structure according to the initial number of available semaphores specified by count and return the ID of this semaphore control structure.
注意
  • None.
参数
count[IN] Initial number of available semaphores. The value range is [0, 1].
semHandle[OUT] ID of the semaphore control structure that is initialized.
返回值
#LOS_ERRNO_SEM_PTR_NULLThe passed-in semHandle value is NULL.
#LOS_ERRNO_SEM_OVERFLOWThe passed-in count value is greater than the maximum number of available semaphores.
#LOS_ERRNO_SEM_ALL_BUSYNo semaphore control structure is available.
#LOS_OKThe semaphore is successfully created.
Dependency:
  • los_sem.h: the header file that contains the API declaration.
参见
LOS_SemDelete

Create a binary semaphore.

在文件 los_sem.c182 行定义.

183{
184 return OsSemCreate(count, OS_SEM_BINARY_COUNT_MAX, semHandle);
185}
LITE_OS_SEC_TEXT_INIT UINT32 OsSemCreate(UINT16 count, UINT16 maxCount, UINT32 *semHandle)
Definition: los_sem.c:135
函数调用图:
这是这个函数的调用关系图:

◆ LOS_SemCreate()

UINT32 LOS_SemCreate ( UINT16  count,
UINT32 semHandle 
)

Create a semaphore.

Description:
This API is used to create a semaphore control structure according to the initial number of available semaphores specified by count and return the ID of this semaphore control structure.
注意
  • None.
参数
count[IN] Initial number of available semaphores. The value range is [0, OS_SEM_COUNT_MAX].
semHandle[OUT] ID of the semaphore control structure that is initialized.
返回值
#LOS_ERRNO_SEM_PTR_NULLThe passed-in semHandle value is NULL.
#LOS_ERRNO_SEM_OVERFLOWThe passed-in count value is greater than the maximum number of available semaphores.
#LOS_ERRNO_SEM_ALL_BUSYNo semaphore control structure is available.
#LOS_OKThe semaphore is successfully created.
Dependency:
  • los_sem.h: the header file that contains the API declaration.
参见
LOS_SemDelete

Create a semaphore.

在文件 los_sem.c177 行定义.

178{
179 return OsSemCreate(count, OS_SEM_COUNT_MAX, semHandle);
180}
函数调用图:
这是这个函数的调用关系图:

◆ LOS_SemDelete()

UINT32 LOS_SemDelete ( UINT32  semHandle)

Delete a semaphore.

Description:
This API is used to delete a semaphore control structure that has an ID specified by semHandle.
注意
  • The specified sem id must be created first.
参数
semHandle[IN] ID of the semaphore control structure to be deleted. The ID of the semaphore control structure is obtained from semaphore creation.
返回值
#LOS_ERRNO_SEM_INVALIDThe passed-in semHandle value is invalid.
#LOS_ERRNO_SEM_PENDEDThe queue of the tasks that are waiting on the semaphore control structure is not null.
#LOS_OKThe semaphore control structure is successfully deleted.
Dependency:
  • los_sem.h: the header file that contains the API declaration.
参见
LOS_SemCreate

Delete a semaphore.

在文件 los_sem.c187 行定义.

188{
189 UINT32 intSave;
190 LosSemCB *semDeleted = NULL;
191 UINT32 errNo;
192 UINT32 errLine;
193
194 if (GET_SEM_INDEX(semHandle) >= (UINT32)LOSCFG_BASE_IPC_SEM_LIMIT) {
195 OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_INVALID);
196 }
197
198 semDeleted = GET_SEM(semHandle);//通过ID拿到信号量实体
199
200 SCHEDULER_LOCK(intSave);
201
202 if ((semDeleted->semStat == OS_SEM_UNUSED) || (semDeleted->semID != semHandle)) {//参数判断
203 SCHEDULER_UNLOCK(intSave);
204 OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_INVALID);
205 }
206
207 if (!LOS_ListEmpty(&semDeleted->semList)) {//当前还有任务挂在这个信号上面,当然不能删除
208 SCHEDULER_UNLOCK(intSave);
209 OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_PENDED);//这个宏很有意思,里面goto到ERR_HANDLER
210 }
211
212 LOS_ListTailInsert(&g_unusedSemList, &semDeleted->semList);//通过semList从尾部插入空闲链表
213 semDeleted->semStat = OS_SEM_UNUSED;//状态变成了未使用
214 semDeleted->semID = SET_SEM_ID(GET_SEM_COUNT(semDeleted->semID) + 1, GET_SEM_INDEX(semDeleted->semID));//设置ID
215
216 OsHookCall(LOS_HOOK_TYPE_SEM_DELETE, semDeleted);
217 OsSemDbgUpdateHook(semDeleted->semID, NULL, 0);
218
219 SCHEDULER_UNLOCK(intSave);
220 return LOS_OK;
221
222ERR_HANDLER:
223 OS_RETURN_ERROR_P2(errLine, errNo);
224}
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListTailInsert(LOS_DL_LIST *list, LOS_DL_LIST *node)
Insert a node to the tail of a doubly linked list.
Definition: los_list.h:244
LITE_OS_SEC_ALW_INLINE STATIC INLINE BOOL LOS_ListEmpty(LOS_DL_LIST *list)
Identify whether a specified doubly linked list is empty. | 判断链表是否为空
Definition: los_list.h:321
LITE_OS_SEC_DATA_INIT STATIC LOS_DL_LIST g_unusedSemList
可用的信号量列表,干嘛不用freeList? 可以看出这里是另一个人写的代码
Definition: los_sem.c:96
STATIC INLINE VOID OsSemDbgUpdateHook(UINT32 semID, TSK_ENTRY_FUNC creater, UINT16 count)
unsigned int UINT32
Definition: los_typedef.h:57
UINT32 semID
Definition: los_sem_pri.h:51
UINT8 semStat
Definition: los_sem_pri.h:48
LOS_DL_LIST semList
Definition: los_sem_pri.h:52
函数调用图:
这是这个函数的调用关系图:

◆ LOS_SemPend()

UINT32 LOS_SemPend ( UINT32  semHandle,
UINT32  timeout 
)

Request a semaphore.

Description:
This API is used to request a semaphore based on the semaphore control structure ID specified by semHandle and the parameter that specifies the timeout period.
注意
  • The specified sem id must be created first.
  • Do not call this API in software timer callback.
参数
semHandle[IN] ID of the semaphore control structure to be requested. The ID of the semaphore control structure is obtained from semaphore creation.
timeout[IN] Timeout interval for waiting on the semaphore. The value range is [0, 0xFFFFFFFF]. If the value is set to 0, the semaphore is not waited on. If the value is set to 0xFFFFFFFF, the semaphore is waited on forever(unit: Tick).
返回值
#LOS_ERRNO_SEM_INVALIDThe passed-in semHandle value is invalid.
#LOS_ERRNO_SEM_UNAVAILABLEThere is no available semaphore resource.
#LOS_ERRNO_SEM_PEND_INTERRThe API is called during an interrupt, which is forbidden.
#LOS_ERRNO_SEM_PEND_IN_LOCKThe task is unable to request a semaphore because task scheduling is locked.
#LOS_ERRNO_SEM_TIMEOUTThe request for the semaphore times out.
#LOS_OKThe semaphore request succeeds.
Dependency:
  • los_sem.h: the header file that contains the API declaration.
参见
LOS_SemPost | LOS_SemCreate

Request a semaphore.

在文件 los_sem.c226 行定义.

227{
228 UINT32 intSave;
229 LosSemCB *semPended = GET_SEM(semHandle);//通过ID拿到信号体
230 UINT32 retErr = LOS_OK;
231 LosTaskCB *runTask = NULL;
232
233 if (GET_SEM_INDEX(semHandle) >= (UINT32)LOSCFG_BASE_IPC_SEM_LIMIT) {
234 OS_RETURN_ERROR(LOS_ERRNO_SEM_INVALID);
235 }
236
237 if (OS_INT_ACTIVE) {
238 PRINT_ERR("!!!LOS_ERRNO_SEM_PEND_INTERR!!!\n");
239 OsBackTrace();
240 return LOS_ERRNO_SEM_PEND_INTERR;
241 }
242
243 runTask = OsCurrTaskGet();//获取当前任务
244 if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
245 OsBackTrace();
246 return LOS_ERRNO_SEM_PEND_IN_SYSTEM_TASK;
247 }
248
249 SCHEDULER_LOCK(intSave);
250
251 if ((semPended->semStat == OS_SEM_UNUSED) || (semPended->semID != semHandle)) {
252 retErr = LOS_ERRNO_SEM_INVALID;
253 goto OUT;
254 }
255
256 /* Update the operate time, no matter the actual Pend success or not */
257 OsSemDbgTimeUpdateHook(semHandle);
258
259 if (semPended->semCount > 0) {//还有资源可用,返回肯定得成功,semCount=0时代表没资源了,task会必须去睡眠了
260 semPended->semCount--;//资源少了一个
261 OsHookCall(LOS_HOOK_TYPE_SEM_PEND, semPended, runTask, timeout);
262 goto OUT;//注意这里 retErr = LOS_OK ,所以返回是OK的
263 } else if (!timeout) {
264 retErr = LOS_ERRNO_SEM_UNAVAILABLE;
265 goto OUT;
266 }
267
268 if (!OsPreemptableInSched()) {//不能申请调度 (不能调度的原因是因为没有持有调度任务自旋锁)
269 PRINT_ERR("!!!LOS_ERRNO_SEM_PEND_IN_LOCK!!!\n");
270 OsBackTrace();
271 retErr = LOS_ERRNO_SEM_PEND_IN_LOCK;
272 goto OUT;
273 }
274
275 OsHookCall(LOS_HOOK_TYPE_SEM_PEND, semPended, runTask, timeout);
276 OsTaskWaitSetPendMask(OS_TASK_WAIT_SEM, semPended->semID, timeout);
277 retErr = runTask->ops->wait(runTask, &semPended->semList, timeout);
278 if (retErr == LOS_ERRNO_TSK_TIMEOUT) {//注意:这里是涉及到task切换的,把自己挂起,唤醒其他task
279 retErr = LOS_ERRNO_SEM_TIMEOUT;
280 }
281
282OUT:
283 SCHEDULER_UNLOCK(intSave);
284 return retErr;
285}
VOID OsBackTrace(VOID)
Kernel backtrace function.
Definition: los_exc.c:1025
STATIC INLINE LosTaskCB * OsCurrTaskGet(VOID)
STATIC INLINE BOOL OsPreemptableInSched(VOID)
STATIC INLINE VOID OsSemDbgTimeUpdateHook(UINT32 semID)
STATIC INLINE VOID OsTaskWaitSetPendMask(UINT16 mask, UINTPTR lockID, UINT32 timeout)
设置事件阻塞掩码,即设置任务的等待事件.
Definition: los_task_pri.h:289
UINT16 semCount
Definition: los_sem_pri.h:49
UINT32(* wait)(LosTaskCB *runTask, LOS_DL_LIST *list, UINT32 timeout)
任务等待
const SchedOps * ops
UINT16 taskStatus
函数调用图:
这是这个函数的调用关系图:

◆ LOS_SemPost()

UINT32 LOS_SemPost ( UINT32  semHandle)

Release a semaphore.

Description:
This API is used to release a semaphore that has a semaphore control structure ID specified by semHandle.
注意
  • The specified sem id must be created first.
参数
semHandle[IN] ID of the semaphore control structure to be released.The ID of the semaphore control structure is obtained from semaphore creation.
返回值
#LOS_ERRNO_SEM_INVALIDThe passed-in semHandle value is invalid.
#LOS_ERRNO_SEM_OVERFLOWThe times of semaphore release exceed the maximum times permitted.
#LOS_OKThe semaphore is successfully released.
Dependency:
  • los_sem.h: the header file that contains the API declaration.
参见
LOS_SemPend | LOS_SemCreate

Release a semaphore.

在文件 los_sem.c315 行定义.

316{
317 UINT32 intSave;
318 UINT32 ret;
319 BOOL needSched = FALSE;
320
321 if (GET_SEM_INDEX(semHandle) >= LOSCFG_BASE_IPC_SEM_LIMIT) {
322 return LOS_ERRNO_SEM_INVALID;
323 }
324 SCHEDULER_LOCK(intSave);
325 ret = OsSemPostUnsafe(semHandle, &needSched);
326 SCHEDULER_UNLOCK(intSave);
327 if (needSched) {//需要调度的情况
328 LOS_MpSchedule(OS_MP_CPU_ALL);//向所有CPU发送调度指令
329 LOS_Schedule();////发起调度
330 }
331
332 return ret;
333}
VOID LOS_Schedule(VOID)
Trigger active task scheduling.
Definition: los_sched.c:469
VOID LOS_MpSchedule(UINT32 target)
Definition: los_mp.c:76
LITE_OS_SEC_TEXT UINT32 OsSemPostUnsafe(UINT32 semHandle, BOOL *needSched)
以不安全的方式释放指定的信号量,所谓不安全指的是不用自旋锁
Definition: los_sem.c:287
size_t BOOL
Definition: los_typedef.h:88
函数调用图:
这是这个函数的调用关系图: