提交 9fed5f28 编写于 作者: 鸿蒙内核源码分析's avatar 鸿蒙内核源码分析

完善互斥量,信号量注解

    百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
    鸿蒙研究站 | http://weharmonyos.com (国内)
              | https://weharmony.github.io (国外)
    oschina | https://my.oschina.net/weharmony
    博客园 | https://www.cnblogs.com/weharmony/
    知乎 | https://www.zhihu.com/people/weharmonyos
    csdn | https://blog.csdn.net/kuangyufei
    51cto | https://harmonyos.51cto.com/column/34
    掘金 | https://juejin.cn/user/756888642000808
    公众号 | 鸿蒙研究站 (weharmonyos)
上级 a7ab4c72
......@@ -272,7 +272,7 @@ STATIC INLINE VOID OsSwtmrDelete(SWTMR_CTRL_S *swtmr)
/* insert to free list */
LOS_ListTailInsert(&g_swtmrFreeList, &swtmr->stSortList.sortLinkNode);//直接插入空闲链表中,回收再利用
swtmr->ucState = OS_SWTMR_STATUS_UNUSED;//又干净着呢
swtmr->uwOwnerPid = 0;//谁拥有这个定时器? 是 0号进程, 0号进程出来了,竟然是虚拟的一个进程.用于这类缓冲使用.
swtmr->uwOwnerPid = 0;//谁拥有这个定时器? 是 0号进程
}
STATIC INLINE VOID OsWakePendTimeSwtmr(Percpu *cpu, UINT64 currTime, SWTMR_CTRL_S *swtmr)
......
......@@ -326,23 +326,23 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsIdleTaskCreate(VOID)
taskInitParam.uwStackSize = LOSCFG_BASE_CORE_TSK_IDLE_STACK_SIZE;//任务栈大小 2K
taskInitParam.pcName = "Idle";//任务名称 叫pcName有点怪怪的,不能换个撒
taskInitParam.usTaskPrio = OS_TASK_PRIORITY_LOWEST;//默认最低优先级 31
taskInitParam.processID = OsGetIdleProcessID();
taskInitParam.processID = OsGetIdleProcessID();//任务的进程ID绑定为空闲进程
#ifdef LOSCFG_KERNEL_SMP
taskInitParam.usCpuAffiMask = CPUID_TO_AFFI_MASK(ArchCurrCpuid());//每个idle任务只在单独的cpu上运行
#endif
ret = LOS_TaskCreateOnly(idleTaskID, &taskInitParam);
LosTaskCB *idleTask = OS_TCB_FROM_TID(*idleTaskID);
idleTask->taskStatus |= OS_TASK_FLAG_SYSTEM_TASK;
OsSchedSetIdleTaskSchedParam(idleTask);
ret = LOS_TaskCreateOnly(idleTaskID, &taskInitParam);//只创建任务,不调度
LosTaskCB *idleTask = OS_TCB_FROM_TID(*idleTaskID);//获取任务实体
idleTask->taskStatus |= OS_TASK_FLAG_SYSTEM_TASK; //标记为系统任务,idle任务是给CPU休息用的,当然是个系统任务
OsSchedSetIdleTaskSchedParam(idleTask);//设置空闲任务的调度参数
return ret;
}
/*
* Description : get id of current running task.
* Description : get id of current running task. | 获取当前CPU正在执行的任务ID
* Return : task id
*/
LITE_OS_SEC_TEXT UINT32 LOS_CurTaskIDGet(VOID)//获取当前任务的ID
LITE_OS_SEC_TEXT UINT32 LOS_CurTaskIDGet(VOID)
{
LosTaskCB *runTask = OsCurrTaskGet();
......@@ -351,7 +351,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_CurTaskIDGet(VOID)//获取当前任务的ID
}
return runTask->taskID;
}
/// 创建指定任务同步信号量
STATIC INLINE UINT32 OsTaskSyncCreate(LosTaskCB *taskCB)
{
#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
......@@ -364,7 +364,7 @@ STATIC INLINE UINT32 OsTaskSyncCreate(LosTaskCB *taskCB)
#endif
return LOS_OK;
}
/// 销毁指定任务同步信号量
STATIC INLINE VOID OsTaskSyncDestroy(UINT32 syncSignal)
{
#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
......@@ -408,7 +408,7 @@ STATIC INLINE UINT32 OsTaskSyncWait(const LosTaskCB *taskCB)
#endif
}
#endif
/// 同步唤醒
STATIC INLINE VOID OsTaskSyncWake(const LosTaskCB *taskCB)
{
#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC
......@@ -417,7 +417,7 @@ STATIC INLINE VOID OsTaskSyncWake(const LosTaskCB *taskCB)
(VOID)taskCB;
#endif
}
///
STATIC VOID OsTaskReleaseHoldLock(LosProcessCB *processCB, LosTaskCB *taskCB)
{
LosMux *mux = NULL;
......@@ -731,7 +731,16 @@ LITE_OS_SEC_TEXT LosTaskCB *OsGetFreeTaskCB(VOID)
return taskCB;
}
///创建任务,并使该任务进入suspend状态,不对该任务进行调度。如果需要调度,可以调用LOS_TaskResume使该任务进入ready状态
/*!
* @brief LOS_TaskCreateOnly
* 创建任务,并使该任务进入suspend状态,不对该任务进行调度。如果需要调度,可以调用LOS_TaskResume使该任务进入ready状态
* @param initParam
* @param taskID
* @return
*
* @see
*/
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreateOnly(UINT32 *taskID, TSK_INIT_PARAM_S *initParam)
{
UINT32 intSave, errRet;
......
......@@ -86,18 +86,18 @@ typedef enum {
* @attention 读写队列分离
*/
typedef struct {
UINT8 *queueHandle; /**< Pointer to a queue handle */ //指向队列句柄的指针
UINT16 queueState; /**< Queue state */ //队列状态
UINT16 queueLen; /**< Queue length */ //队列中消息总数的上限值,由创建时确定,不再改变
UINT16 queueSize; /**< Node size */ //消息节点大小,由创建时确定,不再改变,即定义了每个消息长度的上限.
UINT32 queueID; /**< queueID */ //队列ID
UINT16 queueHead; /**< Node head */ //消息头节点位置(数组下标)
UINT16 queueTail; /**< Node tail */ //消息尾节点位置(数组下标)
UINT16 readWriteableCnt[OS_QUEUE_N_RW]; /**< Count of readable or writable resources, 0:readable, 1:writable */
//队列中可写或可读消息数,0表示可读,1表示可写
LOS_DL_LIST readWriteList[OS_QUEUE_N_RW]; /**< the linked list to be read or written, 0:readlist, 1:writelist */
//挂的都是等待读/写消息的任务链表,0表示读消息的链表,1表示写消息的任务链表
LOS_DL_LIST memList; /**< Pointer to the memory linked list */ //@note_why 这里尚未搞明白是啥意思 ,是共享内存吗?
UINT8 *queueHandle; /**< Pointer to a queue handle | 队列消息内存空间的指针*/
UINT16 queueState; /**< Queue state | 队列状态*/
UINT16 queueLen; /**< Queue length | 队列中消息节点个数,即队列长度,由创建时确定,不再改变*/
UINT16 queueSize; /**< Node size | 消息节点大小,由创建时确定,不再改变,即定义了每个消息长度的上限.*/
UINT32 queueID; /**< queueID | 队列ID*/
UINT16 queueHead; /**< Node head | 消息头节点位置(数组下标)*/
UINT16 queueTail; /**< Node tail | 消息尾节点位置(数组下标)*/
UINT16 readWriteableCnt[OS_QUEUE_N_RW]; /**< Count of readable or writable resources, 0:readable, 1:writable
| 队列中可写或可读消息数,0表示可读,1表示可写*/
LOS_DL_LIST readWriteList[OS_QUEUE_N_RW]; /**< the linked list to be read or written, 0:readlist, 1:writelist
| 挂的都是等待读/写消息的任务链表,0表示读消息的链表,1表示写消息的任务链表*/
LOS_DL_LIST memList; /**< Pointer to the memory linked list | 内存块链表*/
} LosQueueCB;
/* queue state */
......@@ -105,13 +105,13 @@ typedef struct {
* @ingroup los_queue
* Message queue state: not in use.
*/
#define OS_QUEUE_UNUSED 0 //队列没有使用
#define OS_QUEUE_UNUSED 0 ///< 队列没有使用
/**
* @ingroup los_queue
* Message queue state: used.
*/
#define OS_QUEUE_INUSED 1 //队列被使用
#define OS_QUEUE_INUSED 1 ///< 队列被使用
/**
* @ingroup los_queue
......
......@@ -49,7 +49,7 @@ typedef struct {
UINT16 semCount; /**< Number of available semaphores | 有效信号量的数量 */
UINT16 maxSemCount; /**< Max number of available semaphores | 有效信号量的最大数量 */
UINT32 semID; /**< Semaphore control structure ID | 信号量索引号 */
LOS_DL_LIST semList; /**< Queue of tasks that are waiting on a semaphore | 等待信号量的任务队列,任务通过阻塞节点挂上去 */
LOS_DL_LIST semList; /**< Queue of tasks that are waiting on a semaphore | 挂接阻塞于该信号量的任务 */
} LosSemCB;
/**
......
/*!
* @file los_mux.c
* @brief
* @link kernel-mini-basic-ipc-mutex-guide http://weharmonyos.com/openharmony/zh-cn/device-dev/kernel/kernel-mini-basic-ipc-mutex-guide.html @endlink
@verbatim
基本概念
互斥锁又称互斥型信号量,是一种特殊的二值性信号量,用于实现对共享资源的独占式处理。
任意时刻互斥锁的状态只有两种,开锁或闭锁。当有任务持有时,互斥锁处于闭锁状态,这个任务获得该互斥锁的所有权。
当该任务释放它时,该互斥锁被开锁,任务失去该互斥锁的所有权。当一个任务持有互斥锁时,其他任务将不能再对该互斥锁进行开锁或持有。
多任务环境下往往存在多个任务竞争同一共享资源的应用场景,互斥锁可被用于对共享资源的保护从而实现独占式访问。
另外互斥锁可以解决信号量存在的优先级翻转问题。
运作机制
多任务环境下会存在多个任务访问同一公共资源的场景,而有些公共资源是非共享的临界资源,
只能被独占使用。互斥锁怎样来避免这种冲突呢?
用互斥锁处理临界资源的同步访问时,如果有任务访问该资源,则互斥锁为加锁状态。此时其他任务
如果想访问这个临界资源则会被阻塞,直到互斥锁被持有该锁的任务释放后,其他任务才能重新访问
该公共资源,此时互斥锁再次上锁,如此确保同一时刻只有一个任务正在访问这个临界资源,保证了
临界资源操作的完整性。
使用场景
多任务环境下往往存在多个任务竞争同一临界资源的应用场景,互斥锁可以提供任务间的互斥机制,
防止两个任务在同一时刻访问相同的临界资源,从而实现独占式访问。
申请互斥锁有三种模式:无阻塞模式、永久阻塞模式、定时阻塞模式。
无阻塞模式:任务需要申请互斥锁,若该互斥锁当前没有任务持有,或者持有该互斥锁的任务和申请
该互斥锁的任务为同一个任务,则申请成功。
永久阻塞模式:任务需要申请互斥锁,若该互斥锁当前没有被占用,则申请成功。否则,该任务进入阻塞态,
系统切换到就绪任务中优先级高者继续执行。任务进入阻塞态后,直到有其他任务释放该互斥锁,阻塞任务才会重新得以执行。
定时阻塞模式:任务需要申请互斥锁,若该互斥锁当前没有被占用,则申请成功。否则该任务进入阻塞态,
系统切换到就绪任务中优先级高者继续执行。任务进入阻塞态后,指定时间超时前有其他任务释放该互斥锁,
或者用户指定时间超时后,阻塞任务才会重新得以执行。
释放互斥锁:
如果有任务阻塞于该互斥锁,则唤醒被阻塞任务中优先级最高的,该任务进入就绪态,并进行任务调度。
如果没有任务阻塞于该互斥锁,则互斥锁释放成功。
互斥锁典型场景的开发流程:
通过make menuconfig配置互斥锁模块。
创建互斥锁LOS_MuxCreate。
申请互斥锁LOS_MuxPend。
释放互斥锁LOS_MuxPost。
删除互斥锁LOS_MuxDelete。
@endverbatim
* @image html https://gitee.com/weharmonyos/resources/raw/master/27/mux.png
* @attention 两个任务不能对同一把互斥锁加锁。如果某任务对已被持有的互斥锁加锁,则该任务会被挂起,直到持有该锁的任务对互斥锁解锁,才能执行对这把互斥锁的加锁操作。
\n 互斥锁不能在中断服务程序中使用。
\n LiteOS-M内核作为实时操作系统需要保证任务调度的实时性,尽量避免任务的长时间阻塞,因此在获得互斥锁之后,应该尽快释放互斥锁。
\n 持有互斥锁的过程中,不得再调用LOS_TaskPriSet等接口更改持有互斥锁任务的优先级。
* @version
* @author weharmonyos.com
* @date 2021-11-18
*/
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
......@@ -37,60 +90,6 @@
#include "los_exc.h"
#include "los_sched_pri.h"
/**
* @file los_mux.c
* @brief
* @verbatim
基本概念
互斥锁又称互斥型信号量,是一种特殊的二值性信号量,用于实现对临界资源的独占式处理。
另外,互斥锁可以解决信号量存在的优先级翻转问题。
任意时刻互斥锁只有两种状态,开锁或闭锁。当任务持有时,这个任务获得该互斥锁的所有权,
互斥锁处于闭锁状态。当该任务释放锁后,任务失去该互斥锁的所有权,互斥锁处于开锁状态。
当一个任务持有互斥锁时,其他任务不能再对该互斥锁进行开锁或持有。
互斥锁具有特点
通过优先级继承算法,解决优先级翻转问题。
多任务阻塞等待同一个锁的场景,支持基于任务优先级等待和FIFO两种模式。
运作机制
多任务环境下会存在多个任务访问同一公共资源的场景,而有些公共资源是非共享的临界资源,
只能被独占使用。互斥锁怎样来避免这种冲突呢?
用互斥锁处理临界资源的同步访问时,如果有任务访问该资源,则互斥锁为加锁状态。此时其他任务
如果想访问这个临界资源则会被阻塞,直到互斥锁被持有该锁的任务释放后,其他任务才能重新访问
该公共资源,此时互斥锁再次上锁,如此确保同一时刻只有一个任务正在访问这个临界资源,保证了
临界资源操作的完整性。
使用场景
多任务环境下往往存在多个任务竞争同一临界资源的应用场景,互斥锁可以提供任务间的互斥机制,
防止两个任务在同一时刻访问相同的临界资源,从而实现独占式访问。
申请互斥锁有三种模式:无阻塞模式、永久阻塞模式、定时阻塞模式。
无阻塞模式:即任务申请互斥锁时,入参timeout等于0。若当前没有任务持有该互斥锁,
或者持有该互斥锁的任务和申请该互斥锁的任务为同一个任务,则申请成功,否则立即返回申请失败。
永久阻塞模式:即任务申请互斥锁时,入参timeout等于0xFFFFFFFF。若当前没有任务持有该互斥锁,
则申请成功。否则,任务进入阻塞态,系统切换到就绪任务中优先级最高者继续执行。任务进入阻塞态后,
直到有其他任务释放该互斥锁,阻塞任务才会重新得以执行。
定时阻塞模式:即任务申请互斥锁时,0<timeout<0xFFFFFFFF。若当前没有任务持有该互斥锁,则申请成功。
否则该任务进入阻塞态,系统切换到就绪任务中优先级最高者继续执行。任务进入阻塞态后,超时前如果
有其他任务释放该互斥锁,则该任务可成功获取互斥锁继续执行,若超时前未获取到该互斥锁,接口将返回超时错误码。 释放互斥锁:
如果有任务阻塞于该互斥锁,则唤醒被阻塞任务中优先级最高的,该任务进入就绪态,并进行任务调度。
如果没有任务阻塞于该互斥锁,则互斥锁释放成功。
互斥锁开发流程
通过make menuconfig配置互斥锁模块。
创建互斥锁LOS_MuxCreate。
申请互斥锁LOS_MuxPend。
释放互斥锁LOS_MuxPost。
删除互斥锁LOS_MuxDelete。
注意事项
互斥锁不能在中断服务程序中使用。
Huawei LiteOS作为实时操作系统需要保证任务调度的实时性,尽量避免任务的长时间阻塞,因此在获得互斥锁之后,应该尽快释放互斥锁。
持有互斥锁的过程中,不得再调用LOS_TaskPriSet等接口更改持有互斥锁任务的优先级。
互斥锁不支持多个相同优先级任务翻转的场景。
* @endverbatim
*/
#ifdef LOSCFG_BASE_IPC_MUX
#define MUTEXATTR_TYPE_MASK 0x0FU
......@@ -512,8 +511,18 @@ STATIC VOID OsMuxPostOpSub(LosTaskCB *taskCB, LosMux *mutex)
LOS_BitmapClr(&taskCB->priBitMap, bitMapPri);//把taskCB已知的最高优先级记录位清0,实际等于降低了taskCB优先级的上限
(VOID)OsSchedModifyTaskSchedParam((LosTaskCB *)mutex->owner, ((LosTaskCB *)mutex->owner)->policy, bitMapPri);
}
///是否有其他任务持有互斥锁而处于阻塞状,如果是就要唤醒它,注意唤醒一个任务的操作是由别的任务完成的
//OsMuxPostOp只由OsMuxUnlockUnsafe,参数任务归还锁了,自然就会遇到锁要给谁用的问题, 因为很多任务在申请锁,由OsMuxPostOp来回答这个问题
/*!
* @brief OsMuxPostOp
* 是否有其他任务持有互斥锁而处于阻塞状,如果是就要唤醒它,注意唤醒一个任务的操作是由别的任务完成的
* OsMuxPostOp只由OsMuxUnlockUnsafe,参数任务归还锁了,自然就会遇到锁要给谁用的问题, 因为很多任务在申请锁,由OsMuxPostOp来回答这个问题
* @param mutex
* @param needSched
* @param taskCB
* @return
*
* @see
*/
STATIC UINT32 OsMuxPostOp(LosTaskCB *taskCB, LosMux *mutex, BOOL *needSched)
{
LosTaskCB *resumedTask = NULL;
......
/*!
* @file los_sem.c
* @brief
* @link kernel-mini-basic-ipc-sem-basic http://weharmonyos.com/openharmony/zh-cn/device-dev/kernel/kernel-mini-basic-ipc-sem-basic.html @endlink
@verbatim
信号量(Semaphore)是一种实现任务间通信的机制,可以实现任务间同步或共享资源的互斥访问。
一个信号量的数据结构中,通常有一个计数值,用于对有效资源数的计数,表示剩下的可被使用的共享资源数,其值的含义分两种情况:
0,表示该信号量当前不可获取,因此可能存在正在等待该信号量的任务。
正值,表示该信号量当前可被获取。
以同步为目的的信号量和以互斥为目的的信号量在使用上有如下不同:
用作互斥时,初始信号量计数值不为0,表示可用的共享资源个数。在需要使用共享资源前,先获取信号量,
然后使用一个共享资源,使用完毕后释放信号量。这样在共享资源被取完,即信号量计数减至0时,其他需要获取信号量的任务将被阻塞,
从而保证了共享资源的互斥访问。另外,当共享资源数为1时,建议使用二值信号量,一种类似于互斥锁的机制。
用作同步时,初始信号量计数值为0。任务1获取信号量而阻塞,直到任务2或者某中断释放信号量,任务1才得以进入Ready或Running态,从而达到了任务间的同步。
信号量运作原理
信号量初始化,为配置的N个信号量申请内存(N值可以由用户自行配置,通过LOSCFG_BASE_IPC_SEM_LIMIT宏实现),并把所有信号量初始化成未使用,
加入到未使用链表中供系统使用。
信号量创建,从未使用的信号量链表中获取一个信号量,并设定初值。
信号量申请,若其计数器值大于0,则直接减1返回成功。否则任务阻塞,等待其它任务释放该信号量,等待的超时时间可设定。
当任务被一个信号量阻塞时,将该任务挂到信号量等待任务队列的队尾。
信号量释放,若没有任务等待该信号量,则直接将计数器加1返回。否则唤醒该信号量等待任务队列上的第一个任务。
信号量删除,将正在使用的信号量置为未使用信号量,并挂回到未使用链表。
信号量允许多个任务在同一时刻访问共享资源,但会限制同一时刻访问此资源的最大任务数目。当访问资源的任务数达到该资源允许的最大数量时,
会阻塞其他试图获取该资源的任务,直到有任务释放该信号量。
开发流程
创建信号量LOS_SemCreate,若要创建二值信号量则调用LOS_BinarySemCreate。
申请信号量LOS_SemPend。
释放信号量LOS_SemPost。
删除信号量LOS_SemDelete。
@endverbatim
* @image html https://gitee.com/weharmonyos/resources/raw/master/29/sem_run.png
* @attention 由于中断不能被阻塞,因此不能在中断中使用阻塞模式申请信号量。
* @version
* @author weharmonyos.com
* @date 2021-11-18
*/
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
......@@ -39,61 +85,7 @@
#include "los_mp.h"
#include "los_percpu_pri.h"
#include "los_hook.h"
/**
* @file los_sem.c
* @brief
* @verbatim
基本概念
信号量(Semaphore)是一种实现任务间通信的机制,可以实现任务间同步或共享资源的互斥访问。
一个信号量的数据结构中,通常有一个计数值,用于对有效资源数的计数,表示剩下的可被使用的共享资源数,其值的含义分两种情况:
0,表示该信号量当前不可获取,因此可能存在正在等待该信号量的任务。
正值,表示该信号量当前可被获取。
以同步为目的的信号量和以互斥为目的的信号量在使用上有如下不同:
用作互斥时,初始信号量计数值不为0,表示可用的共享资源个数。在需要使用共享资源前,先获取信号量,
然后使用一个共享资源,使用完毕后释放信号量。这样在共享资源被取完,即信号量计数减至0时,其他
需要获取信号量的任务将被阻塞,从而保证了共享资源的互斥访问。另外,当共享资源数为1时,
建议使用二值信号量,一种类似于互斥锁的机制。
用作同步时,初始信号量计数值为0。任务1获取信号量而阻塞,直到任务2或者某中断释放信号量,
任务1才得以进入Ready或Running态,从而达到了任务间的同步。
信号量运作原理
信号量初始化,为配置的N个信号量申请内存(N值可以由用户自行配置,通过LOSCFG_BASE_IPC_SEM_LIMIT宏实现),
并把所有信号量初始化成未使用,加入到未使用链表中供系统使用。
信号量创建,从未使用的信号量链表中获取一个信号量,并设定初值。
信号量申请,若其计数器值大于0,则直接减1返回成功。否则任务阻塞,等待其它任务释放该信号量,
等待的超时时间可设定。当任务被一个信号量阻塞时,将该任务挂到信号量等待任务队列的队尾。
信号量释放,若没有任务等待该信号量,则直接将计数器加1返回。否则唤醒该信号量等待任务队列上的第一个任务。
信号量删除,将正在使用的信号量置为未使用信号量,并挂回到未使用链表。
信号量允许多个任务在同一时刻访问共享资源,但会限制同一时刻访问此资源的最大任务数目。
当访问资源的任务数达到该资源允许的最大数量时,会阻塞其他试图获取该资源的任务,直到有任务释放该信号量。
使用场景
在多任务系统中,信号量是一种非常灵活的同步方式,可以运用在多种场合中,实现锁、同步、资源计数等功能,
也能方便的用于任务与任务,中断与任务的同步中。信号量常用于协助一组相互竞争的任务访问共享资源。
信号量有三种申请模式:无阻塞模式、永久阻塞模式、定时阻塞模式
无阻塞模式:即任务申请信号量时,入参timeout等于0。若当前信号量计数值不为0,则申请成功,否则立即返回申请失败。
永久阻塞模式:即任务申请信号量时,入参timeout等于0xFFFFFFFF。若当前信号量计数值不为0,则申请成功。
否则该任务进入阻塞态,系统切换到就绪任务中优先级最高者继续执行。任务进入阻塞态后,直到有其他任务释放该信号量,
阻塞任务才会重新得以执行。
定时阻塞模式:即任务申请信号量时,0<timeout<0xFFFFFFFF。若当前信号量计数值不为0,则申请成功。
否则,该任务进入阻塞态,系统切换到就绪任务中优先级最高者继续执行。任务进入阻塞态后,
超时前如果有其他任务释放该信号量,则该任务可成功获取信号量继续执行,若超时前未获取到信号量,接口将返回超时错误码。
使用流程
通过make menuconfig配置信号量模块
创建信号量LOS_SemCreate,若要创建二值信号量则调用LOS_BinarySemCreate。
申请信号量LOS_SemPend。
释放信号量LOS_SemPost。
删除信号量LOS_SemDelete。
注意事项
由于中断不能被阻塞,因此不能在中断中使用阻塞模式申请信号量。
* @endverbatim
*/
#ifdef LOSCFG_BASE_IPC_SEM
......@@ -113,7 +105,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsSemInit(VOID)
LosSemCB *semNode = NULL;
UINT32 index;
LOS_ListInit(&g_unusedSemList);//初始
LOS_ListInit(&g_unusedSemList);//初始化链表,链表上挂未使用的信号量,用于分配信号量,鸿蒙信号量的个数是有限的,默认1024个
/* system resident memory, don't free */
g_allSem = (LosSemCB *)LOS_MemAlloc(m_aucSysMem0, (LOSCFG_BASE_IPC_SEM_LIMIT * sizeof(LosSemCB)));//分配信号池
if (g_allSem == NULL) {
......@@ -186,12 +178,12 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemCreate(UINT16 count, UINT32 *semHandle)
{
return OsSemCreate(count, OS_SEM_COUNT_MAX, semHandle);
}
///对外接口 创建一个最大信号数为1的信号量,可以当互斥锁用
///对外接口 创建二值信号量,其计数值最大为1,可以当互斥锁用
LITE_OS_SEC_TEXT_INIT UINT32 LOS_BinarySemCreate(UINT16 count, UINT32 *semHandle)
{
return OsSemCreate(count, OS_SEM_BINARY_COUNT_MAX, semHandle);
}
///对外接口 删除信号量,参数就是 semID
///对外接口 删除指定的信号量,参数就是 semID
LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemDelete(UINT32 semHandle)
{
UINT32 intSave;
......@@ -230,7 +222,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemDelete(UINT32 semHandle)
ERR_HANDLER:
OS_RETURN_ERROR_P2(errLine, errNo);
}
///对外接口 等待信号量
///对外接口 申请指定的信号量,并设置超时时间
LITE_OS_SEC_TEXT UINT32 LOS_SemPend(UINT32 semHandle, UINT32 timeout)
{
UINT32 intSave;
......@@ -291,7 +283,7 @@ OUT:
SCHEDULER_UNLOCK(intSave);
return retErr;
}
///释放信号
///以不安全的方式释放指定的信号量,所谓不安全指的是不用自旋锁
LITE_OS_SEC_TEXT UINT32 OsSemPostUnsafe(UINT32 semHandle, BOOL *needSched)
{
LosSemCB *semPosted = NULL;
......@@ -321,7 +313,7 @@ LITE_OS_SEC_TEXT UINT32 OsSemPostUnsafe(UINT32 semHandle, BOOL *needSched)
OsHookCall(LOS_HOOK_TYPE_SEM_POST, semPosted, resumedTask);
return LOS_OK;
}
///对外接口 释放信号量
///对外接口 释放指定的信号量
LITE_OS_SEC_TEXT UINT32 LOS_SemPost(UINT32 semHandle)
{
UINT32 intSave;
......
git add -A
git commit -m ' CPU核间通讯注解, 多个CPU之间是如何通讯的 ?
git commit -m ' 完善互斥量,信号量注解
百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
鸿蒙研究站 | http://weharmonyos.com (国内)
| https://weharmony.github.io (国外)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册