los_signal.c 28.6 KB
Newer Older
1
/*
2 3
 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 *    conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
 *    of conditions and the following disclaimer in the documentation and/or other materials
 *    provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
 *    to endorse or promote products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "los_signal.h"
#include "pthread.h"
#include "los_process_pri.h"
35
#include "los_sched_pri.h"
36 37 38 39 40
#include "los_hw_pri.h"
#include "user_copy.h"
#ifdef LOSCFG_SECURITY_CAPABILITY
#include "capability_api.h"
#endif
41
#include "los_atomic.h"
42

43
#ifdef LOSCFG_KERNEL_VM
44 45 46 47 48 49 50 51 52 53 54 55

int raise(int sig)
{
    (VOID)sig;
    PRINT_ERR("%s NOT SUPPORT\n", __FUNCTION__);
    errno = ENOSYS;
    return -1;
}

#define GETUNMASKSET(procmask, pendFlag) ((~(procmask)) & (sigset_t)(pendFlag))
#define UINT64_BIT_SIZE 64
/****************************************************
56
判定信号signo是否存在信号集中。
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
如果信号集里已有该信号则返回1,否则返回0。如果有错误则返回-1
****************************************************/
int OsSigIsMember(const sigset_t *set, int signo)
{
    int ret = LOS_NOK;
    /* In musl, sig No bits 00000100 present sig No 3, but  1<< 3 = 00001000, so signo needs minus 1 */ 
	//在musl中,sig No bits 00000100表示sig No 3,但是在SIGNO2SET中 1<<3 = 00001000,因此signo需要减1
    signo -= 1;
    /* Verify the signal */
    if (GOOD_SIGNO(signo)) {//有效信号判断
        /* Check if the signal is in the set */
        ret = ((*set & SIGNO2SET((unsigned int)signo)) != 0);//检查信号是否还在集合中
    }

    return ret;
}
73

74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
STATIC VOID OsMoveTmpInfoToUnbInfo(sig_cb *sigcb, INT32 signo)
{
    SigInfoListNode *tmpInfoNode = sigcb->tmpInfoListHead;
    SigInfoListNode **prevHook = &sigcb->tmpInfoListHead;
    INT32 isFirstDel = 1;
    while (tmpInfoNode != NULL) {
        if (tmpInfoNode->info.si_signo == signo) {
            /* In some case, many siginfos have same signo, only last one inserted list need copy to unbinfo. */
            if (isFirstDel) {
		/* copy tmpinfo to unbinfo. */
                (VOID)memcpy_s(&sigcb->sigunbinfo, sizeof(siginfo_t), &tmpInfoNode->info, sizeof(siginfo_t));
                isFirstDel = 0;
            }
	    /* delete tmpinfo from tmpList. */
            *prevHook = tmpInfoNode->next;
            (VOID)LOS_MemFree(m_aucSysMem0, tmpInfoNode);
            tmpInfoNode = *prevHook;
            continue;
        }
        prevHook = &tmpInfoNode->next;
        tmpInfoNode = tmpInfoNode->next;
    }

    return;
}

STATIC INT32 OsAddSigInfoToTmpList(sig_cb *sigcb, siginfo_t *info)
{
    SigInfoListNode *tmp = (SigInfoListNode *)LOS_MemAlloc(m_aucSysMem0, sizeof(SigInfoListNode));
    if (tmp == NULL) {
        return LOS_NOK;
    }
    (VOID)memcpy_s(&tmp->info, sizeof(siginfo_t), info, sizeof(siginfo_t));
    tmp->next = sigcb->tmpInfoListHead;
    sigcb->tmpInfoListHead = tmp;

    return LOS_OK;
}

VOID OsClearSigInfoTmpList(sig_cb *sigcb)
{
    while (sigcb->tmpInfoListHead != NULL) {
        SigInfoListNode *tmpInfoNode = sigcb->tmpInfoListHead;
        sigcb->tmpInfoListHead = sigcb->tmpInfoListHead->next;
        (VOID)LOS_MemFree(m_aucSysMem0, tmpInfoNode);
    }
}
121 122 123 124 125
STATIC INLINE VOID OsSigWaitTaskWake(LosTaskCB *taskCB, INT32 signo)
{
    sig_cb *sigcb = &taskCB->sig;

    if (!LOS_ListEmpty(&sigcb->waitList) && OsSigIsMember(&sigcb->sigwaitmask, signo)) {
126
        OsMoveTmpInfoToUnbInfo(sigcb, signo);
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
        OsTaskWakeClearPendMask(taskCB);
        OsSchedTaskWake(taskCB);
        OsSigEmptySet(&sigcb->sigwaitmask);
    }
}

STATIC UINT32 OsPendingTaskWake(LosTaskCB *taskCB, INT32 signo)
{
    if (!OsTaskIsPending(taskCB) || !OsProcessIsUserMode(OS_PCB_FROM_PID(taskCB->processID))) {
        return 0;
    }

    if ((signo != SIGKILL) && (taskCB->waitFlag != OS_TASK_WAIT_SIGNAL)) {
        return 0;
    }

    switch (taskCB->waitFlag) {
        case OS_TASK_WAIT_PROCESS:
        case OS_TASK_WAIT_GID:
        case OS_TASK_WAIT_ANYPROCESS:
            OsWaitWakeTask(taskCB, OS_INVALID_VALUE);
            break;
        case OS_TASK_WAIT_JOIN:
            OsTaskWakeClearPendMask(taskCB);
            OsSchedTaskWake(taskCB);
            break;
        case OS_TASK_WAIT_SIGNAL:
            OsSigWaitTaskWake(taskCB, signo);
            break;
156
#ifdef LOSCFG_KERNEL_LITEIPC
157 158 159 160 161
        case OS_TASK_WAIT_LITEIPC:
            taskCB->ipcStatus &= ~IPC_THREAD_STATUS_PEND;
            OsTaskWakeClearPendMask(taskCB);
            OsSchedTaskWake(taskCB);
            break;
162
#endif
163 164 165 166 167 168 169 170 171 172 173
        case OS_TASK_WAIT_FUTEX:
            OsFutexNodeDeleteFromFutexHash(&taskCB->futex, TRUE, NULL, NULL);
            OsTaskWakeClearPendMask(taskCB);
            OsSchedTaskWake(taskCB);
            break;
        default:
            break;
    }

    return 0;
}
174 175 176 177 178 179 180 181
//给任务(线程)发送一个信号
int OsTcbDispatch(LosTaskCB *stcb, siginfo_t *info)
{
    bool masked = FALSE;
    sig_cb *sigcb = &stcb->sig;

    OS_RETURN_IF_NULL(sigcb);
    /* If signo is 0, not send signal, just check process or pthread exist */
182
    if (info->si_signo == 0) {//如果信号为0,则不发送信号,只是作为检查进程和线程是否还存在.
183 184 185
        return 0;
    }
    masked = (bool)OsSigIsMember(&sigcb->sigprocmask, info->si_signo);//@note_thinking 这里还有 masked= -1的情况要处理!!!
186
    if (masked) {//如果信号被屏蔽了,要看等待信号集,sigwaitmask
187
        /* If signal is in wait list and mask list, need unblock it */ //如果信号在等待列表和掩码列表中,需要解除阻止
188 189
        if (LOS_ListEmpty(&sigcb->waitList)  ||
           (!LOS_ListEmpty(&sigcb->waitList) && !OsSigIsMember(&sigcb->sigwaitmask, info->si_signo))) {
190
            OsSigAddSet(&sigcb->sigPendFlag, info->si_signo);//将信号加入阻塞集
191
        }
192
    } else {//信号没有被屏蔽的处理
193
        /* unmasked signal actions */
194
        OsSigAddSet(&sigcb->sigFlag, info->si_signo);//不屏蔽的信号集
195
    }
196 197 198 199

    if (OsAddSigInfoToTmpList(sigcb, info) == LOS_NOK) {
        return -ENOMEM;
    }
200 201

    return OsPendingTaskWake(stcb, info->si_signo);
202 203 204 205 206 207 208
}

void OsSigMaskSwitch(LosTaskCB * const rtcb, sigset_t set)
{
    sigset_t unmaskset;

    rtcb->sig.sigprocmask = set;
209
    unmaskset = GETUNMASKSET(rtcb->sig.sigprocmask, rtcb->sig.sigPendFlag);//过滤出没有被屏蔽的信号集
210 211
    if (unmaskset != NULL_SIGNAL_SET) {
        /* pendlist do */
212 213
        rtcb->sig.sigFlag |= unmaskset;	//加入不屏蔽信号集
        rtcb->sig.sigPendFlag ^= unmaskset;//从阻塞集中去掉unmaskset
214 215
    }
}
216
/******************************************************************
217
向信号集设置信号屏蔽的方法
218 219 220 221
	SIG_BLOCK:将set指向信号集中的信号,添加到进程阻塞信号集;
	SIG_UNBLOCK:将set指向信号集中的信号,从进程阻塞信号集删除;
	SIG_SETMASK:将set指向信号集中的信号,设置成进程阻塞信号集;
*******************************************************************/
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
int OsSigprocMask(int how, const sigset_t_l *setl, sigset_t_l *oldset)
{
    LosTaskCB *spcb = NULL;
    sigset_t oldSigprocmask;
    int ret = LOS_OK;
    unsigned int intSave;
    sigset_t set;
    int retVal;

    if (setl != NULL) {
        retVal = LOS_ArchCopyFromUser(&set, &(setl->sig[0]), sizeof(sigset_t));
        if (retVal != 0) {
            return -EFAULT;
        }
    }
    SCHEDULER_LOCK(intSave);
    spcb = OsCurrTaskGet();
    /* If requested, copy the old mask to user. */ //如果需要,请将旧掩码复制给用户
    oldSigprocmask = spcb->sig.sigprocmask;

    /* If requested, modify the current signal mask. */ //如有要求,修改当前信号屏蔽
    if (setl != NULL) {
        /* Okay, determine what we are supposed to do */
        switch (how) {
            /* Set the union of the current set and the signal
             * set pointed to by set as the new sigprocmask.
             */
            case SIG_BLOCK:
                spcb->sig.sigprocmask |= set;//增加信号屏蔽位
                break;
            /* Set the intersection of the current set and the
             * signal set pointed to by set as the new sigprocmask.
             */
            case SIG_UNBLOCK:
                spcb->sig.sigprocmask &= ~(set);//解除信号屏蔽位
                break;
            /* Set the signal set pointed to by set as the new sigprocmask. */
            case SIG_SETMASK:
                spcb->sig.sigprocmask = set;//设置一个新的屏蔽掩码
                break;
            default:
                ret = -EINVAL;
                break;
        }
        /* If pending mask not in sigmask, need set sigflag. */
267
        OsSigMaskSwitch(spcb, spcb->sig.sigprocmask);//更新与屏蔽信号相关的变量
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
    }
    SCHEDULER_UNLOCK(intSave);

    if (oldset != NULL) {
        retVal = LOS_ArchCopyToUser(&(oldset->sig[0]), &oldSigprocmask, sizeof(sigset_t));
        if (retVal != 0) {
            return -EFAULT;
        }
    }
    return ret;
}
//让进程的每一个task执行参数函数
int OsSigProcessForeachChild(LosProcessCB *spcb, ForEachTaskCB handler, void *arg)
{
    int ret;

284
    /* Visit the main thread last (if present) */
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
    LosTaskCB *taskCB = NULL;//遍历进程的 threadList 链表,里面存放的都是task节点
    LOS_DL_LIST_FOR_EACH_ENTRY(taskCB, &(spcb->threadSiblingList), LosTaskCB, threadList) {//遍历进程的任务列表
        ret = handler(taskCB, arg);//回调参数函数
        OS_RETURN_IF(ret != 0, ret);//这个宏的意思就是只有ret = 0时,啥也不处理.其余就返回 ret
    }
    return LOS_OK;
}
//信号处理函数,这里就是上面的 handler =  SigProcessSignalHandler,见于 OsSigProcessSend
static int SigProcessSignalHandler(LosTaskCB *tcb, void *arg)
{
    struct ProcessSignalInfo *info = (struct ProcessSignalInfo *)arg;//先把参数解出来
    int ret;
    int isMember;

    if (tcb == NULL) {
        return 0;
    }

    /* If the default tcb is not setted, then set this one as default. */
304
    if (!info->defaultTcb) {//如果没有默认发送方的任务,即默认参数任务.
305 306 307
        info->defaultTcb = tcb;
    }

308 309
    isMember = OsSigIsMember(&tcb->sig.sigwaitmask, info->sigInfo->si_signo);//任务是否在等待这个信号
    if (isMember && (!info->awakenedTcb)) {//是在等待,并尚未向该任务时发送信号时
310 311 312 313
        /* This means the task is waiting for this signal. Stop looking for it and use this tcb.
         * The requirement is: if more than one task in this task group is waiting for the signal,
         * then only one indeterminate task in the group will receive the signal.
         */
314
        ret = OsTcbDispatch(tcb, info->sigInfo);//发送信号,注意这是给其他任务发送信号,tcb不是当前任务
315 316 317 318 319 320 321
        OS_RETURN_IF(ret < 0, ret);//这种写法很有意思

        /* set this tcb as awakenedTcb */
        info->awakenedTcb = tcb;
        OS_RETURN_IF(info->receivedTcb != NULL, SIG_STOP_VISIT); /* Stop search */
    }
    /* Is this signal unblocked on this thread? */
322 323
    isMember = OsSigIsMember(&tcb->sig.sigprocmask, info->sigInfo->si_signo);//任务是否屏蔽了这个信号
    if ((!isMember) && (!info->receivedTcb) && (tcb != info->awakenedTcb)) {//没有屏蔽,有唤醒任务没有接收任务.
324 325 326 327 328
        /* if unblockedTcb of this signal is not setted, then set it. */
        if (!info->unblockedTcb) {
            info->unblockedTcb = tcb;
        }

329
        ret = OsTcbDispatch(tcb, info->sigInfo);//向任务发送信号
330 331
        OS_RETURN_IF(ret < 0, ret);
        /* set this tcb as receivedTcb */
332
        info->receivedTcb = tcb;//设置这个任务为接收任务
333 334 335 336
        OS_RETURN_IF(info->awakenedTcb != NULL, SIG_STOP_VISIT); /* Stop search */
    }
    return 0; /* Keep searching */
}
337
//进程收到 SIGKILL 信号后,通知任务tcb处理.
338 339 340 341
static int SigProcessKillSigHandler(LosTaskCB *tcb, void *arg)
{
    struct ProcessSignalInfo *info = (struct ProcessSignalInfo *)arg;//转参

342
    return OsPendingTaskWake(tcb, info->sigInfo->si_signo);
343
}
344

345
//处理信号发送
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
static void SigProcessLoadTcb(struct ProcessSignalInfo *info, siginfo_t *sigInfo)
{
    LosTaskCB *tcb = NULL;

    if (info->awakenedTcb == NULL && info->receivedTcb == NULL) {//信号即没有指定接收task 也没有指定被唤醒task
        if (info->unblockedTcb) {//如果进程信号信息体中有阻塞task
            tcb = info->unblockedTcb;//
        } else if (info->defaultTcb) {//如果有默认的发送方task
            tcb = info->defaultTcb;
        } else {
            return;
        }
        /* Deliver the signal to the selected task */
        (void)OsTcbDispatch(tcb, sigInfo);//向所选任务发送信号
    }
}
//给参数进程发送参数信号
int OsSigProcessSend(LosProcessCB *spcb, siginfo_t *sigInfo)
{
    int ret;
    struct ProcessSignalInfo info = {
        .sigInfo = sigInfo, //信号内容
368
        .defaultTcb = NULL, //以下四个值将在OsSigProcessForeachChild中根据条件完善
369 370 371 372
        .unblockedTcb = NULL,
        .awakenedTcb = NULL,
        .receivedTcb = NULL
    };
373 374
	//总之是要从进程中找个至少一个任务来接受这个信号,优先级
	//awakenedTcb > receivedTcb > unblockedTcb > defaultTcb
375 376 377
    if (info.sigInfo == NULL){
        return -EFAULT;
    }
378
    /* visit all taskcb and dispatch signal */ //访问所有任务和分发信号
379
    if (info.sigInfo->si_signo == SIGKILL) {//需要干掉进程时 SIGKILL = 9, #linux kill 9 14
380
        OsSigAddSet(&spcb->sigShare, info.sigInfo->si_signo);//信号集中增加信号
381
        (void)OsSigProcessForeachChild(spcb, SigProcessKillSigHandler, &info);
382 383
        return 0;
    } else {
384
        ret = OsSigProcessForeachChild(spcb, SigProcessSignalHandler, &info);//进程通知所有task处理信号
385 386 387 388
    }
    if (ret < 0) {
        return ret;
    }
389
    SigProcessLoadTcb(&info, sigInfo);//确保能给一个任务发送信号
390 391
    return 0;
}
392
//信号集全部清0
393 394 395 396 397 398
int OsSigEmptySet(sigset_t *set)
{
    *set = NULL_SIGNAL_SET;
    return 0;
}

399
/* Privilege process can't send to kernel and privilege process */ //内核进程组和用户特权进程组无法发送
400 401 402 403 404 405 406 407 408 409 410 411
static int OsSignalPermissionToCheck(const LosProcessCB *spcb)
{
    UINT32 gid = spcb->group->groupID;

    if (gid == OS_KERNEL_PROCESS_GROUP) {//内核进程组
        return -EPERM;
    } else if (gid == OS_USER_PRIVILEGE_PROCESS_GROUP) {//用户特权进程组
        return -EPERM;
    }

    return 0;
}
412
//信号分发,发送信号权限/进程组过滤.
413 414
int OsDispatch(pid_t pid, siginfo_t *info, int permission)
{
415 416 417
    if (OsProcessIDUserCheckInvalid(pid) || pid < 0) {
        return -ESRCH;
    }
418
    LosProcessCB *spcb = OS_PCB_FROM_PID(pid);//找到这个进程
419
    if (OsProcessIsUnused(spcb)) {//进程是否还在使用,不一定是当前进程但必须是个有效进程
420 421 422 423
        return -ESRCH;
    }

    /* If the process you want to kill had been inactive, but still exist. should return LOS_OK */
424
    if (OsProcessIsInactive(spcb)) {//不向非活动进程发送信息,但返回OK
425 426 427
        return LOS_OK;
    }

428 429
#ifdef LOSCFG_SECURITY_CAPABILITY	//启用能力安全模式
    LosProcessCB *current = OsCurrProcessGet();//获取当前进程,检查当前进程是否有发送信号的权限.
430 431 432 433 434 435 436
    /* Kernel process always has kill permission and user process should check permission *///内核进程总是有kill权限,用户进程需要检查权限
    if (OsProcessIsUserMode(current) && !(current->processStatus & OS_PROCESS_FLAG_EXIT)) {//用户进程检查能力范围
        if ((current != spcb) && (!IsCapPermit(CAP_KILL)) && (current->user->userID != spcb->user->userID)) {
            return -EPERM;
        }
    }
#endif
437
    if ((permission == OS_USER_KILL_PERMISSION) && (OsSignalPermissionToCheck(spcb) < 0)) {
438 439 440 441 442
        return -EPERM;
    }
    return OsSigProcessSend(spcb, info);//给参数进程发送信号
}
/************************************************
443
用于向进程或进程组发送信号
444 445 446 447 448 449 450 451 452
shell命令 kill 14 7(kill -14 7效果相同)
发送信号14(SIGALRM默认行为为进程终止)给7号进程
************************************************/
int OsKill(pid_t pid, int sig, int permission)
{
    siginfo_t info;
    int ret;

    /* Make sure that the para is valid */
453
    if (!GOOD_SIGNO(sig)) {
454 455 456 457 458 459 460 461
        return -EINVAL;
    }

    /* Create the siginfo structure */ //创建信号结构体
    info.si_signo = sig;	//信号编号
    info.si_code = SI_USER;	//来自用户进程信号
    info.si_value.sival_ptr = NULL;

462 463
    if (pid > 0) {
        /* Send the signal to the specify process */
464
    ret = OsDispatch(pid, &info, permission);//发送信号
465 466 467 468 469 470 471 472 473
    } else if (pid == -1) {
        /* Send SIG to all processes */
        ret = OsSendSignalToAllProcess(&info, permission);
    } else {
        /* Send SIG to all processes in process group PGRP.
           If PGRP is zero, send SIG to all processes in
           the current process's process group. */
        ret = OsSendSignalToProcessGroup(pid, &info, permission);
    }
474 475
    return ret;
}
476
//给发送信号过程加锁
477 478 479 480 481 482
int OsKillLock(pid_t pid, int sig)
{
    int ret;
    unsigned int intSave;

    SCHEDULER_LOCK(intSave);
483
    ret = OsKill(pid, sig, OS_USER_KILL_PERMISSION);//用户权限向进程发送信号
484 485 486
    SCHEDULER_UNLOCK(intSave);
    return ret;
}
487
INT32 OsTaskKillUnsafe(UINT32 taskID, INT32 signo)
488 489
{
    siginfo_t info;
490 491 492 493 494
    LosTaskCB *taskCB = OsGetTaskCB(taskID);
    INT32 ret = OsUserTaskOperatePermissionsCheck(taskCB);
    if (ret != LOS_OK) {
        return -ret;
    }
495

496 497 498 499 500 501 502 503 504 505 506 507
    /* Create the siginfo structure */
    info.si_signo = signo;
    info.si_code = SI_USER;
    info.si_value.sival_ptr = NULL;

    /* Dispatch the signal to thread, bypassing normal task group thread
     * dispatch rules. */
    return OsTcbDispatch(taskCB, &info);
}
//发送信号
int OsPthreadKill(UINT32 tid, int signo)
{
508 509 510 511 512 513 514 515 516 517 518
    int ret;
    UINT32 intSave;

    /* Make sure that the signal is valid */
    OS_RETURN_IF(!GOOD_SIGNO(signo), -EINVAL);
    if (OS_TID_CHECK_INVALID(tid)) {
        return -ESRCH;
    }

    /* Keep things stationary through the following */
    SCHEDULER_LOCK(intSave);
519
    ret = OsTaskKillUnsafe(tid, signo);
520 521 522
    SCHEDULER_UNLOCK(intSave);
    return ret;
}
523
//向信号集中加入signo信号
524 525 526 527 528 529 530
int OsSigAddSet(sigset_t *set, int signo)
{
    /* Verify the signal */
    if (!GOOD_SIGNO(signo)) {
        return -EINVAL;
    } else {
        /* In musl, sig No bits 00000100 present sig No 3, but  1<< 3 = 00001000, so signo needs minus 1 */
531
        signo -= 1;// 信号范围是 [1 ~ 64 ],而保存变量位的范围是[0 ~ 63]
532
        /* Add the signal to the set */
533
        *set |= SIGNO2SET((unsigned int)signo);//填充信号集
534 535 536
        return LOS_OK;
    }
}
537
//获取阻塞当前任务的信号集
538 539 540 541 542 543 544 545 546 547 548
int OsSigPending(sigset_t *set)
{
    LosTaskCB *tcb = NULL;
    unsigned int intSave;

    if (set == NULL) {
        return -EFAULT;
    }

    SCHEDULER_LOCK(intSave);
    tcb = OsCurrTaskGet();
549
    *set = tcb->sig.sigPendFlag;//被阻塞的信号集
550 551 552 553 554 555 556 557 558 559 560 561 562 563
    SCHEDULER_UNLOCK(intSave);
    return LOS_OK;
}

STATIC int FindFirstSetedBit(UINT64 n)
{
    int count;

    if (n == 0) {
        return -1;
    }
    for (count = 0; (count < UINT64_BIT_SIZE) && (n ^ 1ULL); n >>= 1, count++) {}
    return (count < UINT64_BIT_SIZE) ? count : (-1);
}
564
//等待信号时间
565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581
int OsSigTimedWaitNoLock(sigset_t *set, siginfo_t *info, unsigned int timeout)
{
    LosTaskCB *task = NULL;
    sig_cb *sigcb = NULL;
    int ret;

    task = OsCurrTaskGet();
    sigcb = &task->sig;

    if (sigcb->waitList.pstNext == NULL) {
        LOS_ListInit(&sigcb->waitList);//初始化信号等待链表
    }
    /* If pendingflag & set > 0, shound clear pending flag */
    sigset_t clear = sigcb->sigPendFlag & *set;
    if (clear) {
        sigcb->sigPendFlag ^= clear;
        ret = FindFirstSetedBit((UINT64)clear) + 1;
582
        OsMoveTmpInfoToUnbInfo(sigcb, ret);
583 584 585 586 587
    } else {
        OsSigAddSet(set, SIGKILL);//kill 9 14 必须要处理
        OsSigAddSet(set, SIGSTOP);//终止进程的信号也必须处理

        sigcb->sigwaitmask |= *set;//按位加到等待集上,也就是说sigwaitmask的信号来了都是要处理的.
588 589
        OsTaskWaitSetPendMask(OS_TASK_WAIT_SIGNAL, sigcb->sigwaitmask, timeout);
        ret = OsSchedTaskWait(&sigcb->waitList, timeout, TRUE);
590 591 592 593 594 595
        if (ret == LOS_ERRNO_TSK_TIMEOUT) {
            ret = -EAGAIN;
        }
        sigcb->sigwaitmask = NULL_SIGNAL_SET;
    }
    if (info != NULL) {
596
        (VOID)memcpy_s(info, sizeof(siginfo_t), &sigcb->sigunbinfo, sizeof(siginfo_t));
597 598 599
    }
    return ret;
}
600
//让当前任务等待的信号
601 602 603 604 605 606 607
int OsSigTimedWait(sigset_t *set, siginfo_t *info, unsigned int timeout)
{
    int ret;
    unsigned int intSave;

    SCHEDULER_LOCK(intSave);

608
    ret = OsSigTimedWaitNoLock(set, info, timeout);//以不加锁的方式等待
609 610 611 612

    SCHEDULER_UNLOCK(intSave);
    return ret;
}
鸿蒙内核源码分析's avatar
鸿蒙内核源码分析 已提交
613
//通过信号挂起当前任务
614 615 616 617 618 619 620 621 622
int OsPause(void)
{
    LosTaskCB *spcb = NULL;
    sigset_t oldSigprocmask;

    spcb = OsCurrTaskGet();
    oldSigprocmask = spcb->sig.sigprocmask;
    return OsSigSuspend(&oldSigprocmask);
}
623
//用参数set代替进程的原有掩码,并暂停进程执行,直到收到信号再恢复原有掩码并继续执行进程。
624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
int OsSigSuspend(const sigset_t *set)
{
    unsigned int intSave;
    LosTaskCB *rtcb = NULL;
    sigset_t setSuspend;
    int ret;

    if (set == NULL) {
        return -EINVAL;
    }
    SCHEDULER_LOCK(intSave);
    rtcb = OsCurrTaskGet();

    /* Wait signal calc */
    setSuspend = FULL_SIGNAL_SET & (~(*set));

    /* If pending mask not in sigmask, need set sigflag */
    OsSigMaskSwitch(rtcb, *set);
642 643 644 645 646 647 648 649 650 651 652 653 654 655 656

    if (rtcb->sig.sigFlag > 0) {
        SCHEDULER_UNLOCK(intSave);

        /*
         * If rtcb->sig.sigFlag > 0, it means that some signal have been
         * received, and we need to do schedule to handle the signal directly.
         */
        LOS_Schedule();
        return -EINTR;
    } else {
        ret = OsSigTimedWaitNoLock(&setSuspend, NULL, LOS_WAIT_FOREVER);
        if (ret < 0) {
            PRINT_ERR("FUNC %s LINE = %d, ret = %x\n", __FUNCTION__, __LINE__, ret);
        }
657 658 659 660 661 662
    }

    SCHEDULER_UNLOCK(intSave);
    return -EINTR;
}
/**************************************************
663
信号安装,函数用于改变进程接收到特定信号后的行为。
664
sig:信号的值,可以为除SIGKILL及SIGSTOP外的任何一个特定有效的信号(为这两个信号定义自己的处理函数,将导致信号安装错误)。
665 666
act:设置对signal信号的新处理方式。
oldact:原来对信号的处理方式。
667
如果把第二、第三个参数都设为NULL,那么该函数可用于检查信号的有效性。
668
返回值:0 表示成功,-1 表示有错误发生。
669 670 671 672 673 674 675 676 677
**************************************************/
int OsSigAction(int sig, const sigaction_t *act, sigaction_t *oact)
{
    UINTPTR addr;
    sigaction_t action;

    if (!GOOD_SIGNO(sig) || sig < 1 || act == NULL) {
        return -EINVAL;
    }
678 679 680 681 682
	//将数据从用户空间拷贝到内核空间
	if (LOS_ArchCopyFromUser(&action, act, sizeof(sigaction_t)) != LOS_OK) {
		return -EFAULT;
	}
	
683 684
	if (sig == SIGSYS) {//鸿蒙此处通过错误的系统调用 来安装信号处理函数,有点巧妙. 
		addr = OsGetSigHandler();//是否已存在信号处理函数
685 686 687 688
		if (addr == 0) {//进程没有设置信号处理函数时
			OsSetSigHandler((unsigned long)(UINTPTR)action.sa_handler);//设置进程信号处理函数
			//void (*sa_handler)(int); //信号处理函数——普通版
			//void (*sa_sigaction)(int, siginfo_t *, void *);//信号处理函数——高级版
689 690 691 692 693 694 695
            return LOS_OK;
        }
        return -EINVAL;
    }

    return LOS_OK;
}
696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711

VOID OsSigIntLock(VOID)
{
    LosTaskCB *task = OsCurrTaskGet();
    sig_cb *sigcb = &task->sig;

    (VOID)LOS_AtomicAdd((Atomic *)&sigcb->sigIntLock, 1);
}

VOID OsSigIntUnlock(VOID)
{
    LosTaskCB *task = OsCurrTaskGet();
    sig_cb *sigcb = &task->sig;

    (VOID)LOS_AtomicSub((Atomic *)&sigcb->sigIntLock, 1);
}
712 713
/**********************************************
产生系统调用时,也就是软中断时,保存用户栈寄存器现场信息
714
改写PC寄存器的值
715
**********************************************/
716
VOID *OsSaveSignalContext(VOID *sp, VOID *newSp)
717 718 719
{
    UINTPTR sigHandler;
    UINT32 intSave;
720 721 722
    LosTaskCB *task = OsCurrTaskGet();
    LosProcessCB *process = OsCurrProcessGet();
    sig_cb *sigcb = &task->sig;
723

724 725 726 727 728 729 730 731 732 733
    /* A thread is not allowed to interrupt the processing of its signals during a system call */
    if (sigcb->sigIntLock > 0) {
        return sp;
    }

    if (task->taskStatus & OS_TASK_FLAG_EXIT_KILL) {
        OsTaskToExit(task, 0);
        return sp;
    }

734 735 736 737
    SCHEDULER_LOCK(intSave);
    if ((sigcb->count == 0) && ((sigcb->sigFlag != 0) || (process->sigShare != 0))) {
        sigHandler = OsGetSigHandler();
        if (sigHandler == 0) {
738 739 740 741
            sigcb->sigFlag = 0;
            process->sigShare = 0;
            SCHEDULER_UNLOCK(intSave);
            PRINT_ERR("The signal processing function for the current process pid =%d is NULL!\n", task->processID);
742
            return sp;
743
        }
744 745 746 747
        /* One pthread do the share signal */
        sigcb->sigFlag |= process->sigShare;
        UINT32 signo = (UINT32)FindFirstSetedBit(sigcb->sigFlag) + 1;
        UINT32 sigVal = (UINT32)(UINTPTR)(sigcb->sigunbinfo.si_value.sival_ptr);
748
        OsMoveTmpInfoToUnbInfo(sigcb, signo);
749 750 751 752 753
        OsProcessExitCodeSignalSet(process, signo);
        sigcb->sigContext = sp;

        OsInitSignalContext(sp, newSp, sigHandler, signo, sigVal);

754 755
        /* sig No bits 00000100 present sig No 3, but  1<< 3 = 00001000, so signo needs minus 1 */
        sigcb->sigFlag ^= 1ULL << (signo - 1);
756 757 758
        sigcb->count++;
        SCHEDULER_UNLOCK(intSave);
        return newSp;
759 760 761
    }

    SCHEDULER_UNLOCK(intSave);
762
    return sp;
763 764
}

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

776 777
    LosTaskCB *task = OsCurrTaskGet();
    sig_cb *sigcb = &task->sig;
778

779 780
    SCHEDULER_LOCK(intSave);
    if (sigcb->count != 1) {
781
        SCHEDULER_UNLOCK(intSave);
782 783 784 785 786 787
        PRINT_ERR("sig error count : %d\n", sigcb->count);
        return sp;
    }

    LosProcessCB *process = OsCurrProcessGet();
    VOID *saveContext = sigcb->sigContext;
鸿蒙内核源码分析's avatar
鸿蒙内核源码分析 已提交
788
    sigcb->sigContext = NULL;
789
    sigcb->count--;
790 791
    process->sigShare = 0;	//回到用户态,信号共享清0
    OsProcessExitCodeSignalClear(process);//清空进程退出码
792
    SCHEDULER_UNLOCK(intSave);
793
    return saveContext;
794 795
}

796
#endif