更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
los_mux.c 文件参考

http://weharmonyos.com/openharmony/zh-cn/device-dev/kernel/kernel-mini-basic-ipc-mutex-guide.html 更多...

浏览源代码.

函数

LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrInit (LosMuxAttr *attr)
 互斥属性初始化 更多...
 
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrDestroy (LosMuxAttr *attr)
 ????? 销毁互斥属 ,这里啥也没干呀 更多...
 
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrGetType (const LosMuxAttr *attr, INT32 *outType)
 获取互斥锁的类型属性,由outType接走,不送! 更多...
 
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrSetType (LosMuxAttr *attr, INT32 type)
 设置互斥锁的类型属性
更多...
 
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrGetProtocol (const LosMuxAttr *attr, INT32 *protocol)
 获取互斥锁的类型属性 更多...
 
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrSetProtocol (LosMuxAttr *attr, INT32 protocol)
 设置互斥锁属性的协议 更多...
 
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrGetPrioceiling (const LosMuxAttr *attr, INT32 *prioceiling)
 获取互斥锁属性优先级 更多...
 
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrSetPrioceiling (LosMuxAttr *attr, INT32 prioceiling)
 设置互斥锁属性的优先级的上限 更多...
 
LITE_OS_SEC_TEXT UINT32 LOS_MuxSetPrioceiling (LosMux *mutex, INT32 prioceiling, INT32 *oldPrioceiling)
 设置互斥锁的优先级的上限,老优先级由oldPrioceiling带走 更多...
 
LITE_OS_SEC_TEXT UINT32 LOS_MuxGetPrioceiling (const LosMux *mutex, INT32 *prioceiling)
 获取互斥锁的优先级的上限 更多...
 
LITE_OS_SEC_TEXT BOOL LOS_MuxIsValid (const LosMux *mutex)
 互斥锁是否有效 更多...
 
STATIC UINT32 OsCheckMutexAttr (const LosMuxAttr *attr)
 检查互斥锁属性是否OK,否则 no ok :|) 更多...
 
LITE_OS_SEC_TEXT UINT32 LOS_MuxInit (LosMux *mutex, const LosMuxAttr *attr)
 初始化互斥锁 更多...
 
LITE_OS_SEC_TEXT UINT32 LOS_MuxDestroy (LosMux *mutex)
 销毁互斥锁 更多...
 
STATIC VOID OsMuxBitmapSet (const LosMux *mutex, const LosTaskCB *runTask)
 设置互斥锁位图 更多...
 
VOID OsMuxBitmapRestore (const LosMux *mutex, const LOS_DL_LIST *list, const LosTaskCB *runTask)
 恢复互斥锁位图 更多...
 
STATIC UINT32 OsMuxPendOp (LosTaskCB *runTask, LosMux *mutex, UINT32 timeout)
 最坏情况就是拿锁失败,让出CPU,变成阻塞任务,等别的任务释放锁后排到自己了接着执行. 更多...
 
UINT32 OsMuxLockUnsafe (LosMux *mutex, UINT32 timeout)
 
UINT32 OsMuxTrylockUnsafe (LosMux *mutex, UINT32 timeout)
 尝试加锁, 更多...
 
LITE_OS_SEC_TEXT UINT32 LOS_MuxLock (LosMux *mutex, UINT32 timeout)
 拿互斥锁, 更多...
 
LITE_OS_SEC_TEXT UINT32 LOS_MuxTrylock (LosMux *mutex)
 尝试要锁,没拿到也不等,直接返回,不纠结 更多...
 
STATIC UINT32 OsMuxPostOp (LosTaskCB *taskCB, LosMux *mutex, BOOL *needSched)
 OsMuxPostOp
是否有其他任务持有互斥锁而处于阻塞状,如果是就要唤醒它,注意唤醒一个任务的操作是由别的任务完成的 OsMuxPostOp只由OsMuxUnlockUnsafe,参数任务归还锁了,自然就会遇到锁要给谁用的问题, 因为很多任务在申请锁,由OsMuxPostOp来回答这个问题 更多...
 
