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

浏览源代码.

函数

int raise (int sig)
 
int OsSigIsMember (const sigset_t *set, int signo)
 判定信号signo是否存在信号集中。如果信号集里已有该信号则返回1,否则返回0。如果有错误则返回-1 更多...
 
STATIC VOID OsMoveTmpInfoToUnbInfo (sig_cb *sigcb, INT32 signo)
 
STATIC INT32 OsAddSigInfoToTmpList (sig_cb *sigcb, siginfo_t *info)
 
VOID OsClearSigInfoTmpList (sig_cb *sigcb)
 
STATIC INLINE VOID OsSigWaitTaskWake (LosTaskCB *taskCB, INT32 signo)
 唤醒被挂起的处于等待指定信号的任务 更多...
 
STATIC UINT32 OsPendingTaskWake (LosTaskCB *taskCB, INT32 signo)
 
int OsTcbDispatch (LosTaskCB *stcb, siginfo_t *info)
 给任务(线程)发送一个信号 更多...
 
void OsSigMaskSwitch (LosTaskCB *const rtcb, sigset_t set)
 
int OsSigprocMask (int how, const sigset_t_l *setl, sigset_t_l *oldsetl)
 
int OsSigProcessForeachChild (LosProcessCB *spcb, ForEachTaskCB handler, void *arg)
 让进程的每一个task执行参数函数 更多...
 
static int SigProcessSignalHandler (LosTaskCB *tcb, void *arg)
 信号处理函数,这里就是上面的 handler = SigProcessSignalHandler,见于 OsSigProcessSend 更多...
 
static int SigProcessKillSigHandler (LosTaskCB *tcb, void *arg)
 进程收到 SIGKILL 信号后,通知任务tcb处理. 更多...
 
static void SigProcessLoadTcb (struct ProcessSignalInfo *info, siginfo_t *sigInfo)
 
int OsSigProcessSend (LosProcessCB *spcb, siginfo_t *sigInfo)
 给参数进程发送参数信号 更多...
 
int OsSigEmptySet (sigset_t *set)
 信号集全部清0 更多...
 
static int OsSignalPermissionToCheck (const LosProcessCB *spcb)
 
int OsDispatch (pid_t pid, siginfo_t *info, int permission)
 信号分发,发送信号权限/进程组过滤. 更多...
 
int OsKill (pid_t pid, int sig, int permission)
 
int OsKillLock (pid_t pid, int sig)
 给发送信号过程加锁 更多...
 
INT32 OsTaskKillUnsafe (UINT32 taskID, INT32 signo)
 
int OsPthreadKill (UINT32 tid, int signo)
 发送信号 更多...
 
int OsSigAddSet (sigset_t *set, int signo)
 向信号集中加入signo信号 更多...
 
int OsSigPending (sigset_t *set)
 获取阻塞当前任务的信号集 更多...
 
STATIC int FindFirstSetedBit (UINT64 n)
 
int OsSigTimedWaitNoLock (sigset_t *set, siginfo_t *info, unsigned int timeout)
 等待信号时间 更多...
 
int OsSigTimedWait (sigset_t *set, siginfo_t *info, unsigned int timeout)
 让当前任务等待的信号 更多...
 
int OsPause (void)
 通过信号挂起当前任务 更多...
 
int OsSigSuspend (const sigset_t *set)
 用参数set代替进程的原有掩码,并暂停进程执行,直到收到信号再恢复原有掩码并继续执行进程。 更多...
 
int OsSigAction (int sig, const sigaction_t *act, sigaction_t *oact)
 
VOID OsSigIntLock (VOID)
 
VOID OsSigIntUnlock (VOID)
 
VOID * OsSaveSignalContext (VOID *sp, VOID *newSp)
 保存信号上下文 更多...
 
VOID * OsRestorSignalContext (VOID *sp)
 

函数说明

◆ FindFirstSetedBit()

STATIC int FindFirstSetedBit ( UINT64  n)

在文件 los_signal.c557 行定义.

558{
559 int count;
560
561 if (n == 0) {
562 return -1;
563 }
564 for (count = 0; (count < UINT64_BIT_SIZE) && (n ^ 1ULL); n >>= 1, count++) {}
565 return (count < UINT64_BIT_SIZE) ? count : (-1);
566}
这是这个函数的调用关系图:

◆ OsAddSigInfoToTmpList()

STATIC INT32 OsAddSigInfoToTmpList ( sig_cb sigcb,
siginfo_t *  info 
)

在文件 los_signal.c96 行定义.

97{
98 /* try to find the old siginfo */
99 SigInfoListNode *tmp = sigcb->tmpInfoListHead;
100 while (tmp != NULL) {
101 if (tmp->info.si_signo == info->si_signo) {
102 /* found it, break. */
103 break;
104 }
105 tmp = tmp->next;
106 }
107
108 if (tmp == NULL) {
109 /* none, alloc new one */
111 if (tmp == NULL) {
112 return LOS_NOK;
113 }
114 tmp->next = sigcb->tmpInfoListHead;
115 sigcb->tmpInfoListHead = tmp;
116 }
117
118 (VOID)memcpy_s(&tmp->info, sizeof(siginfo_t), info, sizeof(siginfo_t));
119
120 return LOS_OK;
121}
VOID * LOS_MemAlloc(VOID *pool, UINT32 size)
从指定内存池中申请size长度的内存,注意这可不是从内核堆空间中申请内存
Definition: los_memory.c:1123
UINT8 * m_aucSysMem0
异常交互动态内存池地址的起始地址,当不支持异常交互特性时,m_aucSysMem0等于m_aucSysMem1。
Definition: los_memory.c:107
siginfo_t info
Definition: los_signal.h:215
struct SigInfoListNode * next
Definition: los_signal.h:214
SigInfoListNode * tmpInfoListHead
Definition: los_signal.h:228
函数调用图:
这是这个函数的调用关系图:

◆ OsClearSigInfoTmpList()

VOID OsClearSigInfoTmpList ( sig_cb sigcb)

在文件 los_signal.c123 行定义.

124{
125 while (sigcb->tmpInfoListHead != NULL) {
126 SigInfoListNode *tmpInfoNode = sigcb->tmpInfoListHead;
127 sigcb->tmpInfoListHead = sigcb->tmpInfoListHead->next;
128 (VOID)LOS_MemFree(m_aucSysMem0, tmpInfoNode);
129 }
130}
UINT32 LOS_MemFree(VOID *pool, VOID *ptr)
释放从指定动态内存中申请的内存
Definition: los_memory.c:1369
函数调用图:
这是这个函数的调用关系图:

◆ OsDispatch()

int OsDispatch ( pid_t  pid,
siginfo_t *  info,
int  permission 
)

信号分发,发送信号权限/进程组过滤.

在文件 los_signal.c412 行定义.

413{
414 if (OsProcessIDUserCheckInvalid(pid) || pid < 0) {
415 return -ESRCH;
416 }
417 LosProcessCB *spcb = OS_PCB_FROM_PID(pid);//找到这个进程
418 if (OsProcessIsUnused(spcb)) {//进程是否还在使用,不一定是当前进程但必须是个有效进程
419 return -ESRCH;
420 }
421
422 /* If the process you want to kill had been inactive, but still exist. should return LOS_OK */
423 if (OsProcessIsInactive(spcb)) {//不向非活动进程发送信息,但返回OK
424 return LOS_OK;
425 }
426
427#ifdef LOSCFG_SECURITY_CAPABILITY //启用能力安全模式
428 LosProcessCB *current = OsCurrProcessGet();//获取当前进程,检查当前进程是否有发送信号的权限.
429 /* Kernel process always has kill permission and user process should check permission *///内核进程总是有kill权限,用户进程需要检查权限
430 if (OsProcessIsUserMode(current) && !(current->processStatus & OS_PROCESS_FLAG_EXIT)) {//用户进程检查能力范围
431 if ((current != spcb) && (!IsCapPermit(CAP_KILL)) && (current->user->userID != spcb->user->userID)) {
432 return -EPERM;
433 }
434 }
435#endif
436 if ((permission == OS_USER_KILL_PERMISSION) && (OsSignalPermissionToCheck(spcb) < 0)) {
437 return -EPERM;
438 }
439 return OsSigProcessSend(spcb, info);//给参数进程发送信号
440}
BOOL IsCapPermit(UINT32 capIndex)
Definition: capability.c:43
STATIC INLINE BOOL OsProcessIsInactive(const LosProcessCB *processCB)
进程不活跃函数定义:身上贴有不使用且不活跃标签的进程
STATIC INLINE BOOL OsProcessIsUserMode(const LosProcessCB *processCB)
STATIC INLINE BOOL OsProcessIsUnused(const LosProcessCB *processCB)
STATIC INLINE BOOL OsProcessIDUserCheckInvalid(UINT32 pid)
STATIC INLINE LosProcessCB * OsCurrProcessGet(VOID)
static int OsSignalPermissionToCheck(const LosProcessCB *spcb)
Definition: los_signal.c:399
int OsSigProcessSend(LosProcessCB *spcb, siginfo_t *sigInfo)
给参数进程发送参数信号
Definition: los_signal.c:362
UINT16 processStatus
User * user
进程的拥有者
UINT32 userID
用户ID [0,60000],0为root用户
函数调用图:
这是这个函数的调用关系图:

◆ OsKill()

int OsKill ( pid_t  pid,
int  sig,
int  permission 
)
   用于向进程或进程组发送信号
   shell命令 kill 14 7(kill -14 7效果相同)
   发送信号14(SIGALRM默认行为为进程终止)给7号进程
* 

在文件 los_signal.c450 行定义.

451{
452 siginfo_t info;
453 int ret;
454
455 /* Make sure that the para is valid */
456 if (!GOOD_SIGNO(sig)) {
457 return -EINVAL;
458 }
459
460 /* Create the siginfo structure */ //创建信号结构体
461 info.si_signo = sig; //信号编号
462 info.si_code = SI_USER; //来自用户进程信号
463 info.si_value.sival_ptr = NULL;
464
465 if (pid > 0) {
466 /* Send the signal to the specify process */
467 ret = OsDispatch(pid, &info, permission);//发送信号
468 } else if (pid == -1) {
469 /* Send SIG to all processes */
470 ret = OsSendSignalToAllProcess(&info, permission);
471 } else {
472 /* Send SIG to all processes in process group PGRP.
473 If PGRP is zero, send SIG to all processes in
474 the current process's process group. */
475 ret = OsSendSignalToProcessGroup(pid, &info, permission);
476 }
477 return ret;
478}
LITE_OS_SEC_TEXT INT32 OsSendSignalToProcessGroup(INT32 pid, siginfo_t *info, INT32 permission)
Definition: los_process.c:262
LITE_OS_SEC_TEXT INT32 OsSendSignalToAllProcess(siginfo_t *info, INT32 permission)
Definition: los_process.c:242
int OsDispatch(pid_t pid, siginfo_t *info, int permission)
信号分发,发送信号权限/进程组过滤.
Definition: los_signal.c:412
static int GOOD_SIGNO(unsigned int sig)
信号ID是否有效
Definition: los_signal.h:158
函数调用图:
这是这个函数的调用关系图:

◆ OsKillLock()

int OsKillLock ( pid_t  pid,
int  sig 
)

给发送信号过程加锁

在文件 los_signal.c480 行定义.

481{
482 int ret;
483 unsigned int intSave;
484
485 SCHEDULER_LOCK(intSave);
486 ret = OsKill(pid, sig, OS_USER_KILL_PERMISSION);//用户权限向进程发送信号
487 SCHEDULER_UNLOCK(intSave);
488 return ret;
489}
int OsKill(pid_t pid, int sig, int permission)
Definition: los_signal.c:450
函数调用图:
这是这个函数的调用关系图:

◆ OsMoveTmpInfoToUnbInfo()

STATIC VOID OsMoveTmpInfoToUnbInfo ( sig_cb sigcb,
INT32  signo 
)

在文件 los_signal.c77 行定义.

78{
79 SigInfoListNode *tmpInfoNode = sigcb->tmpInfoListHead;
80 SigInfoListNode **prevHook = &sigcb->tmpInfoListHead;
81 while (tmpInfoNode != NULL) {
82 if (tmpInfoNode->info.si_signo == signo) {
83 /* copy tmpinfo to unbinfo. */
84 (VOID)memcpy_s(&sigcb->sigunbinfo, sizeof(siginfo_t), &tmpInfoNode->info, sizeof(siginfo_t));
85 /* delete tmpinfo from tmpList. */
86 *prevHook = tmpInfoNode->next;
87 (VOID)LOS_MemFree(m_aucSysMem0, tmpInfoNode);
88 tmpInfoNode = *prevHook;
89 break;
90 }
91 prevHook = &tmpInfoNode->next;
92 tmpInfoNode = tmpInfoNode->next;
93 }
94}
siginfo_t sigunbinfo
Definition: los_signal.h:227
函数调用图:
这是这个函数的调用关系图:

◆ OsPause()

int OsPause ( void  )

通过信号挂起当前任务

在文件 los_signal.c617 行定义.

618{
619 LosTaskCB *spcb = NULL;
620 sigset_t oldSigprocmask;
621
622 spcb = OsCurrTaskGet();
623 oldSigprocmask = spcb->sig.sigprocmask;
624 return OsSigSuspend(&oldSigprocmask);
625}
STATIC INLINE LosTaskCB * OsCurrTaskGet(VOID)
int OsSigSuspend(const sigset_t *set)
用参数set代替进程的原有掩码,并暂停进程执行,直到收到信号再恢复原有掩码并继续执行进程。
Definition: los_signal.c:627
sig_cb sig
信号控制块,用于异步通信,类似于 linux singal模块
sigset_t sigprocmask
Signals that are blocked | 任务屏蔽了哪些信号
Definition: los_signal.h:223
函数调用图:
这是这个函数的调用关系图:

◆ OsPendingTaskWake()

STATIC UINT32 OsPendingTaskWake ( LosTaskCB taskCB,
INT32  signo 
)

在文件 los_signal.c143 行定义.

144{
145 if (!OsTaskIsPending(taskCB) || !OsProcessIsUserMode(OS_PCB_FROM_PID(taskCB->processID))) {
146 return 0;
147 }
148
149 if ((signo != SIGKILL) && (taskCB->waitFlag != OS_TASK_WAIT_SIGNAL)) { // @note_thinking 这个判断会不会有问题 ?
150 return 0;
151 }
152
153 switch (taskCB->waitFlag) {
154 case OS_TASK_WAIT_PROCESS:
155 case OS_TASK_WAIT_GID:
156 case OS_TASK_WAIT_ANYPROCESS:
157 OsWaitWakeTask(taskCB, OS_INVALID_VALUE);
158 break;
159 case OS_TASK_WAIT_JOIN:
161 taskCB->ops->wake(taskCB);
162 break;
163 case OS_TASK_WAIT_SIGNAL://等待普通信号
164 OsSigWaitTaskWake(taskCB, signo);
165 break;
166 case OS_TASK_WAIT_LITEIPC://等待liteipc信号
167 OsTaskWakeClearPendMask(taskCB);//重置任务的等待信息
168 taskCB->ops->wake(taskCB);
169 break;
170 case OS_TASK_WAIT_FUTEX://等待快锁信号
171 OsFutexNodeDeleteFromFutexHash(&taskCB->futex, TRUE, NULL, NULL);//从哈希桶中删除快锁
172 OsTaskWakeClearPendMask(taskCB);//重置任务的等待信息
173 taskCB->ops->wake(taskCB);
174 break;
175 default:
176 break;
177 }
178
179 return 0;
180}
VOID OsFutexNodeDeleteFromFutexHash(FutexNode *node, BOOL isDeleteHead, FutexNode **headNode, BOOL *queueFlags)
从哈希桶上删除快锁
Definition: los_futex.c:302
VOID OsWaitWakeTask(LosTaskCB *taskCB, UINT32 wakePID)
Definition: los_process.c:326
STATIC INLINE BOOL OsTaskIsPending(const LosTaskCB *taskCB)
STATIC INLINE VOID OsSigWaitTaskWake(LosTaskCB *taskCB, INT32 signo)
唤醒被挂起的处于等待指定信号的任务
Definition: los_signal.c:131
STATIC INLINE VOID OsTaskWakeClearPendMask(LosTaskCB *resumeTask)
清除事件阻塞掩码,即任务不再等待任何事件.
Definition: los_task_pri.h:298
VOID(* wake)(LosTaskCB *taskCB)
任务唤醒
FutexNode futex
指明任务在等待哪把快锁,一次只等一锁,锁和任务的关系是(1:N)关系
UINT32 processID
const SchedOps * ops
UINT16 waitFlag
函数调用图:
这是这个函数的调用关系图:

◆ OsPthreadKill()

int OsPthreadKill ( UINT32  tid,
int  signo 
)

发送信号

在文件 los_signal.c509 行定义.

510{
511 int ret;
512 UINT32 intSave;
513
514 /* Make sure that the signal is valid */
515 OS_RETURN_IF(!GOOD_SIGNO(signo), -EINVAL);
516 if (OS_TID_CHECK_INVALID(tid)) {
517 return -ESRCH;
518 }
519
520 /* Keep things stationary through the following */
521 SCHEDULER_LOCK(intSave);
522 ret = OsTaskKillUnsafe(tid, signo);
523 SCHEDULER_UNLOCK(intSave);
524 return ret;
525}
INT32 OsTaskKillUnsafe(UINT32 taskID, INT32 signo)
Definition: los_signal.c:490
unsigned int UINT32
Definition: los_typedef.h:57
函数调用图:
这是这个函数的调用关系图:

◆ OsRestorSignalContext()

VOID * OsRestorSignalContext ( VOID *  sp)
   恢复信号上下文,由系统调用之__NR_sigreturn产生,这是一个内部产生的系统调用.
   为什么要恢复呢?
   因为系统调用的执行由任务内核态完成,使用的栈也是内核栈,CPU相关寄存器记录的都是内核栈的内容,
   而系统调用完成后,需返回任务的用户栈执行,这时需将CPU各寄存器回到用户态现场
   所以函数的功能就变成了还原寄存器的值
* 

在文件 los_signal.c786 行定义.

787{
788 UINT32 intSave;
789
790 LosTaskCB *task = OsCurrTaskGet();
791 sig_cb *sigcb = &task->sig;
792
793 SCHEDULER_LOCK(intSave);
794 if (sigcb->count != 1) {
795 SCHEDULER_UNLOCK(intSave);
796 PRINT_ERR("sig error count : %d\n", sigcb->count);
797 return sp;
798 }
799
800 LosProcessCB *process = OsCurrProcessGet();
801 VOID *saveContext = sigcb->sigContext;
802 sigcb->sigContext = NULL;
803 sigcb->count--;
804 process->sigShare = 0; //回到用户态,信号共享清0
805 OsProcessExitCodeSignalClear(process);//清空进程退出码
806 SCHEDULER_UNLOCK(intSave);
807 return saveContext;
808}
macro EXC_SP_SET reg1 mrc 获取CPU信息 and mov mul reg0 计算当前CPU栈的偏移位置 ldr reg1 相减得到栈顶 mov sp
Definition: asm.h:57
STATIC INLINE VOID OsProcessExitCodeSignalClear(LosProcessCB *processCB)
清除进程退出信号(0 ~ 7)
sigset_t sigShare
信号控制块(描述符)
Definition: los_signal.h:220
unsigned int count
信号数量
Definition: los_signal.h:231
void * sigContext
信号上下文
Definition: los_signal.h:230
函数调用图:

◆ OsSaveSignalContext()

VOID * OsSaveSignalContext ( VOID *  sp,
VOID *  newSp 
)

保存信号上下文

   产生系统调用时,也就是软中断时,保存用户栈寄存器现场信息
   改写PC寄存器的值
* 

在文件 los_signal.c727 行定义.

728{
729 UINTPTR sigHandler;
730 UINT32 intSave;
731 LosTaskCB *task = OsCurrTaskGet();
732 LosProcessCB *process = OsCurrProcessGet();
733 sig_cb *sigcb = &task->sig;
734
735 /* A thread is not allowed to interrupt the processing of its signals during a system call */
736 if (sigcb->sigIntLock > 0) {
737 return sp;
738 }
739
740 if (OsTaskIsKilled(task)) {
741 OsRunningTaskToExit(task, 0);
742 return sp;
743 }
744
745 SCHEDULER_LOCK(intSave);
746 if ((sigcb->count == 0) && ((sigcb->sigFlag != 0) || (process->sigShare != 0))) {
747 sigHandler = OsGetSigHandler();
748 if (sigHandler == 0) {
749 sigcb->sigFlag = 0;
750 process->sigShare = 0;
751 SCHEDULER_UNLOCK(intSave);
752 PRINT_ERR("The signal processing function for the current process pid =%d is NULL!\n", task->processID);
753 return sp;
754 }
755 /* One pthread do the share signal */
756 sigcb->sigFlag |= process->sigShare;
757 UINT32 signo = (UINT32)FindFirstSetedBit(sigcb->sigFlag) + 1;
758 UINT32 sigVal = (UINT32)(UINTPTR)(sigcb->sigunbinfo.si_value.sival_ptr);
759 OsMoveTmpInfoToUnbInfo(sigcb, signo);
760 OsProcessExitCodeSignalSet(process, signo);
761 sigcb->sigContext = sp;
762
763 OsInitSignalContext(sp, newSp, sigHandler, signo, sigVal);//初始化信号上下文
764
765 /* sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */
766 sigcb->sigFlag ^= 1ULL << (signo - 1);
767 sigcb->count++;
768 SCHEDULER_UNLOCK(intSave);
769 return newSp;
770 }
771
772 SCHEDULER_UNLOCK(intSave);
773 return sp;
774}
VOID OsInitSignalContext(const VOID *sp, VOID *signalContext, UINTPTR sigHandler, UINT32 signo, UINT32 param)
初始化信号上下文
Definition: los_hw.c:138
LITE_OS_SEC_TEXT UINTPTR OsGetSigHandler(VOID)
获取进程的信号处理函数
Definition: los_process.c:2264
STATIC INLINE VOID OsProcessExitCodeSignalSet(LosProcessCB *processCB, UINT32 signal)
设置进程退出信号(0 ~ 7)
STATIC VOID OsMoveTmpInfoToUnbInfo(sig_cb *sigcb, INT32 signo)
Definition: los_signal.c:77
STATIC int FindFirstSetedBit(UINT64 n)
Definition: los_signal.c:557
LITE_OS_SEC_TEXT VOID OsRunningTaskToExit(LosTaskCB *runTask, UINT32 status)
Definition: los_task.c:908
STATIC INLINE BOOL OsTaskIsKilled(const LosTaskCB *taskCB)
Definition: los_task_pri.h:260
unsigned long UINTPTR
Definition: los_typedef.h:68
unsigned int sigIntLock
信号中断锁
Definition: los_signal.h:229
sigset_t sigFlag
不屏蔽的信号集
Definition: los_signal.h:221
函数调用图:

◆ OsSigAction()

int OsSigAction ( int  sig,
const sigaction_t act,
sigaction_t oact 
)
   信号安装,函数用于改变进程接收到特定信号后的行为。
   sig:信号的值,可以为除SIGKILL及SIGSTOP外的任何一个特定有效的信号(为这两个信号定义自己的处理函数,将导致信号安装错误)。
   act:设置对signal信号的新处理方式。
   oldact:原来对信号的处理方式。
   如果把第二、第三个参数都设为NULL,那么该函数可用于检查信号的有效性。
   返回值:0 表示成功,-1 表示有错误发生。
* 

在文件 los_signal.c677 行定义.

678{
679 UINTPTR addr;
680 sigaction_t action;
681
682 if (!GOOD_SIGNO(sig) || sig < 1 || act == NULL) {
683 return -EINVAL;
684 }
685 //将数据从用户空间拷贝到内核空间
686 if (LOS_ArchCopyFromUser(&action, act, sizeof(sigaction_t)) != LOS_OK) {
687 return -EFAULT;
688 }
689
690 if (sig == SIGSYS) {//鸿蒙此处通过错误的系统调用 来安装信号处理函数,有点巧妙.
691 addr = OsGetSigHandler();//是否已存在信号处理函数
692 if (addr == 0) {//进程没有设置信号处理函数时
693 OsSetSigHandler((unsigned long)(UINTPTR)action.sa_handler);//设置进程信号处理函数
694 //void (*sa_handler)(int); //信号处理函数——普通版
695 //void (*sa_sigaction)(int, siginfo_t *, void *);//信号处理函数——高级版
696 return LOS_OK;
697 }
698 return -EINVAL;
699 }
700
701 return LOS_OK;
702}
LITE_OS_SEC_TEXT VOID OsSetSigHandler(UINTPTR addr)
设置进程的信号处理函数
Definition: los_process.c:2259
struct sigaction sigaction_t
Definition: los_signal.h:186
size_t LOS_ArchCopyFromUser(void *dst, const void *src, size_t len)
Definition: user_copy.c:58
函数调用图:
这是这个函数的调用关系图:

◆ OsSigAddSet()

int OsSigAddSet ( sigset_t *  set,
int  signo 
)

向信号集中加入signo信号

在文件 los_signal.c527 行定义.

528{
529 /* Verify the signal */
530 if (!GOOD_SIGNO(signo)) {
531 return -EINVAL;
532 } else {
533 /* In musl, sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */
534 signo -= 1;// 信号范围是 [1 ~ 64 ],而保存变量位的范围是[0 ~ 63]
535 /* Add the signal to the set */
536 *set |= SIGNO2SET((unsigned int)signo);//填充信号集
537 return LOS_OK;
538 }
539}
函数调用图:
这是这个函数的调用关系图:

◆ OsSigEmptySet()

int OsSigEmptySet ( sigset_t *  set)

信号集全部清0

在文件 los_signal.c392 行定义.

393{
394 *set = NULL_SIGNAL_SET;
395 return 0;
396}
这是这个函数的调用关系图:

◆ OsSigIntLock()

VOID OsSigIntLock ( VOID  )

在文件 los_signal.c704 行定义.

705{
706 LosTaskCB *task = OsCurrTaskGet();
707 sig_cb *sigcb = &task->sig;
708
709 (VOID)LOS_AtomicAdd((Atomic *)&sigcb->sigIntLock, 1);
710}
STATIC INLINE INT32 LOS_AtomicAdd(Atomic *v, INT32 addVal)
Atomic addition.
Definition: los_atomic.h:173
volatile INT32 Atomic
Definition: los_atomic.h:102
函数调用图:
这是这个函数的调用关系图:

◆ OsSigIntUnlock()

VOID OsSigIntUnlock ( VOID  )

在文件 los_signal.c712 行定义.

713{
714 LosTaskCB *task = OsCurrTaskGet();
715 sig_cb *sigcb = &task->sig;
716
717 (VOID)LOS_AtomicSub((Atomic *)&sigcb->sigIntLock, 1);
718}
STATIC INLINE INT32 LOS_AtomicSub(Atomic *v, INT32 subVal)
Atomic subtraction.
Definition: los_atomic.h:217
函数调用图:
这是这个函数的调用关系图:

◆ OsSigIsMember()

int OsSigIsMember ( const sigset_t *  set,
int  signo 
)

判定信号signo是否存在信号集中。如果信号集里已有该信号则返回1,否则返回0。如果有错误则返回-1

参数
set
signo
返回
int

在文件 los_signal.c62 行定义.

63{
64 int ret = LOS_NOK;
65 /* In musl, sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */
66 //在musl中,sig No bits 00000100表示sig No 3,但是在SIGNO2SET中 1<<3 = 00001000,因此signo需要减1
67 signo -= 1;
68 /* Verify the signal */
69 if (GOOD_SIGNO(signo)) {//有效信号判断
70 /* Check if the signal is in the set */
71 ret = ((*set & SIGNO2SET((unsigned int)signo)) != 0);//检查信号是否还在集合中
72 }
73
74 return ret;
75}
函数调用图:
这是这个函数的调用关系图:

◆ OsSigMaskSwitch()

void OsSigMaskSwitch ( LosTaskCB *const  rtcb,
sigset_t  set 
)

在文件 los_signal.c211 行定义.

212{
213 sigset_t unmaskset;
214
215 rtcb->sig.sigprocmask = set;
216 unmaskset = GETUNMASKSET(rtcb->sig.sigprocmask, rtcb->sig.sigPendFlag);//过滤出没有被屏蔽的信号集
217 if (unmaskset != NULL_SIGNAL_SET) {
218 /* pendlist do */
219 rtcb->sig.sigFlag |= unmaskset; //加入不屏蔽信号集
220 rtcb->sig.sigPendFlag ^= unmaskset;//从挂起/待办集中去掉unmaskset
221 }
222}
sigset_t sigPendFlag
信号阻塞标签集,记录那些信号来过,任务依然阻塞的集合.即:这些信号不能唤醒任务
Definition: los_signal.h:222
这是这个函数的调用关系图:

◆ OsSignalPermissionToCheck()

static int OsSignalPermissionToCheck ( const LosProcessCB spcb)
static

在文件 los_signal.c399 行定义.

400{
401 UINT32 gid = spcb->group->groupID;
402
403 if (gid == OS_KERNEL_PROCESS_GROUP) {//内核进程组
404 return -EPERM;
405 } else if (gid == OS_USER_PRIVILEGE_PROCESS_GROUP) {//用户特权进程组
406 return -EPERM;
407 }
408
409 return 0;
410}
ProcessGroup * group
这是这个函数的调用关系图:

◆ OsSigPending()

int OsSigPending ( sigset_t *  set)

获取阻塞当前任务的信号集

在文件 los_signal.c541 行定义.

542{
543 LosTaskCB *tcb = NULL;
544 unsigned int intSave;
545
546 if (set == NULL) {
547 return -EFAULT;
548 }
549
550 SCHEDULER_LOCK(intSave);
551 tcb = OsCurrTaskGet();
552 *set = tcb->sig.sigPendFlag;//被阻塞的信号集
553 SCHEDULER_UNLOCK(intSave);
554 return LOS_OK;
555}
函数调用图:
这是这个函数的调用关系图:

◆ OsSigProcessForeachChild()

int OsSigProcessForeachChild ( LosProcessCB spcb,
ForEachTaskCB  handler,
void arg 
)

让进程的每一个task执行参数函数

在文件 los_signal.c279 行定义.

280{
281 int ret;
282
283 /* Visit the main thread last (if present) */
284 LosTaskCB *taskCB = NULL;//遍历进程的 threadList 链表,里面存放的都是task节点
285 LOS_DL_LIST_FOR_EACH_ENTRY(taskCB, &(spcb->threadSiblingList), LosTaskCB, threadList) {//遍历进程的任务列表
286 ret = handler(taskCB, arg);//回调参数函数
287 OS_RETURN_IF(ret != 0, ret);//这个宏的意思就是只有ret = 0时,啥也不处理.其余就返回 ret
288 }
289 return LOS_OK;
290}
LOS_DL_LIST threadSiblingList
这是这个函数的调用关系图:

◆ OsSigProcessSend()

int OsSigProcessSend ( LosProcessCB spcb,
siginfo_t *  sigInfo 
)

给参数进程发送参数信号

在文件 los_signal.c362 行定义.

363{
364 int ret;
365 struct ProcessSignalInfo info = {
366 .sigInfo = sigInfo, //信号内容
367 .defaultTcb = NULL, //以下四个值将在OsSigProcessForeachChild中根据条件完善
368 .unblockedTcb = NULL,
369 .awakenedTcb = NULL,
370 .receivedTcb = NULL
371 };
372 //总之是要从进程中找个至少一个任务来接受这个信号,优先级
373 //awakenedTcb > receivedTcb > unblockedTcb > defaultTcb
374 if (info.sigInfo == NULL){
375 return -EFAULT;
376 }
377 /* visit all taskcb and dispatch signal */ //访问所有任务和分发信号
378 if (info.sigInfo->si_signo == SIGKILL) {//需要干掉进程时 SIGKILL = 9, #linux kill 9 14
379 OsSigAddSet(&spcb->sigShare, info.sigInfo->si_signo);//信号集中增加信号
381 return 0;
382 } else {
383 ret = OsSigProcessForeachChild(spcb, SigProcessSignalHandler, &info);//进程通知所有task处理信号
384 }
385 if (ret < 0) {
386 return ret;
387 }
388 SigProcessLoadTcb(&info, sigInfo);//确保能给一个任务发送信号
389 return 0;
390}
int OsSigAddSet(sigset_t *set, int signo)
向信号集中加入signo信号
Definition: los_signal.c:527
int OsSigProcessForeachChild(LosProcessCB *spcb, ForEachTaskCB handler, void *arg)
让进程的每一个task执行参数函数
Definition: los_signal.c:279
static int SigProcessSignalHandler(LosTaskCB *tcb, void *arg)
信号处理函数,这里就是上面的 handler = SigProcessSignalHandler,见于 OsSigProcessSend
Definition: los_signal.c:292
static int SigProcessKillSigHandler(LosTaskCB *tcb, void *arg)
进程收到 SIGKILL 信号后,通知任务tcb处理.
Definition: los_signal.c:337
static void SigProcessLoadTcb(struct ProcessSignalInfo *info, siginfo_t *sigInfo)
Definition: los_signal.c:345
siginfo_t * sigInfo
Definition: los_task_pri.h:215
ARG_NUM_3 ARG_NUM_1 ARG_NUM_2 ARG_NUM_2 ARG_NUM_3 ARG_NUM_1 ARG_NUM_4 ARG_NUM_2 ARG_NUM_2 ARG_NUM_5 ARG_NUM_2 void
函数调用图:
这是这个函数的调用关系图:

◆ OsSigprocMask()

int OsSigprocMask ( int  how,
const sigset_t_l setl,
sigset_t_l oldsetl 
)
   向信号集设置信号屏蔽的方法
       SIG_BLOCK:将set指向信号集中的信号,添加到进程阻塞信号集;
       SIG_UNBLOCK:将set指向信号集中的信号,从进程阻塞信号集删除;
       SIG_SETMASK:将set指向信号集中的信号,设置成进程阻塞信号集;
* 

在文件 los_signal.c233 行定义.

234{
235 LosTaskCB *spcb = NULL;
236 int ret = LOS_OK;
237 unsigned int intSave;
238 sigset_t set;
239
240 SCHEDULER_LOCK(intSave);
241 spcb = OsCurrTaskGet();
242 /* If requested, copy the old mask to user. | 如果需要,请将旧掩码复制给用户*/
243 if (oldsetl != NULL) {
244 *(sigset_t *)oldsetl = spcb->sig.sigprocmask;
245 }
246 /* If requested, modify the current signal mask. | 如有要求,修改当前信号屏蔽*/
247 if (setl != NULL) {
248 set = *(sigset_t *)setl;
249 /* Okay, determine what we are supposed to do */
250 switch (how) {
251 /* Set the union of the current set and the signal
252 * set pointed to by set as the new sigprocmask.
253 */
254 case SIG_BLOCK:
255 spcb->sig.sigprocmask |= set;//增加信号屏蔽位
256 break;
257 /* Set the intersection of the current set and the
258 * signal set pointed to by set as the new sigprocmask.
259 */
260 case SIG_UNBLOCK:
261 spcb->sig.sigprocmask &= ~(set);//解除信号屏蔽位
262 break;
263 /* Set the signal set pointed to by set as the new sigprocmask. */
264 case SIG_SETMASK:
265 spcb->sig.sigprocmask = set;//设置一个新的屏蔽掩码
266 break;
267 default:
268 ret = -EINVAL;
269 break;
270 }
271 /* If pending mask not in sigmask, need set sigflag. */
272 OsSigMaskSwitch(spcb, spcb->sig.sigprocmask);//更新与屏蔽信号相关的变量
273 }
274 SCHEDULER_UNLOCK(intSave);
275
276 return ret;
277}
void OsSigMaskSwitch(LosTaskCB *const rtcb, sigset_t set)
Definition: los_signal.c:211
函数调用图:
这是这个函数的调用关系图:

◆ OsSigSuspend()

int OsSigSuspend ( const sigset_t *  set)

用参数set代替进程的原有掩码,并暂停进程执行,直到收到信号再恢复原有掩码并继续执行进程。

在文件 los_signal.c627 行定义.

628{
629 unsigned int intSave;
630 LosTaskCB *rtcb = NULL;
631 sigset_t setSuspend;
632 int ret;
633
634 if (set == NULL) {
635 return -EINVAL;
636 }
637 SCHEDULER_LOCK(intSave);
638 rtcb = OsCurrTaskGet();
639
640 /* Wait signal calc */
641 setSuspend = FULL_SIGNAL_SET & (~(*set));
642
643 /* If pending mask not in sigmask, need set sigflag */
644 OsSigMaskSwitch(rtcb, *set);
645
646 if (rtcb->sig.sigFlag > 0) {
647 SCHEDULER_UNLOCK(intSave);
648
649 /*
650 * If rtcb->sig.sigFlag > 0, it means that some signal have been
651 * received, and we need to do schedule to handle the signal directly.
652 */
653 LOS_Schedule();
654 return -EINTR;
655 } else {
656 ret = OsSigTimedWaitNoLock(&setSuspend, NULL, LOS_WAIT_FOREVER);
657 if (ret < 0) {
658 PRINT_ERR("FUNC %s LINE = %d, ret = %x\n", __FUNCTION__, __LINE__, ret);
659 }
660 }
661
662 SCHEDULER_UNLOCK(intSave);
663 return -EINTR;
664}
VOID LOS_Schedule(VOID)
Trigger active task scheduling.
Definition: los_sched.c:469
int OsSigTimedWaitNoLock(sigset_t *set, siginfo_t *info, unsigned int timeout)
等待信号时间
Definition: los_signal.c:568
函数调用图:
这是这个函数的调用关系图:

◆ OsSigTimedWait()

int OsSigTimedWait ( sigset_t *  set,
siginfo_t *  info,
unsigned int  timeout 
)

让当前任务等待的信号

在文件 los_signal.c604 行定义.

605{
606 int ret;
607 unsigned int intSave;
608
609 SCHEDULER_LOCK(intSave);
610
611 ret = OsSigTimedWaitNoLock(set, info, timeout);//以不加锁的方式等待
612
613 SCHEDULER_UNLOCK(intSave);
614 return ret;
615}
函数调用图:
这是这个函数的调用关系图:

◆ OsSigTimedWaitNoLock()

int OsSigTimedWaitNoLock ( sigset_t *  set,
siginfo_t *  info,
unsigned int  timeout 
)

等待信号时间

在文件 los_signal.c568 行定义.

569{
570 LosTaskCB *task = NULL;
571 sig_cb *sigcb = NULL;
572 int ret;
573
574 task = OsCurrTaskGet();
575 sigcb = &task->sig;
576
577 if (sigcb->waitList.pstNext == NULL) {
578 LOS_ListInit(&sigcb->waitList);//初始化信号等待链表
579 }
580 /* If pendingflag & set > 0, shound clear pending flag */
581 sigset_t clear = sigcb->sigPendFlag & *set;
582 if (clear) {
583 sigcb->sigPendFlag ^= clear;
584 ret = FindFirstSetedBit((UINT64)clear) + 1;
585 OsMoveTmpInfoToUnbInfo(sigcb, ret);
586 } else {
587 OsSigAddSet(set, SIGKILL);//kill 9 14 必须要处理
588 OsSigAddSet(set, SIGSTOP);//终止进程的信号也必须处理
589
590 sigcb->sigwaitmask |= *set;//按位加到等待集上,也就是说sigwaitmask的信号来了都是要处理的.
591 OsTaskWaitSetPendMask(OS_TASK_WAIT_SIGNAL, sigcb->sigwaitmask, timeout);
592 ret = task->ops->wait(task, &sigcb->waitList, timeout);
593 if (ret == LOS_ERRNO_TSK_TIMEOUT) {
594 ret = -EAGAIN;
595 }
596 sigcb->sigwaitmask = NULL_SIGNAL_SET;
597 }
598 if (info != NULL) {
599 (VOID)memcpy_s(info, sizeof(siginfo_t), &sigcb->sigunbinfo, sizeof(siginfo_t));
600 }
601 return ret;
602}
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
Definition: los_list.h:104
STATIC INLINE VOID OsTaskWaitSetPendMask(UINT16 mask, UINTPTR lockID, UINT32 timeout)
设置事件阻塞掩码,即设置任务的等待事件.
Definition: los_task_pri.h:289
long unsigned int UINT64
Definition: los_typedef.h:66
struct LOS_DL_LIST * pstNext
Definition: los_list.h:84
UINT32(* wait)(LosTaskCB *runTask, LOS_DL_LIST *list, UINT32 timeout)
任务等待
sigset_t sigwaitmask
Definition: los_signal.h:226
LOS_DL_LIST waitList
待链表,上面挂的是等待信号到来的任务, 请查找 OsTaskWait(&sigcb->waitList, timeout, TRUE) 理解
Definition: los_signal.h:225
函数调用图:
这是这个函数的调用关系图:

◆ OsSigWaitTaskWake()

STATIC INLINE VOID OsSigWaitTaskWake ( LosTaskCB taskCB,
INT32  signo 
)

唤醒被挂起的处于等待指定信号的任务

在文件 los_signal.c131 行定义.

函数调用图:
这是这个函数的调用关系图:

◆ OsTaskKillUnsafe()

INT32 OsTaskKillUnsafe ( UINT32  taskID,
INT32  signo 
)

在文件 los_signal.c490 行定义.

491{
492 siginfo_t info;
493 LosTaskCB *taskCB = OsGetTaskCB(taskID);
495 if (ret != LOS_OK) {
496 return -ret;
497 }
498
499 /* Create the siginfo structure */
500 info.si_signo = signo;
501 info.si_code = SI_USER;
502 info.si_value.sival_ptr = NULL;
503
504 /* Dispatch the signal to thread, bypassing normal task group thread
505 * dispatch rules. */
506 return OsTcbDispatch(taskCB, &info);
507}
int OsTcbDispatch(LosTaskCB *stcb, siginfo_t *info)
给任务(线程)发送一个信号
Definition: los_signal.c:182
INT32 OsUserTaskOperatePermissionsCheck(const LosTaskCB *taskCB)
Definition: los_task.c:1380
STATIC INLINE LosTaskCB * OsGetTaskCB(UINT32 taskID)
通过任务ID获取任务实体,task由任务池分配,本质是个数组,彼此都挨在一块
Definition: los_task_pri.h:250
signed int INT32
Definition: los_typedef.h:60
函数调用图:
这是这个函数的调用关系图:

◆ OsTcbDispatch()

int OsTcbDispatch ( LosTaskCB stcb,
siginfo_t *  info 
)

给任务(线程)发送一个信号

在文件 los_signal.c182 行定义.

183{
184 bool masked = FALSE;
185 sig_cb *sigcb = &stcb->sig;
186
187 OS_RETURN_IF_NULL(sigcb);
188 /* If signo is 0, not send signal, just check process or pthread exist */
189 if (info->si_signo == 0) {//如果信号为0,则不发送信号,只是作为检查进程和线程是否还存在.
190 return 0;
191 }
192 masked = (bool)OsSigIsMember(&sigcb->sigprocmask, info->si_signo);//@note_thinking 这里还有 masked= -1的情况要处理!!!
193 if (masked) {//如果信号被屏蔽了,要看等待信号集,sigwaitmask
194 /* If signal is in wait list and mask list, need unblock it */ //如果信号在等待列表和掩码列表中,需要解除阻止
195 if (LOS_ListEmpty(&sigcb->waitList) ||
196 (!LOS_ListEmpty(&sigcb->waitList) && !OsSigIsMember(&sigcb->sigwaitmask, info->si_signo))) {
197 OsSigAddSet(&sigcb->sigPendFlag, info->si_signo);//将信号加入挂起/待办集
198 }
199 } else {//信号没有被屏蔽的处理
200 /* unmasked signal actions */
201 OsSigAddSet(&sigcb->sigFlag, info->si_signo);//不屏蔽的信号集
202 }
203
204 if (OsAddSigInfoToTmpList(sigcb, info) == LOS_NOK) {
205 return -ENOMEM;
206 }
207
208 return OsPendingTaskWake(stcb, info->si_signo);
209}
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 UINT32 OsPendingTaskWake(LosTaskCB *taskCB, INT32 signo)
Definition: los_signal.c:143
int OsSigIsMember(const sigset_t *set, int signo)
判定信号signo是否存在信号集中。如果信号集里已有该信号则返回1,否则返回0。如果有错误则返回-1
Definition: los_signal.c:62
STATIC INT32 OsAddSigInfoToTmpList(sig_cb *sigcb, siginfo_t *info)
Definition: los_signal.c:96
size_t bool
Definition: shell_list.h:44
函数调用图:
这是这个函数的调用关系图:

◆ raise()

int raise ( int  sig)

在文件 los_signal.c45 行定义.

46{
47 (VOID)sig;
48 PRINT_ERR("%s NOT SUPPORT\n", __FUNCTION__);
49 errno = ENOSYS;
50 return -1;
51}

◆ SigProcessKillSigHandler()

static int SigProcessKillSigHandler ( LosTaskCB tcb,
void arg 
)
static

进程收到 SIGKILL 信号后,通知任务tcb处理.

在文件 los_signal.c337 行定义.

338{
339 struct ProcessSignalInfo *info = (struct ProcessSignalInfo *)arg;//转参
340
341 return OsPendingTaskWake(tcb, info->sigInfo->si_signo);
342}
函数调用图:
这是这个函数的调用关系图:

◆ SigProcessLoadTcb()

static void SigProcessLoadTcb ( struct ProcessSignalInfo info,
siginfo_t *  sigInfo 
)
static

在文件 los_signal.c345 行定义.

346{
347 LosTaskCB *tcb = NULL;
348
349 if (info->awakenedTcb == NULL && info->receivedTcb == NULL) {//信号即没有指定接收task 也没有指定被唤醒task
350 if (info->unblockedTcb) {//如果进程信号信息体中有阻塞task
351 tcb = info->unblockedTcb;//
352 } else if (info->defaultTcb) {//如果有默认的发送方task
353 tcb = info->defaultTcb;
354 } else {
355 return;
356 }
357 /* Deliver the signal to the selected task */
358 (void)OsTcbDispatch(tcb, sigInfo);//向所选任务发送信号
359 }
360}
LosTaskCB * defaultTcb
Definition: los_task_pri.h:216
LosTaskCB * unblockedTcb
Definition: los_task_pri.h:217
LosTaskCB * receivedTcb
Definition: los_task_pri.h:219
LosTaskCB * awakenedTcb
Definition: los_task_pri.h:218
函数调用图:
这是这个函数的调用关系图:

◆ SigProcessSignalHandler()

static int SigProcessSignalHandler ( LosTaskCB tcb,
void arg 
)
static

信号处理函数,这里就是上面的 handler = SigProcessSignalHandler,见于 OsSigProcessSend

在文件 los_signal.c292 行定义.

293{
294 struct ProcessSignalInfo *info = (struct ProcessSignalInfo *)arg;//先把参数解出来
295 int ret;
296 int isMember;
297
298 if (tcb == NULL) {
299 return 0;
300 }
301
302 /* If the default tcb is not setted, then set this one as default. */
303 if (!info->defaultTcb) {//如果没有默认发送方的任务,即默认参数任务.
304 info->defaultTcb = tcb;
305 }
306
307 isMember = OsSigIsMember(&tcb->sig.sigwaitmask, info->sigInfo->si_signo);//任务是否在等待这个信号
308 if (isMember && (!info->awakenedTcb)) {//是在等待,并尚未向该任务时发送信号时
309 /* This means the task is waiting for this signal. Stop looking for it and use this tcb.
310 * The requirement is: if more than one task in this task group is waiting for the signal,
311 * then only one indeterminate task in the group will receive the signal.
312 */
313 ret = OsTcbDispatch(tcb, info->sigInfo);//发送信号,注意这是给其他任务发送信号,tcb不是当前任务
314 OS_RETURN_IF(ret < 0, ret);//这种写法很有意思
315
316 /* set this tcb as awakenedTcb */
317 info->awakenedTcb = tcb;
318 OS_RETURN_IF(info->receivedTcb != NULL, SIG_STOP_VISIT); /* Stop search */
319 }
320 /* Is this signal unblocked on this thread? */
321 isMember = OsSigIsMember(&tcb->sig.sigprocmask, info->sigInfo->si_signo);//任务是否屏蔽了这个信号
322 if ((!isMember) && (!info->receivedTcb) && (tcb != info->awakenedTcb)) {//没有屏蔽,有唤醒任务没有接收任务.
323 /* if unblockedTcb of this signal is not setted, then set it. */
324 if (!info->unblockedTcb) {
325 info->unblockedTcb = tcb;
326 }
327
328 ret = OsTcbDispatch(tcb, info->sigInfo);//向任务发送信号
329 OS_RETURN_IF(ret < 0, ret);
330 /* set this tcb as receivedTcb */
331 info->receivedTcb = tcb;//设置这个任务为接收任务
332 OS_RETURN_IF(info->awakenedTcb != NULL, SIG_STOP_VISIT); /* Stop search */
333 }
334 return 0; /* Keep searching */
335}
函数调用图:
这是这个函数的调用关系图: