los_signal.c 28.7 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
STATIC VOID OsMoveTmpInfoToUnbInfo(sig_cb *sigcb, INT32 signo)
{
    SigInfoListNode *tmpInfoNode = sigcb->tmpInfoListHead;
    SigInfoListNode **prevHook = &sigcb->tmpInfoListHead;
    while (tmpInfoNode != NULL) {
        if (tmpInfoNode->info.si_signo == signo) {
80 81 82
            /* copy tmpinfo to unbinfo. */
            (VOID)memcpy_s(&sigcb->sigunbinfo, sizeof(siginfo_t), &tmpInfoNode->info, sizeof(siginfo_t));
            /* delete tmpinfo from tmpList. */
83 84 85
            *prevHook = tmpInfoNode->next;
            (VOID)LOS_MemFree(m_aucSysMem0, tmpInfoNode);
            tmpInfoNode = *prevHook;
86
            break;
87 88 89 90 91 92 93 94
        }
        prevHook = &tmpInfoNode->next;
        tmpInfoNode = tmpInfoNode->next;
    }
}

STATIC INT32 OsAddSigInfoToTmpList(sig_cb *sigcb, siginfo_t *info)
{
95 96 97 98 99 100 101 102 103 104
    /* try to find the old siginfo */
    SigInfoListNode *tmp = sigcb->tmpInfoListHead;
    while (tmp != NULL) {
        if (tmp->info.si_signo == info->si_signo) {
            /* found it, break. */
            break;
        }
        tmp = tmp->next;
    }

105
    if (tmp == NULL) {
106 107 108 109 110 111 112
        /* none, alloc new one */
        tmp = (SigInfoListNode *)LOS_MemAlloc(m_aucSysMem0, sizeof(SigInfoListNode));
        if (tmp == NULL) {
            return LOS_NOK;
        }
        tmp->next = sigcb->tmpInfoListHead;
        sigcb->tmpInfoListHead = tmp;
113
    }
114

115 116 117 118 119 120 121 122 123 124 125 126 127
    (VOID)memcpy_s(&tmp->info, sizeof(siginfo_t), info, sizeof(siginfo_t));

    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);
    }
}
128 129 130 131 132
STATIC INLINE VOID OsSigWaitTaskWake(LosTaskCB *taskCB, INT32 signo)
{
    sig_cb *sigcb = &taskCB->sig;

    if (!LOS_ListEmpty(&sigcb->waitList) && OsSigIsMember(&sigcb->sigwaitmask, signo)) {
133
        OsMoveTmpInfoToUnbInfo(sigcb, signo);
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
        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;
        case OS_TASK_WAIT_LITEIPC:
            OsTaskWakeClearPendMask(taskCB);
            OsSchedTaskWake(taskCB);
            break;
        case OS_TASK_WAIT_FUTEX:
            OsFutexNodeDeleteFromFutexHash(&taskCB->futex, TRUE, NULL, NULL);
            OsTaskWakeClearPendMask(taskCB);
            OsSchedTaskWake(taskCB);
            break;
        default:
            break;
    }

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

    if (OsAddSigInfoToTmpList(sigcb, info) == LOS_NOK) {
        return -ENOMEM;
    }
204 205

    return OsPendingTaskWake(stcb, info->si_signo);
206 207 208 209 210 211 212
}

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

    rtcb->sig.sigprocmask = set;
213
    unmaskset = GETUNMASKSET(rtcb->sig.sigprocmask, rtcb->sig.sigPendFlag);//过滤出没有被屏蔽的信号集
214 215
    if (unmaskset != NULL_SIGNAL_SET) {
        /* pendlist do */
216 217
        rtcb->sig.sigFlag |= unmaskset;	//加入不屏蔽信号集
        rtcb->sig.sigPendFlag ^= unmaskset;//从阻塞集中去掉unmaskset
218 219
    }
}
220
/******************************************************************
221
向信号集设置信号屏蔽的方法
222 223 224 225
	SIG_BLOCK:将set指向信号集中的信号,添加到进程阻塞信号集;
	SIG_UNBLOCK:将set指向信号集中的信号,从进程阻塞信号集删除;
	SIG_SETMASK:将set指向信号集中的信号,设置成进程阻塞信号集;
*******************************************************************/
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 267 268 269 270
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. */
271
        OsSigMaskSwitch(spcb, spcb->sig.sigprocmask);//更新与屏蔽信号相关的变量
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
    }
    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;

288
    /* Visit the main thread last (if present) */
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
    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. */
308
    if (!info->defaultTcb) {//如果没有默认发送方的任务,即默认参数任务.
309 310 311
        info->defaultTcb = tcb;
    }

312 313
    isMember = OsSigIsMember(&tcb->sig.sigwaitmask, info->sigInfo->si_signo);//任务是否在等待这个信号
    if (isMember && (!info->awakenedTcb)) {//是在等待,并尚未向该任务时发送信号时
314 315 316 317
        /* 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.
         */
318
        ret = OsTcbDispatch(tcb, info->sigInfo);//发送信号,注意这是给其他任务发送信号,tcb不是当前任务
319 320 321 322 323 324 325
        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? */
326 327
    isMember = OsSigIsMember(&tcb->sig.sigprocmask, info->sigInfo->si_signo);//任务是否屏蔽了这个信号
    if ((!isMember) && (!info->receivedTcb) && (tcb != info->awakenedTcb)) {//没有屏蔽,有唤醒任务没有接收任务.
328 329 330 331 332
        /* if unblockedTcb of this signal is not setted, then set it. */
        if (!info->unblockedTcb) {
            info->unblockedTcb = tcb;
        }

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

346
    return OsPendingTaskWake(tcb, info->sigInfo->si_signo);
347
}
348

349
//处理信号发送
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
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, //信号内容
372
        .defaultTcb = NULL, //以下四个值将在OsSigProcessForeachChild中根据条件完善
373 374 375 376
        .unblockedTcb = NULL,
        .awakenedTcb = NULL,
        .receivedTcb = NULL
    };
377 378
	//总之是要从进程中找个至少一个任务来接受这个信号,优先级
	//awakenedTcb > receivedTcb > unblockedTcb > defaultTcb
379 380 381
    if (info.sigInfo == NULL){
        return -EFAULT;
    }
382
    /* visit all taskcb and dispatch signal */ //访问所有任务和分发信号
383
    if (info.sigInfo->si_signo == SIGKILL) {//需要干掉进程时 SIGKILL = 9, #linux kill 9 14
384
        OsSigAddSet(&spcb->sigShare, info.sigInfo->si_signo);//信号集中增加信号
385
        (void)OsSigProcessForeachChild(spcb, SigProcessKillSigHandler, &info);
386 387
        return 0;
    } else {
388
        ret = OsSigProcessForeachChild(spcb, SigProcessSignalHandler, &info);//进程通知所有task处理信号
389 390 391 392
    }
    if (ret < 0) {
        return ret;
    }
393
    SigProcessLoadTcb(&info, sigInfo);//确保能给一个任务发送信号
394 395
    return 0;
}
396
//信号集全部清0
397 398 399 400 401 402
int OsSigEmptySet(sigset_t *set)
{
    *set = NULL_SIGNAL_SET;
    return 0;
}

403
/* Privilege process can't send to kernel and privilege process */ //内核进程组和用户特权进程组无法发送
404 405 406 407 408 409 410 411 412 413 414 415
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;
}
416
//信号分发,发送信号权限/进程组过滤.
417 418
int OsDispatch(pid_t pid, siginfo_t *info, int permission)
{
419 420 421
    if (OsProcessIDUserCheckInvalid(pid) || pid < 0) {
        return -ESRCH;
    }
422
    LosProcessCB *spcb = OS_PCB_FROM_PID(pid);//找到这个进程
423
    if (OsProcessIsUnused(spcb)) {//进程是否还在使用,不一定是当前进程但必须是个有效进程
424 425 426 427
        return -ESRCH;
    }

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

432 433
#ifdef LOSCFG_SECURITY_CAPABILITY	//启用能力安全模式
    LosProcessCB *current = OsCurrProcessGet();//获取当前进程,检查当前进程是否有发送信号的权限.
434 435 436 437 438 439 440
    /* 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
441
    if ((permission == OS_USER_KILL_PERMISSION) && (OsSignalPermissionToCheck(spcb) < 0)) {
442 443 444 445 446
        return -EPERM;
    }
    return OsSigProcessSend(spcb, info);//给参数进程发送信号
}
/************************************************
447
用于向进程或进程组发送信号
448 449 450 451 452 453 454 455 456
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 */
457
    if (!GOOD_SIGNO(sig)) {
458 459 460 461 462 463 464 465
        return -EINVAL;
    }

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

466 467
    if (pid > 0) {
        /* Send the signal to the specify process */
468
    ret = OsDispatch(pid, &info, permission);//发送信号
469 470 471 472 473 474 475 476 477
    } 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);
    }
478 479
    return ret;
}
480
//给发送信号过程加锁
481 482 483 484 485 486
int OsKillLock(pid_t pid, int sig)
{
    int ret;
    unsigned int intSave;

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

500 501 502 503 504 505 506 507 508 509 510 511
    /* 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)
{
512 513 514 515 516 517 518 519 520 521 522
    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);
523
    ret = OsTaskKillUnsafe(tid, signo);
524 525 526
    SCHEDULER_UNLOCK(intSave);
    return ret;
}
527
//向信号集中加入signo信号
528 529 530 531 532 533 534
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 */
535
        signo -= 1;// 信号范围是 [1 ~ 64 ],而保存变量位的范围是[0 ~ 63]
536
        /* Add the signal to the set */
537
        *set |= SIGNO2SET((unsigned int)signo);//填充信号集
538 539 540
        return LOS_OK;
    }
}
541
//获取阻塞当前任务的信号集
542 543 544 545 546 547 548 549 550 551 552
int OsSigPending(sigset_t *set)
{
    LosTaskCB *tcb = NULL;
    unsigned int intSave;

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

    SCHEDULER_LOCK(intSave);
    tcb = OsCurrTaskGet();
553
    *set = tcb->sig.sigPendFlag;//被阻塞的信号集
554 555 556 557 558 559 560 561 562 563 564 565 566 567
    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);
}
568
//等待信号时间
569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585
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;
586
        OsMoveTmpInfoToUnbInfo(sigcb, ret);
587 588 589 590 591
    } else {
        OsSigAddSet(set, SIGKILL);//kill 9 14 必须要处理
        OsSigAddSet(set, SIGSTOP);//终止进程的信号也必须处理

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

    SCHEDULER_LOCK(intSave);

612
    ret = OsSigTimedWaitNoLock(set, info, timeout);//以不加锁的方式等待
613 614 615 616

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

    spcb = OsCurrTaskGet();
    oldSigprocmask = spcb->sig.sigprocmask;
    return OsSigSuspend(&oldSigprocmask);
}
627
//用参数set代替进程的原有掩码,并暂停进程执行,直到收到信号再恢复原有掩码并继续执行进程。
628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645
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);
646 647 648 649 650 651 652 653 654 655 656 657 658 659 660

    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);
        }
661 662 663 664 665 666
    }

    SCHEDULER_UNLOCK(intSave);
    return -EINTR;
}
/**************************************************
667
信号安装,函数用于改变进程接收到特定信号后的行为。
668
sig:信号的值,可以为除SIGKILL及SIGSTOP外的任何一个特定有效的信号(为这两个信号定义自己的处理函数,将导致信号安装错误)。
669 670
act:设置对signal信号的新处理方式。
oldact:原来对信号的处理方式。
671
如果把第二、第三个参数都设为NULL,那么该函数可用于检查信号的有效性。
672
返回值:0 表示成功,-1 表示有错误发生。
673 674 675 676 677 678 679 680 681
**************************************************/
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;
    }
682 683 684 685 686
	//将数据从用户空间拷贝到内核空间
	if (LOS_ArchCopyFromUser(&action, act, sizeof(sigaction_t)) != LOS_OK) {
		return -EFAULT;
	}
	
687 688
	if (sig == SIGSYS) {//鸿蒙此处通过错误的系统调用 来安装信号处理函数,有点巧妙. 
		addr = OsGetSigHandler();//是否已存在信号处理函数
689 690 691 692
		if (addr == 0) {//进程没有设置信号处理函数时
			OsSetSigHandler((unsigned long)(UINTPTR)action.sa_handler);//设置进程信号处理函数
			//void (*sa_handler)(int); //信号处理函数——普通版
			//void (*sa_sigaction)(int, siginfo_t *, void *);//信号处理函数——高级版
693 694 695 696 697 698 699
            return LOS_OK;
        }
        return -EINVAL;
    }

    return LOS_OK;
}
700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715

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);
}
716 717
/**********************************************
产生系统调用时,也就是软中断时,保存用户栈寄存器现场信息
718
改写PC寄存器的值
719
**********************************************/
720
VOID *OsSaveSignalContext(VOID *sp, VOID *newSp)
721 722 723
{
    UINTPTR sigHandler;
    UINT32 intSave;
724 725 726
    LosTaskCB *task = OsCurrTaskGet();
    LosProcessCB *process = OsCurrProcessGet();
    sig_cb *sigcb = &task->sig;
727

728 729 730 731 732 733 734 735 736 737
    /* 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;
    }

738 739 740 741
    SCHEDULER_LOCK(intSave);
    if ((sigcb->count == 0) && ((sigcb->sigFlag != 0) || (process->sigShare != 0))) {
        sigHandler = OsGetSigHandler();
        if (sigHandler == 0) {
742 743 744 745
            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);
746
            return sp;
747
        }
748 749 750 751
        /* 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);
752
        OsMoveTmpInfoToUnbInfo(sigcb, signo);
753 754 755 756 757
        OsProcessExitCodeSignalSet(process, signo);
        sigcb->sigContext = sp;

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

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

    SCHEDULER_UNLOCK(intSave);
766
    return sp;
767 768
}

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

780 781
    LosTaskCB *task = OsCurrTaskGet();
    sig_cb *sigcb = &task->sig;
782

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

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

800
#endif