UINT32 OsMuxUnlockUnsafe (LosTaskCB *taskCB, LosMux *mutex, BOOL *needSched)
 
LITE_OS_SEC_TEXT UINT32 LOS_MuxUnlock (LosMux *mutex)
 释放锁 更多...
 

详细描述

http://weharmonyos.com/openharmony/zh-cn/device-dev/kernel/kernel-mini-basic-ipc-mutex-guide.html

基本概念
    互斥锁又称互斥型信号量,是一种特殊的二值性信号量,用于实现对共享资源的独占式处理。
    任意时刻互斥锁的状态只有两种,开锁或闭锁。当有任务持有时,互斥锁处于闭锁状态,这个任务获得该互斥锁的所有权。
    当该任务释放它时,该互斥锁被开锁,任务失去该互斥锁的所有权。当一个任务持有互斥锁时,其他任务将不能再对该互斥锁进行开锁或持有。
    多任务环境下往往存在多个任务竞争同一共享资源的应用场景,互斥锁可被用于对共享资源的保护从而实现独占式访问。
    另外互斥锁可以解决信号量存在的优先级翻转问题。

运作机制
    多任务环境下会存在多个任务访问同一公共资源的场景,而有些公共资源是非共享的临界资源,
    只能被独占使用。互斥锁怎样来避免这种冲突呢?
    用互斥锁处理临界资源的同步访问时,如果有任务访问该资源,则互斥锁为加锁状态。此时其他任务
    如果想访问这个临界资源则会被阻塞,直到互斥锁被持有该锁的任务释放后,其他任务才能重新访问
    该公共资源,此时互斥锁再次上锁,如此确保同一时刻只有一个任务正在访问这个临界资源,保证了
    临界资源操作的完整性。

使用场景
    多任务环境下往往存在多个任务竞争同一临界资源的应用场景,互斥锁可以提供任务间的互斥机制,
    防止两个任务在同一时刻访问相同的临界资源,从而实现独占式访问。

申请互斥锁有三种模式:无阻塞模式、永久阻塞模式、定时阻塞模式。
    无阻塞模式:任务需要申请互斥锁,若该互斥锁当前没有任务持有,或者持有该互斥锁的任务和申请
            该互斥锁的任务为同一个任务,则申请成功。
    永久阻塞模式:任务需要申请互斥锁,若该互斥锁当前没有被占用,则申请成功。否则,该任务进入阻塞态,
            系统切换到就绪任务中优先级高者继续执行。任务进入阻塞态后,直到有其他任务释放该互斥锁,阻塞任务才会重新得以执行。
    定时阻塞模式:任务需要申请互斥锁,若该互斥锁当前没有被占用,则申请成功。否则该任务进入阻塞态,
            系统切换到就绪任务中优先级高者继续执行。任务进入阻塞态后,指定时间超时前有其他任务释放该互斥锁,
            或者用户指定时间超时后,阻塞任务才会重新得以执行。 
    释放互斥锁:
        如果有任务阻塞于该互斥锁,则唤醒被阻塞任务中优先级最高的,该任务进入就绪态,并进行任务调度。
        如果没有任务阻塞于该互斥锁,则互斥锁释放成功。

互斥锁典型场景的开发流程:
    通过make menuconfig配置互斥锁模块。
    创建互斥锁LOS_MuxCreate。
    申请互斥锁LOS_MuxPend。
    释放互斥锁LOS_MuxPost。
    删除互斥锁LOS_MuxDelete。
注意
两个任务不能对同一把互斥锁加锁。如果某任务对已被持有的互斥锁加锁,则该任务会被挂起,直到持有该锁的任务对互斥锁解锁,才能执行对这把互斥锁的加锁操作。
互斥锁不能在中断服务程序中使用。
LiteOS-M内核作为实时操作系统需要保证任务调度的实时性,尽量避免任务的长时间阻塞,因此在获得互斥锁之后,应该尽快释放互斥锁。
持有互斥锁的过程中,不得再调用LOS_TaskPriSet等接口更改持有互斥锁任务的优先级。
版本
作者
weharmonyos.com | 鸿蒙研究站 | 每天死磕一点点
日期
2021-11-18

在文件 los_mux.c 中定义.

函数说明

◆ LOS_MuxAttrDestroy()

LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrDestroy ( LosMuxAttr attr)

????? 销毁互斥属 ,这里啥也没干呀

在文件 los_mux.c109 行定义.

110{
111 if (attr == NULL) {
112 return LOS_EINVAL;
113 }
114
115 return LOS_OK;
116}
这是这个函数的调用关系图:

◆ LOS_MuxAttrGetPrioceiling()

LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrGetPrioceiling ( const LosMuxAttr attr,
INT32 prioceiling 
)

获取互斥锁属性优先级

在文件 los_mux.c174 行定义.

175{
176 if (attr == NULL) {
177 return LOS_EINVAL;
178 }
179
180 if (prioceiling != NULL) {
181 *prioceiling = attr->prioceiling;
182 }
183
184 return LOS_OK;
185}
UINT8 prioceiling
优先级上限
Definition: los_mux.h:64
这是这个函数的调用关系图:

◆ LOS_MuxAttrGetProtocol()

LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrGetProtocol ( const LosMuxAttr attr,
INT32 protocol 
)

获取互斥锁的类型属性

在文件 los_mux.c146 行定义.

147{
148 if ((attr != NULL) && (protocol != NULL)) {
149 *protocol = attr->protocol;
150 } else {
151 return LOS_EINVAL;
152 }
153
154 return LOS_OK;
155}
UINT8 protocol
协议
Definition: los_mux.h:63
这是这个函数的调用关系图:

◆ LOS_MuxAttrGetType()

LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrGetType ( const LosMuxAttr attr,
INT32 outType 
)

获取互斥锁的类型属性,由outType接走,不送!

在文件 los_mux.c118 行定义.

119{
120 INT32 type;
121
122 if ((attr == NULL) || (outType == NULL)) {
123 return LOS_EINVAL;
124 }
125
126 type = (INT32)(attr->type & MUTEXATTR_TYPE_MASK);
127 if ((type < LOS_MUX_NORMAL) || (type > LOS_MUX_ERRORCHECK)) {
128 return LOS_EINVAL;
129 }
130
131 *outType = type;
132
133 return LOS_OK;
134}
@ LOS_MUX_ERRORCHECK
进行错误检查,如果一个线程企图对一个已经锁住的mutex进行relock或对未加锁的unlock,将返回一个错误。
Definition: los_mux.h:58
@ LOS_MUX_NORMAL
非递归锁 只有[0.1]两个状态,不做任何特殊的错误检,不进行deadlock detection(死锁检测)
Definition: los_mux.h:56
signed int INT32
Definition: los_typedef.h:60
UINT8 type
类型属性
Definition: los_mux.h:65
这是这个函数的调用关系图:

◆ LOS_MuxAttrInit()

LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrInit ( LosMuxAttr attr)

互斥属性初始化

在文件 los_mux.c97 行定义.

98{
99 if (attr == NULL) {
100 return LOS_EINVAL;
101 }
102
103 attr->protocol = LOS_MUX_PRIO_INHERIT; //协议默认用继承方式, A(4)task等B(19)释放锁时,B的调度优先级直接升到(4)
104 attr->prioceiling = OS_TASK_PRIORITY_LOWEST;//最低优先级
105 attr->type = LOS_MUX_DEFAULT; //默认 LOS_MUX_RECURSIVE
106 return LOS_OK;
107}
@ LOS_MUX_DEFAULT
Definition: los_mux.h:59
@ LOS_MUX_PRIO_INHERIT
Definition: los_mux.h:50
这是这个函数的调用关系图:

◆ LOS_MuxAttrSetPrioceiling()

LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrSetPrioceiling ( LosMuxAttr attr,
INT32  prioceiling 
)

设置互斥锁属性的优先级的上限

在文件 los_mux.c187 行定义.

188{
189 if ((attr == NULL) ||
190 (prioceiling < OS_TASK_PRIORITY_HIGHEST) ||
191 (prioceiling > OS_TASK_PRIORITY_LOWEST)) {
192 return LOS_EINVAL;
193 }
194
195 attr->prioceiling = (UINT8)prioceiling;
196
197 return LOS_OK;
198}
unsigned char UINT8
Definition: los_typedef.h:55
这是这个函数的调用关系图:

◆ LOS_MuxAttrSetProtocol()

LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrSetProtocol ( LosMuxAttr attr,
INT32  protocol 
)

设置互斥锁属性的协议

在文件 los_mux.c157 行定义.

158{
159 if (attr == NULL) {
160 return LOS_EINVAL;
161 }
162
163 switch (protocol) {
167 attr->protocol = (UINT8)protocol;
168 return LOS_OK;
169 default:
170 return LOS_EINVAL;
171 }
172}
@ LOS_MUX_PRIO_PROTECT
详见: OsMuxPendOp 中的注解,详细说明了LOS_MUX_PRIO_PROTECT的含义
Definition: los_mux.h:52
@ LOS_MUX_PRIO_NONE
线程的优先级和调度不会受到互斥锁影响,先来后到,普通排队.
Definition: los_mux.h:49
这是这个函数的调用关系图:

◆ LOS_MuxAttrSetType()

LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrSetType ( LosMuxAttr attr,
INT32  type 
)

设置互斥锁的类型属性

在文件 los_mux.c136 行定义.

137{
138 if ((attr == NULL) || (type < LOS_MUX_NORMAL) || (type > LOS_MUX_ERRORCHECK)) {
139 return LOS_EINVAL;
140 }
141
142 attr->type = (UINT8)((attr->type & ~MUTEXATTR_TYPE_MASK) | (UINT32)type);
143 return LOS_OK;
144}
unsigned int UINT32
Definition: los_typedef.h:57
这是这个函数的调用关系图:

◆ LOS_MuxGetPrioceiling()

LITE_OS_SEC_TEXT UINT32 LOS_MuxGetPrioceiling ( const LosMux mutex,
INT32 prioceiling 
)

获取互斥锁的优先级的上限

在文件 los_mux.c229 行定义.

230{
231 if ((mutex != NULL) && (prioceiling != NULL) && (mutex->magic == OS_MUX_MAGIC)) {
232 *prioceiling = mutex->attr.prioceiling;
233 return LOS_OK;
234 }
235
236 return LOS_EINVAL;
237}
UINT32 magic
Definition: los_mux.h:74
LosMuxAttr attr
Definition: los_mux.h:75
这是这个函数的调用关系图:

◆ LOS_MuxIsValid()

LITE_OS_SEC_TEXT BOOL LOS_MuxIsValid ( const LosMux mutex)

互斥锁是否有效

在文件 los_mux.c239 行定义.

240{
241 if ((mutex != NULL) && (mutex->magic == OS_MUX_MAGIC)) {
242 return TRUE;
243 }
244
245 return FALSE;
246}
这是这个函数的调用关系图:

◆ LOS_MuxSetPrioceiling()

LITE_OS_SEC_TEXT UINT32 LOS_MuxSetPrioceiling ( LosMux mutex,
INT32  prioceiling,
INT32 oldPrioceiling 
)

设置互斥锁的优先级的上限,老优先级由oldPrioceiling带走

在文件 los_mux.c200 行定义.

201{
202 INT32 ret;
203 INT32 retLock;
204 if ((mutex == NULL) ||
205 (prioceiling < OS_TASK_PRIORITY_HIGHEST) ||
206 (prioceiling > OS_TASK_PRIORITY_LOWEST)) {
207 return LOS_EINVAL;
208 }
209
210 retLock = LOS_MuxLock(mutex, LOS_WAIT_FOREVER);
211 if (retLock != LOS_OK) {
212 return retLock;
213 }
214
215 if (oldPrioceiling != NULL) {
216 *oldPrioceiling = mutex->attr.prioceiling;
217 }
218
219 ret = LOS_MuxAttrSetPrioceiling(&mutex->attr, prioceiling);
220
221 retLock = LOS_MuxUnlock(mutex);
222 if ((ret == LOS_OK) && (retLock != LOS_OK)) {
223 return retLock;
224 }
225
226 return ret;
227}
LITE_OS_SEC_TEXT UINT32 LOS_MuxUnlock(LosMux *mutex)
释放锁
Definition: los_mux.c:559
LITE_OS_SEC_TEXT UINT32 LOS_MuxLock(LosMux *mutex, UINT32 timeout)
拿互斥锁,
Definition: los_mux.c:437
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrSetPrioceiling(LosMuxAttr *attr, INT32 prioceiling)
设置互斥锁属性的优先级的上限
Definition: los_mux.c:187
函数调用图:
这是这个函数的调用关系图:

◆ OsCheckMutexAttr()

STATIC UINT32 OsCheckMutexAttr ( const LosMuxAttr attr)

检查互斥锁属性是否OK,否则 no ok :|)

在文件 los_mux.c248 行定义.

249{
250 if (((INT8)(attr->type) < LOS_MUX_NORMAL) || (attr->type > LOS_MUX_ERRORCHECK)) {
251 return LOS_NOK;
252 }
253 if (((INT8)(attr->prioceiling) < OS_TASK_PRIORITY_HIGHEST) || (attr->prioceiling > OS_TASK_PRIORITY_LOWEST)) {
254 return LOS_NOK;
255 }
256 if (((INT8)(attr->protocol) < LOS_MUX_PRIO_NONE) || (attr->protocol > LOS_MUX_PRIO_PROTECT)) {
257 return LOS_NOK;
258 }
259 return LOS_OK;
260}
signed char INT8
Definition: los_typedef.h:58
这是这个函数的调用关系图:

◆ OsMuxBitmapRestore()

VOID OsMuxBitmapRestore ( const LosMux mutex,
const LOS_DL_LIST list,
const LosTaskCB runTask 
)

恢复互斥锁位图

在文件 los_mux.c328 行定义.

329{
330 if (mutex->attr.protocol != LOS_MUX_PRIO_INHERIT) {
331 return;
332 }
333
334 SchedParam param = { 0 };
335 LosTaskCB *owner = (LosTaskCB *)mutex->owner;
336 runTask->ops->schedParamGet(runTask, &param);
337 owner->ops->priorityRestore(owner, list, &param);
338}
VOID * owner
Definition: los_mux.h:78
VOID(* priorityRestore)(LosTaskCB *owner, const LOS_DL_LIST *list, const SchedParam *param)
恢复调度参数
UINT32(* schedParamGet)(const LosTaskCB *taskCB, SchedParam *param)
获取调度参数
const SchedOps * ops
这是这个函数的调用关系图:

◆ OsMuxBitmapSet()

STATIC VOID OsMuxBitmapSet ( const LosMux mutex,
const LosTaskCB runTask 
)

设置互斥锁位图

在文件 los_mux.c313 行定义.

314{
315 if (mutex->attr.protocol != LOS_MUX_PRIO_INHERIT) {
316 return;
317 }
318
319 SchedParam param = { 0 };
320 LosTaskCB *owner = (LosTaskCB *)mutex->owner;
321 INT32 ret = OsSchedParamCompare(owner, runTask);
322 if (ret > 0) {
323 runTask->ops->schedParamGet(runTask, &param);
324 owner->ops->priorityInheritance(owner, &param);
325 }
326}
INT32 OsSchedParamCompare(const LosTaskCB *task1, const LosTaskCB *task2)
Definition: los_sched.c:233
VOID(* priorityInheritance)(LosTaskCB *owner, const SchedParam *param)
函数调用图:
这是这个函数的调用关系图:

◆ OsMuxLockUnsafe()

UINT32 OsMuxLockUnsafe ( LosMux mutex,
UINT32  timeout 
)

在文件 los_mux.c398 行定义.

399{
400 LosTaskCB *runTask = OsCurrTaskGet();//获取当前任务
401
402 if (mutex->magic != OS_MUX_MAGIC) {
403 return LOS_EBADF;
404 }
405
406 if (OsCheckMutexAttr(&mutex->attr) != LOS_OK) {
407 return LOS_EINVAL;
408 }
409 //LOS_MUX_ERRORCHECK 时 muxCount是要等于0 ,当前任务持有锁就不能再lock了. 鸿蒙默认用的是递归锁LOS_MUX_RECURSIVE
410 if ((mutex->attr.type == LOS_MUX_ERRORCHECK) && (mutex->owner == (VOID *)runTask)) {
411 return LOS_EDEADLK;
412 }
413
414 return OsMuxPendOp(runTask, mutex, timeout);
415}
STATIC UINT32 OsMuxPendOp(LosTaskCB *runTask, LosMux *mutex, UINT32 timeout)
最坏情况就是拿锁失败,让出CPU,变成阻塞任务,等别的任务释放锁后排到自己了接着执行.
Definition: los_mux.c:341
STATIC UINT32 OsCheckMutexAttr(const LosMuxAttr *attr)
检查互斥锁属性是否OK,否则 no ok :|)
Definition: los_mux.c:248
STATIC INLINE LosTaskCB * OsCurrTaskGet(VOID)
函数调用图:
这是这个函数的调用关系图:

◆ OsMuxPendOp()

STATIC UINT32 OsMuxPendOp ( LosTaskCB runTask,
LosMux mutex,
UINT32  timeout 
)

最坏情况就是拿锁失败,让出CPU,变成阻塞任务,等别的任务释放锁后排到自己了接着执行.

在文件 los_mux.c341 行定义.

342{
343 UINT32 ret;
344
345 if ((mutex->muxList.pstPrev == NULL) || (mutex->muxList.pstNext == NULL)) {//列表为空时的处理
346 /* This is for mutex macro initialization. */
347 mutex->muxCount = 0;//锁计数器清0
348 mutex->owner = NULL;//锁没有归属任务
349 LOS_ListInit(&mutex->muxList);//初始化锁的任务链表,后续申请这把锁任务都会挂上去
350 }
351
352 if (mutex->muxCount == 0) {//无task用锁时,肯定能拿到锁了.在里面返回
353 mutex->muxCount++; //互斥锁计数器加1
354 mutex->owner = (VOID *)runTask; //当前任务拿到锁
355 LOS_ListTailInsert(&runTask->lockList, &mutex->holdList);
356 if (mutex->attr.protocol == LOS_MUX_PRIO_PROTECT) {
357 SchedParam param = { 0 };
358 runTask->ops->schedParamGet(runTask, &param);
359 param.priority = mutex->attr.prioceiling;
360 runTask->ops->priorityInheritance(runTask, &param);
361 }
362 return LOS_OK;
363 }
364 //递归锁muxCount>0 如果是递归锁就要处理两种情况 1.runtask持有锁 2.锁被别的任务拿走了
365 if (((LosTaskCB *)mutex->owner == runTask) && (mutex->attr.type == LOS_MUX_RECURSIVE)) {//第一种情况 runtask是锁持有方
366 mutex->muxCount++; //递归锁计数器加1,递归锁的目的是防止死锁,鸿蒙默认用的就是递归锁(LOS_MUX_DEFAULT = LOS_MUX_RECURSIVE)
367 return LOS_OK; //成功退出
368 }
369 //到了这里说明锁在别的任务那里,当前任务只能被阻塞了.
370 if (!timeout) {//参数timeout表示等待多久再来拿锁
371 return LOS_EINVAL;//timeout = 0表示不等了,没拿到锁就返回不纠结,返回错误.见于LOS_MuxTrylock
372 }
373 //自己要被阻塞,只能申请调度,让出CPU core 让别的任务上
374 if (!OsPreemptableInSched()) {//不能申请调度 (不能调度的原因是因为没有持有调度任务自旋锁)
375 return LOS_EDEADLK;//返回错误,自旋锁被别的CPU core 持有
376 }
377
378 OsMuxBitmapSet(mutex, runTask);//设置锁位图,尽可能的提高锁持有任务的优先级
379
380 runTask->taskMux = (VOID *)mutex; //记下当前任务在等待这把锁
381 LOS_DL_LIST *node = OsSchedLockPendFindPos(runTask, &mutex->muxList);
382 if (node == NULL) {
383 ret = LOS_NOK;
384 return ret;
385 }
386
387 OsTaskWaitSetPendMask(OS_TASK_WAIT_MUTEX, (UINTPTR)mutex, timeout);
388 ret = runTask->ops->wait(runTask, node, timeout);
389 if (ret == LOS_ERRNO_TSK_TIMEOUT) {//这行代码虽和OsTaskWait挨在一起,但要过很久才会执行到,因为在OsTaskWait中CPU切换了任务上下文
390 OsMuxBitmapRestore(mutex, NULL, runTask);
391 runTask->taskMux = NULL;// 所以重新回到这里时可能已经超时了
392 ret = LOS_ETIMEDOUT;//返回超时
393 }
394
395 return ret;
396}
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
Definition: los_list.h:104
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
VOID OsMuxBitmapRestore(const LosMux *mutex, const LOS_DL_LIST *list, const LosTaskCB *runTask)
恢复互斥锁位图
Definition: los_mux.c:328
STATIC VOID OsMuxBitmapSet(const LosMux *mutex, const LosTaskCB *runTask)
设置互斥锁位图
Definition: los_mux.c:313
@ LOS_MUX_RECURSIVE
递归锁 允许同一线程在互斥量解锁前对该互斥量进行多次加锁。递归互斥量维护锁的计数,在解锁次数和加锁次数不相同的情况下,不会释放锁,别的线程就无法加锁此互斥量。
Definition: los_mux.h:57
LOS_DL_LIST * OsSchedLockPendFindPos(const LosTaskCB *runTask, LOS_DL_LIST *lockList)
Definition: los_sched.c:519
STATIC INLINE BOOL OsPreemptableInSched(VOID)
STATIC INLINE VOID OsTaskWaitSetPendMask(UINT16 mask, UINTPTR lockID, UINT32 timeout)
设置事件阻塞掩码,即设置任务的等待事件.
Definition: los_task_pri.h:289
unsigned long UINTPTR
Definition: los_typedef.h:68
struct LOS_DL_LIST * pstPrev
Definition: los_list.h:83
struct LOS_DL_LIST * pstNext
Definition: los_list.h:84
LOS_DL_LIST muxList
Definition: los_mux.h:77
UINT16 muxCount
Definition: los_mux.h:79
LOS_DL_LIST holdList
Definition: los_mux.h:76
UINT32(* wait)(LosTaskCB *runTask, LOS_DL_LIST *list, UINT32 timeout)
任务等待
UINT16 priority
LOS_DL_LIST lockList
VOID * taskMux
函数调用图:
这是这个函数的调用关系图:

◆ OsMuxPostOp()

STATIC UINT32 OsMuxPostOp ( LosTaskCB taskCB,
LosMux mutex,
BOOL needSched 
)

OsMuxPostOp
是否有其他任务持有互斥锁而处于阻塞状,如果是就要唤醒它,注意唤醒一个任务的操作是由别的任务完成的 OsMuxPostOp只由OsMuxUnlockUnsafe,参数任务归还锁了,自然就会遇到锁要给谁用的问题, 因为很多任务在申请锁,由OsMuxPostOp来回答这个问题

参数
mutex
needSched
taskCB
返回
参见

在文件 los_mux.c502 行定义.

503{
504 if (LOS_ListEmpty(&mutex->muxList)) {//如果互斥锁列表为空
505 LOS_ListDelete(&mutex->holdList);//把持有互斥锁的节点摘掉
506 mutex->owner = NULL;
507 return LOS_OK;
508 }
509
510 LosTaskCB *resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(mutex->muxList)));//拿到等待互斥锁链表的第一个任务实体,接下来要唤醒任务
511 OsMuxBitmapRestore(mutex, &mutex->muxList, resumedTask);
512
513 mutex->muxCount = 1;//互斥锁数量为1
514 mutex->owner = (VOID *)resumedTask;//互斥锁的持有人换了
515 LOS_ListDelete(&mutex->holdList);//自然要从等锁链表中把自己摘出去
516 LOS_ListTailInsert(&resumedTask->lockList, &mutex->holdList);//把锁挂到恢复任务的锁链表上,lockList是任务持有的所有锁记录
517 OsTaskWakeClearPendMask(resumedTask);
518 resumedTask->ops->wake(resumedTask);
519 resumedTask->taskMux = NULL;
520 if (needSched != NULL) {//如果不为空
521 *needSched = TRUE;//就走起再次调度流程
522 }
523
524 return LOS_OK;
525}
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelete(LOS_DL_LIST *node)
Definition: los_list.h:292
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
STATIC INLINE VOID OsTaskWakeClearPendMask(LosTaskCB *resumeTask)
清除事件阻塞掩码,即任务不再等待任何事件.
Definition: los_task_pri.h:298
VOID(* wake)(LosTaskCB *taskCB)
任务唤醒
函数调用图:
这是这个函数的调用关系图:

◆ OsMuxTrylockUnsafe()

UINT32 OsMuxTrylockUnsafe ( LosMux mutex,
UINT32  timeout 
)

尝试加锁,

在文件 los_mux.c417 行定义.

418{
419 LosTaskCB *runTask = OsCurrTaskGet();//获取当前任务
420
421 if (mutex->magic != OS_MUX_MAGIC) {//检查MAGIC有没有被改变
422 return LOS_EBADF;
423 }
424
425 if (OsCheckMutexAttr(&mutex->attr) != LOS_OK) {//检查互斥锁属性
426 return LOS_EINVAL;
427 }
428
429 if ((mutex->owner != NULL) &&
430 (((LosTaskCB *)mutex->owner != runTask) || (mutex->attr.type != LOS_MUX_RECURSIVE))) {
431 return LOS_EBUSY;
432 }
433
434 return OsMuxPendOp(runTask, mutex, timeout);//当前任务去拿锁,拿不到就等timeout
435}
函数调用图:
这是这个函数的调用关系图:

◆ OsMuxUnlockUnsafe()

UINT32 OsMuxUnlockUnsafe ( LosTaskCB taskCB,
LosMux mutex,
BOOL needSched 
)

在文件 los_mux.c527 行定义.

528{
529 if (mutex->magic != OS_MUX_MAGIC) {
530 return LOS_EBADF;
531 }
532
533 if (OsCheckMutexAttr(&mutex->attr) != LOS_OK) {
534 return LOS_EINVAL;
535 }
536
537 if ((LosTaskCB *)mutex->owner != taskCB) {
538 return LOS_EPERM;
539 }
540
541 if (mutex->muxCount == 0) {
542 return LOS_EPERM;
543 }
544 //注意 --mutex->muxCount 先执行了-- 操作.
545 if ((--mutex->muxCount != 0) && (mutex->attr.type == LOS_MUX_RECURSIVE)) {//属性类型为LOS_MUX_RECURSIVE时,muxCount是可以不为0的
546 return LOS_OK;
547 }
548
549 if (mutex->attr.protocol == LOS_MUX_PRIO_PROTECT) {//属性协议为保护时
550 SchedParam param = { 0 };
551 taskCB->ops->schedParamGet(taskCB, &param);
552 taskCB->ops->priorityRestore(taskCB, NULL, &param);
553 }
554
555 /* Whether a task block the mutex lock. *///任务是否阻塞互斥锁
556 return OsMuxPostOp(taskCB, mutex, needSched);//一个任务去唤醒另一个在等锁的任务
557}
STATIC UINT32 OsMuxPostOp(LosTaskCB *taskCB, LosMux *mutex, BOOL *needSched)
OsMuxPostOp 是否有其他任务持有互斥锁而处于阻塞状,如果是就要唤醒它,注意唤醒一个任务的操作是由别的任务完成的 OsMuxPostOp只由OsMuxUnlockUnsafe,...
Definition: los_mux.c:502
函数调用图:
这是这个函数的调用关系图: