• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2023 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "los_signal.h"
33 #include "pthread.h"
34 #include "los_process_pri.h"
35 #include "los_sched_pri.h"
36 #include "los_hw_pri.h"
37 #include "user_copy.h"
38 #ifdef LOSCFG_SECURITY_CAPABILITY
39 #include "capability_api.h"
40 #endif
41 #include "los_atomic.h"
42 
43 #ifdef LOSCFG_KERNEL_VM
44 
raise(int sig)45 int raise(int sig)
46 {
47     (VOID)sig;
48     PRINT_ERR("%s NOT SUPPORT\n", __FUNCTION__);
49     errno = ENOSYS;
50     return -1;
51 }
52 
53 #define GETUNMASKSET(procmask, pendFlag) ((~(procmask)) & (sigset_t)(pendFlag))
54 #define UINT64_BIT_SIZE 64
55 
OsSigIsMember(const sigset_t * set,int signo)56 int OsSigIsMember(const sigset_t *set, int signo)
57 {
58     int ret = LOS_NOK;
59     /* In musl, sig No bits 00000100 present sig No 3, but  1<< 3 = 00001000, so signo needs minus 1 */
60     signo -= 1;
61     /* Verify the signal */
62     if (GOOD_SIGNO(signo)) {
63         /* Check if the signal is in the set */
64         ret = ((*set & SIGNO2SET((unsigned int)signo)) != 0);
65     }
66 
67     return ret;
68 }
69 
OsMoveTmpInfoToUnbInfo(sig_cb * sigcb,INT32 signo)70 STATIC VOID OsMoveTmpInfoToUnbInfo(sig_cb *sigcb, INT32 signo)
71 {
72     SigInfoListNode *tmpInfoNode = sigcb->tmpInfoListHead;
73     SigInfoListNode **prevHook = &sigcb->tmpInfoListHead;
74     while (tmpInfoNode != NULL) {
75         if (tmpInfoNode->info.si_signo == signo) {
76             /* copy tmpinfo to unbinfo. */
77             (VOID)memcpy_s(&sigcb->sigunbinfo, sizeof(siginfo_t), &tmpInfoNode->info, sizeof(siginfo_t));
78             /* delete tmpinfo from tmpList. */
79             *prevHook = tmpInfoNode->next;
80             (VOID)LOS_MemFree(m_aucSysMem0, tmpInfoNode);
81             break;
82         }
83         prevHook = &tmpInfoNode->next;
84         tmpInfoNode = tmpInfoNode->next;
85     }
86 }
87 
OsAddSigInfoToTmpList(sig_cb * sigcb,siginfo_t * info)88 STATIC INT32 OsAddSigInfoToTmpList(sig_cb *sigcb, siginfo_t *info)
89 {
90     /* try to find the old siginfo */
91     SigInfoListNode *tmp = sigcb->tmpInfoListHead;
92     while (tmp != NULL) {
93         if (tmp->info.si_signo == info->si_signo) {
94             /* found it, break. */
95             break;
96         }
97         tmp = tmp->next;
98     }
99 
100     if (tmp == NULL) {
101         /* none, alloc new one */
102         tmp = (SigInfoListNode *)LOS_MemAlloc(m_aucSysMem0, sizeof(SigInfoListNode));
103         if (tmp == NULL) {
104             return LOS_NOK;
105         }
106         tmp->next = sigcb->tmpInfoListHead;
107         sigcb->tmpInfoListHead = tmp;
108     }
109 
110     (VOID)memcpy_s(&tmp->info, sizeof(siginfo_t), info, sizeof(siginfo_t));
111 
112     return LOS_OK;
113 }
114 
OsClearSigInfoTmpList(sig_cb * sigcb)115 VOID OsClearSigInfoTmpList(sig_cb *sigcb)
116 {
117     while (sigcb->tmpInfoListHead != NULL) {
118         SigInfoListNode *tmpInfoNode = sigcb->tmpInfoListHead;
119         sigcb->tmpInfoListHead = sigcb->tmpInfoListHead->next;
120         (VOID)LOS_MemFree(m_aucSysMem0, tmpInfoNode);
121     }
122 }
123 
OsSigWaitTaskWake(LosTaskCB * taskCB,INT32 signo)124 STATIC INLINE VOID OsSigWaitTaskWake(LosTaskCB *taskCB, INT32 signo)
125 {
126     sig_cb *sigcb = &taskCB->sig;
127 
128     if (!LOS_ListEmpty(&sigcb->waitList) && OsSigIsMember(&sigcb->sigwaitmask, signo)) {
129         OsMoveTmpInfoToUnbInfo(sigcb, signo);
130         OsTaskWakeClearPendMask(taskCB);
131         taskCB->ops->wake(taskCB);
132         OsSigEmptySet(&sigcb->sigwaitmask);
133     }
134 }
135 
OsPendingTaskWake(LosTaskCB * taskCB,INT32 signo)136 STATIC UINT32 OsPendingTaskWake(LosTaskCB *taskCB, INT32 signo)
137 {
138     if (!OsTaskIsPending(taskCB) || !OsProcessIsUserMode(OS_PCB_FROM_TCB(taskCB))) {
139         return 0;
140     }
141 
142     if ((signo != SIGKILL) && (taskCB->waitFlag != OS_TASK_WAIT_SIGNAL)) {
143         return 0;
144     }
145 
146     switch (taskCB->waitFlag) {
147         case OS_TASK_WAIT_PROCESS:
148         case OS_TASK_WAIT_GID:
149         case OS_TASK_WAIT_ANYPROCESS:
150             OsWaitWakeTask(taskCB, OS_INVALID_VALUE);
151             break;
152         case OS_TASK_WAIT_JOIN:
153             OsTaskWakeClearPendMask(taskCB);
154             taskCB->ops->wake(taskCB);
155             break;
156         case OS_TASK_WAIT_SIGNAL:
157             OsSigWaitTaskWake(taskCB, signo);
158             break;
159         case OS_TASK_WAIT_LITEIPC:
160             OsTaskWakeClearPendMask(taskCB);
161             taskCB->ops->wake(taskCB);
162             break;
163         case OS_TASK_WAIT_FUTEX:
164             OsFutexNodeDeleteFromFutexHash(&taskCB->futex, TRUE, NULL, NULL);
165             OsTaskWakeClearPendMask(taskCB);
166             taskCB->ops->wake(taskCB);
167             break;
168         default:
169             break;
170     }
171 
172     return 0;
173 }
174 
OsTcbDispatch(LosTaskCB * stcb,siginfo_t * info)175 int OsTcbDispatch(LosTaskCB *stcb, siginfo_t *info)
176 {
177     bool masked = FALSE;
178     sig_cb *sigcb = &stcb->sig;
179 
180     OS_RETURN_IF_NULL(sigcb);
181     /* If signo is 0, not send signal, just check process or pthread exist */
182     if (info->si_signo == 0) {
183         return 0;
184     }
185     masked = (bool)OsSigIsMember(&sigcb->sigprocmask, info->si_signo);
186     if (masked) {
187         /* If signal is in wait list and mask list, need unblock it */
188         if (LOS_ListEmpty(&sigcb->waitList)  ||
189             (!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     if (OsAddSigInfoToTmpList(sigcb, info) == LOS_NOK) {
198         return -ENOMEM;
199     }
200 
201     return OsPendingTaskWake(stcb, info->si_signo);
202 }
203 
OsSigMaskSwitch(LosTaskCB * const rtcb,sigset_t set)204 void OsSigMaskSwitch(LosTaskCB * const rtcb, sigset_t set)
205 {
206     sigset_t unmaskset;
207 
208     rtcb->sig.sigprocmask = set;
209     unmaskset = GETUNMASKSET(rtcb->sig.sigprocmask, rtcb->sig.sigPendFlag);
210     if (unmaskset != NULL_SIGNAL_SET) {
211         /* pendlist do */
212         rtcb->sig.sigFlag |= unmaskset;
213         rtcb->sig.sigPendFlag ^= unmaskset;
214     }
215 }
216 
OsSigprocMask(int how,const sigset_t_l * setl,sigset_t_l * oldsetl)217 int OsSigprocMask(int how, const sigset_t_l *setl, sigset_t_l *oldsetl)
218 {
219     LosTaskCB *spcb = NULL;
220     int ret = LOS_OK;
221     unsigned int intSave;
222     sigset_t set;
223 
224     SCHEDULER_LOCK(intSave);
225     spcb = OsCurrTaskGet();
226     /* If requested, copy the old mask to user. */
227     if (oldsetl != NULL) {
228         *(sigset_t *)oldsetl = spcb->sig.sigprocmask;
229     }
230     /* If requested, modify the current signal mask. */
231     if (setl != NULL) {
232         set = *(sigset_t *)setl;
233         /* Okay, determine what we are supposed to do */
234         switch (how) {
235             /* Set the union of the current set and the signal
236              * set pointed to by set as the new sigprocmask.
237              */
238             case SIG_BLOCK:
239                 spcb->sig.sigprocmask |= set;
240                 break;
241             /* Set the intersection of the current set and the
242              * signal set pointed to by set as the new sigprocmask.
243              */
244             case SIG_UNBLOCK:
245                 spcb->sig.sigprocmask &= ~(set);
246                 break;
247             /* Set the signal set pointed to by set as the new sigprocmask. */
248             case SIG_SETMASK:
249                 spcb->sig.sigprocmask = set;
250                 break;
251             default:
252                 ret = -EINVAL;
253                 break;
254         }
255         /* If pending mask not in sigmask, need set sigflag. */
256         OsSigMaskSwitch(spcb, spcb->sig.sigprocmask);
257     }
258     SCHEDULER_UNLOCK(intSave);
259 
260     return ret;
261 }
262 
OsSigProcessForeachChild(LosProcessCB * spcb,ForEachTaskCB handler,void * arg)263 int OsSigProcessForeachChild(LosProcessCB *spcb, ForEachTaskCB handler, void *arg)
264 {
265     int ret;
266 
267     /* Visit the main thread last (if present) */
268     LosTaskCB *taskCB = NULL;
269     LOS_DL_LIST_FOR_EACH_ENTRY(taskCB, &(spcb->threadSiblingList), LosTaskCB, threadList) {
270         ret = handler(taskCB, arg);
271         OS_RETURN_IF(ret != 0, ret);
272     }
273     return LOS_OK;
274 }
275 
SigProcessSignalHandler(LosTaskCB * tcb,void * arg)276 static int SigProcessSignalHandler(LosTaskCB *tcb, void *arg)
277 {
278     struct ProcessSignalInfo *info = (struct ProcessSignalInfo *)arg;
279     int ret;
280     int isMember;
281 
282     if (tcb == NULL) {
283         return 0;
284     }
285 
286     /* If the default tcb is not set, then set this one as default. */
287     if (!info->defaultTcb) {
288         info->defaultTcb = tcb;
289     }
290 
291     isMember = OsSigIsMember(&tcb->sig.sigwaitmask, info->sigInfo->si_signo);
292     if (isMember && (!info->awakenedTcb)) {
293         /* This means the task is waiting for this signal. Stop looking for it and use this tcb.
294          * The requirement is: if more than one task in this task group is waiting for the signal,
295          * then only one indeterminate task in the group will receive the signal.
296          */
297         ret = OsTcbDispatch(tcb, info->sigInfo);
298         OS_RETURN_IF(ret < 0, ret);
299 
300         /* set this tcb as awakenedTcb */
301         info->awakenedTcb = tcb;
302         OS_RETURN_IF(info->receivedTcb != NULL, SIG_STOP_VISIT); /* Stop search */
303     }
304     /* Is this signal unblocked on this thread? */
305     isMember = OsSigIsMember(&tcb->sig.sigprocmask, info->sigInfo->si_signo);
306     if ((!isMember) && (!info->receivedTcb) && (tcb != info->awakenedTcb)) {
307         /* if unblockedTcb of this signal is not set, then set it. */
308         if (!info->unblockedTcb) {
309             info->unblockedTcb = tcb;
310         }
311 
312         ret = OsTcbDispatch(tcb, info->sigInfo);
313         OS_RETURN_IF(ret < 0, ret);
314         /* set this tcb as receivedTcb */
315         info->receivedTcb = tcb;
316         OS_RETURN_IF(info->awakenedTcb != NULL, SIG_STOP_VISIT); /* Stop search */
317     }
318     return 0; /* Keep searching */
319 }
320 
SigProcessKillSigHandler(LosTaskCB * tcb,void * arg)321 static int SigProcessKillSigHandler(LosTaskCB *tcb, void *arg)
322 {
323     struct ProcessSignalInfo *info = (struct ProcessSignalInfo *)arg;
324 
325     return OsPendingTaskWake(tcb, info->sigInfo->si_signo);
326 }
327 
SigProcessLoadTcb(struct ProcessSignalInfo * info,siginfo_t * sigInfo)328 static void SigProcessLoadTcb(struct ProcessSignalInfo *info, siginfo_t *sigInfo)
329 {
330     LosTaskCB *tcb = NULL;
331 
332     if (info->awakenedTcb == NULL && info->receivedTcb == NULL) {
333         if (info->unblockedTcb) {
334             tcb = info->unblockedTcb;
335         } else if (info->defaultTcb) {
336             tcb = info->defaultTcb;
337         } else {
338             return;
339         }
340         /* Deliver the signal to the selected task */
341         (void)OsTcbDispatch(tcb, sigInfo);
342     }
343 }
344 
OsSigProcessSend(LosProcessCB * spcb,siginfo_t * sigInfo)345 int OsSigProcessSend(LosProcessCB *spcb, siginfo_t *sigInfo)
346 {
347     int ret;
348     struct ProcessSignalInfo info = {
349         .sigInfo = sigInfo,
350         .defaultTcb = NULL,
351         .unblockedTcb = NULL,
352         .awakenedTcb = NULL,
353         .receivedTcb = NULL
354     };
355 
356     if (info.sigInfo == NULL) {
357         return -EFAULT;
358     }
359 
360     /* visit all taskcb and dispatch signal */
361     if (info.sigInfo->si_signo == SIGKILL) {
362         OsSigAddSet(&spcb->sigShare, info.sigInfo->si_signo);
363         (void)OsSigProcessForeachChild(spcb, SigProcessKillSigHandler, &info);
364         return 0;
365     } else {
366         ret = OsSigProcessForeachChild(spcb, SigProcessSignalHandler, &info);
367     }
368     if (ret < 0) {
369         return ret;
370     }
371     SigProcessLoadTcb(&info, sigInfo);
372     return 0;
373 }
374 
OsSigEmptySet(sigset_t * set)375 int OsSigEmptySet(sigset_t *set)
376 {
377     *set = NULL_SIGNAL_SET;
378     return 0;
379 }
380 
381 /* Privilege process can't send to kernel and privilege process */
OsSignalPermissionToCheck(const LosProcessCB * spcb)382 static int OsSignalPermissionToCheck(const LosProcessCB *spcb)
383 {
384     UINTPTR gid = (UINTPTR)OS_GET_PGROUP_LEADER(spcb->pgroup);
385     if (gid == OS_KERNEL_PROCESS_GROUP) {
386         return -EPERM;
387     } else if (gid == OS_USER_PRIVILEGE_PROCESS_GROUP) {
388         return -EPERM;
389     }
390 
391     return 0;
392 }
393 
SendSigPermissionCheck(LosProcessCB * spcb,int permission)394 STATIC int SendSigPermissionCheck(LosProcessCB *spcb, int permission)
395 {
396     if (spcb == NULL) {
397         return -ESRCH;
398     }
399 
400     if (OsProcessIsUnused(spcb)) {
401         return -ESRCH;
402     }
403 
404 #ifdef LOSCFG_SECURITY_CAPABILITY
405     LosProcessCB *current = OsCurrProcessGet();
406     /* Kernel process always has kill permission and user process should check permission */
407     if (OsProcessIsUserMode(current) && !(current->processStatus & OS_PROCESS_FLAG_EXIT)) {
408         if ((current != spcb) && (!IsCapPermit(CAP_KILL)) && (current->user->userID != spcb->user->userID)) {
409             return -EPERM;
410         }
411     }
412 #endif
413     if ((permission == OS_USER_KILL_PERMISSION) && (OsSignalPermissionToCheck(spcb) < 0)) {
414         return -EPERM;
415     }
416     return LOS_OK;
417 }
418 
OsSendSigToProcess(LosProcessCB * spcb,int sig,int permission)419 int OsSendSigToProcess(LosProcessCB *spcb, int sig, int permission)
420 {
421     siginfo_t info;
422     int ret = SendSigPermissionCheck(spcb, permission);
423     if (ret != LOS_OK) {
424         return ret;
425     }
426 
427     /* If the process you want to kill had been inactive, but still exist. should return LOS_OK */
428     if (OsProcessIsInactive(spcb)) {
429         return LOS_OK;
430     }
431 
432     if (!GOOD_SIGNO(sig)) {
433         return -EINVAL;
434     }
435 
436     info.si_signo = sig;
437     info.si_code = SI_USER;
438     info.si_value.sival_ptr = NULL;
439 
440     return OsSigProcessSend(spcb, &info);
441 }
442 
OsDispatch(pid_t pid,siginfo_t * info,int permission)443 int OsDispatch(pid_t pid, siginfo_t *info, int permission)
444 {
445     if (OsProcessIDUserCheckInvalid(pid) || pid < 0) {
446         return -ESRCH;
447     }
448 
449     LosProcessCB *spcb = OS_PCB_FROM_PID(pid);
450     int ret = SendSigPermissionCheck(spcb, permission);
451     if (ret != LOS_OK) {
452         return ret;
453     }
454 
455     /* If the process you want to kill had been inactive, but still exist. should return LOS_OK */
456     if (OsProcessIsInactive(spcb)) {
457         return LOS_OK;
458     }
459 
460     return OsSigProcessSend(spcb, info);
461 }
462 
OsKill(pid_t pid,int sig,int permission)463 int OsKill(pid_t pid, int sig, int permission)
464 {
465     siginfo_t info;
466     int ret;
467 
468     /* Make sure that the para is valid */
469     if (!GOOD_SIGNO(sig)) {
470         return -EINVAL;
471     }
472 
473     /* Create the siginfo structure */
474     info.si_signo = sig;
475     info.si_code = SI_USER;
476     info.si_value.sival_ptr = NULL;
477 
478     if (pid > 0) {
479         /* Send the signal to the specify process */
480         ret = OsDispatch(pid, &info, permission);
481     } else if (pid == -1) {
482         /* Send SIG to all processes */
483         ret = OsSendSignalToAllProcess(&info, permission);
484     } else {
485         /* Send SIG to all processes in process group PGRP.
486            If PGRP is zero, send SIG to all processes in
487            the current process's process group. */
488         ret = OsSendSignalToProcessGroup(pid, &info, permission);
489     }
490     return ret;
491 }
492 
OsKillLock(pid_t pid,int sig)493 int OsKillLock(pid_t pid, int sig)
494 {
495     int ret;
496     unsigned int intSave;
497 
498     SCHEDULER_LOCK(intSave);
499     ret = OsKill(pid, sig, OS_USER_KILL_PERMISSION);
500     SCHEDULER_UNLOCK(intSave);
501     return ret;
502 }
503 
OsTaskKillUnsafe(UINT32 taskID,INT32 signo)504 INT32 OsTaskKillUnsafe(UINT32 taskID, INT32 signo)
505 {
506     siginfo_t info;
507     LosTaskCB *taskCB = OsGetTaskCB(taskID);
508     INT32 ret = OsUserTaskOperatePermissionsCheck(taskCB);
509     if (ret != LOS_OK) {
510         return -ret;
511     }
512 
513     /* Create the siginfo structure */
514     info.si_signo = signo;
515     info.si_code = SI_USER;
516     info.si_value.sival_ptr = NULL;
517 
518     /* Dispatch the signal to thread, bypassing normal task group thread
519      * dispatch rules. */
520     return OsTcbDispatch(taskCB, &info);
521 }
522 
OsPthreadKill(UINT32 tid,int signo)523 int OsPthreadKill(UINT32 tid, int signo)
524 {
525     int ret;
526     UINT32 intSave;
527 
528     /* Make sure that the signal is valid */
529     OS_RETURN_IF(!GOOD_SIGNO(signo), -EINVAL);
530     if (OS_TID_CHECK_INVALID(tid)) {
531         return -ESRCH;
532     }
533 
534     /* Keep things stationary through the following */
535     SCHEDULER_LOCK(intSave);
536     ret = OsTaskKillUnsafe(tid, signo);
537     SCHEDULER_UNLOCK(intSave);
538     return ret;
539 }
540 
OsSigAddSet(sigset_t * set,int signo)541 int OsSigAddSet(sigset_t *set, int signo)
542 {
543     /* Verify the signal */
544     if (!GOOD_SIGNO(signo)) {
545         return -EINVAL;
546     } else {
547         /* In musl, sig No bits 00000100 present sig No 3, but  1<< 3 = 00001000, so signo needs minus 1 */
548         signo -= 1;
549         /* Add the signal to the set */
550         *set |= SIGNO2SET((unsigned int)signo);
551         return LOS_OK;
552     }
553 }
554 
OsSigPending(sigset_t * set)555 int OsSigPending(sigset_t *set)
556 {
557     LosTaskCB *tcb = NULL;
558     unsigned int intSave;
559 
560     if (set == NULL) {
561         return -EFAULT;
562     }
563 
564     SCHEDULER_LOCK(intSave);
565     tcb = OsCurrTaskGet();
566     *set = tcb->sig.sigPendFlag;
567     SCHEDULER_UNLOCK(intSave);
568     return LOS_OK;
569 }
570 
FindFirstSetedBit(UINT64 n)571 STATIC int FindFirstSetedBit(UINT64 n)
572 {
573     int count;
574 
575     if (n == 0) {
576         return -1;
577     }
578     for (count = 0; (count < UINT64_BIT_SIZE) && (n ^ 1ULL); n >>= 1, count++) {}
579     return (count < UINT64_BIT_SIZE) ? count : (-1);
580 }
581 
OsSigTimedWaitNoLock(sigset_t * set,siginfo_t * info,unsigned int timeout)582 int OsSigTimedWaitNoLock(sigset_t *set, siginfo_t *info, unsigned int timeout)
583 {
584     LosTaskCB *task = NULL;
585     sig_cb *sigcb = NULL;
586     int ret;
587 
588     task = OsCurrTaskGet();
589     sigcb = &task->sig;
590 
591     if (sigcb->waitList.pstNext == NULL) {
592         LOS_ListInit(&sigcb->waitList);
593     }
594     /* If pendingflag & set > 0, should clear pending flag */
595     sigset_t clear = sigcb->sigPendFlag & *set;
596     if (clear) {
597         sigcb->sigPendFlag ^= clear;
598         ret = FindFirstSetedBit((UINT64)clear) + 1;
599         OsMoveTmpInfoToUnbInfo(sigcb, ret);
600     } else {
601         OsSigAddSet(set, SIGKILL);
602         OsSigAddSet(set, SIGSTOP);
603 
604         sigcb->sigwaitmask |= *set;
605         OsTaskWaitSetPendMask(OS_TASK_WAIT_SIGNAL, sigcb->sigwaitmask, timeout);
606         ret = task->ops->wait(task, &sigcb->waitList, timeout);
607         if (ret == LOS_ERRNO_TSK_TIMEOUT) {
608             ret = -EAGAIN;
609         }
610         sigcb->sigwaitmask = NULL_SIGNAL_SET;
611     }
612     if (info != NULL) {
613         (VOID)memcpy_s(info, sizeof(siginfo_t), &sigcb->sigunbinfo, sizeof(siginfo_t));
614     }
615     return ret;
616 }
617 
OsSigTimedWait(sigset_t * set,siginfo_t * info,unsigned int timeout)618 int OsSigTimedWait(sigset_t *set, siginfo_t *info, unsigned int timeout)
619 {
620     int ret;
621     unsigned int intSave;
622 
623     SCHEDULER_LOCK(intSave);
624 
625     ret = OsSigTimedWaitNoLock(set, info, timeout);
626 
627     SCHEDULER_UNLOCK(intSave);
628     return ret;
629 }
630 
OsPause(void)631 int OsPause(void)
632 {
633     LosTaskCB *spcb = NULL;
634     sigset_t oldSigprocmask;
635 
636     spcb = OsCurrTaskGet();
637     oldSigprocmask = spcb->sig.sigprocmask;
638     return OsSigSuspend(&oldSigprocmask);
639 }
640 
OsSigSuspend(const sigset_t * set)641 int OsSigSuspend(const sigset_t *set)
642 {
643     unsigned int intSave;
644     LosTaskCB *rtcb = NULL;
645     sigset_t setSuspend;
646     int ret;
647 
648     if (set == NULL) {
649         return -EINVAL;
650     }
651     SCHEDULER_LOCK(intSave);
652     rtcb = OsCurrTaskGet();
653 
654     /* Wait signal calc */
655     setSuspend = FULL_SIGNAL_SET & (~(*set));
656 
657     /* If pending mask not in sigmask, need set sigflag */
658     OsSigMaskSwitch(rtcb, *set);
659 
660     if (rtcb->sig.sigFlag > 0) {
661         SCHEDULER_UNLOCK(intSave);
662 
663         /*
664          * If rtcb->sig.sigFlag > 0, it means that some signal have been
665          * received, and we need to do schedule to handle the signal directly.
666          */
667         LOS_Schedule();
668         return -EINTR;
669     } else {
670         ret = OsSigTimedWaitNoLock(&setSuspend, NULL, LOS_WAIT_FOREVER);
671         if (ret < 0) {
672             PRINT_ERR("FUNC %s LINE = %d, ret = %x\n", __FUNCTION__, __LINE__, ret);
673         }
674     }
675 
676     SCHEDULER_UNLOCK(intSave);
677     return -EINTR;
678 }
679 
OsSigAction(int sig,const sigaction_t * act,sigaction_t * oact)680 int OsSigAction(int sig, const sigaction_t *act, sigaction_t *oact)
681 {
682     UINTPTR addr;
683     sigaction_t action;
684 
685     if (!GOOD_SIGNO(sig) || sig < 1 || act == NULL) {
686         return -EINVAL;
687     }
688     if (LOS_ArchCopyFromUser(&action, act, sizeof(sigaction_t)) != LOS_OK) {
689         return -EFAULT;
690     }
691 
692     if (sig == SIGSYS) {
693         addr = OsGetSigHandler();
694         if (addr == 0) {
695             OsSetSigHandler((unsigned long)(UINTPTR)action.sa_handler);
696             return LOS_OK;
697         }
698         return -EINVAL;
699     }
700 
701     return LOS_OK;
702 }
703 
OsSigIntLock(VOID)704 VOID OsSigIntLock(VOID)
705 {
706     LosTaskCB *task = OsCurrTaskGet();
707     sig_cb *sigcb = &task->sig;
708 
709     (VOID)LOS_AtomicAdd((Atomic *)&sigcb->sigIntLock, 1);
710 }
711 
OsSigIntUnlock(VOID)712 VOID OsSigIntUnlock(VOID)
713 {
714     LosTaskCB *task = OsCurrTaskGet();
715     sig_cb *sigcb = &task->sig;
716 
717     (VOID)LOS_AtomicSub((Atomic *)&sigcb->sigIntLock, 1);
718 }
719 
OsSaveSignalContext(VOID * sp,VOID * newSp)720 VOID *OsSaveSignalContext(VOID *sp, VOID *newSp)
721 {
722     UINTPTR sigHandler;
723     UINT32 intSave;
724 
725     LosTaskCB *task = OsCurrTaskGet();
726     LosProcessCB *process = OsCurrProcessGet();
727     sig_cb *sigcb = &task->sig;
728 
729     /* A thread is not allowed to interrupt the processing of its signals during a system call */
730     if (sigcb->sigIntLock > 0) {
731         return sp;
732     }
733 
734     if (OsTaskIsKilled(task)) {
735         OsRunningTaskToExit(task, 0);
736         return sp;
737     }
738 
739     SCHEDULER_LOCK(intSave);
740     if ((sigcb->count == 0) && ((sigcb->sigFlag != 0) || (process->sigShare != 0))) {
741         sigHandler = OsGetSigHandler();
742         if (sigHandler == 0) {
743             sigcb->sigFlag = 0;
744             process->sigShare = 0;
745             SCHEDULER_UNLOCK(intSave);
746             PRINT_ERR("The signal processing function for the current process pid =%d is NULL!\n", process->processID);
747             return sp;
748         }
749         /* One pthread do the share signal */
750         sigcb->sigFlag |= process->sigShare;
751         UINT32 signo = (UINT32)FindFirstSetedBit(sigcb->sigFlag) + 1;
752         UINT32 sigVal = (UINT32)(UINTPTR)(sigcb->sigunbinfo.si_value.sival_ptr);
753         OsMoveTmpInfoToUnbInfo(sigcb, signo);
754         OsProcessExitCodeSignalSet(process, signo);
755         sigcb->sigContext = sp;
756 
757         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 */
760         sigcb->sigFlag ^= 1ULL << (signo - 1);
761         sigcb->count++;
762         SCHEDULER_UNLOCK(intSave);
763         return newSp;
764     }
765 
766     SCHEDULER_UNLOCK(intSave);
767     return sp;
768 }
769 
OsRestorSignalContext(VOID * sp)770 VOID *OsRestorSignalContext(VOID *sp)
771 {
772     UINT32 intSave;
773 
774     LosTaskCB *task = OsCurrTaskGet();
775     sig_cb *sigcb = &task->sig;
776 
777     SCHEDULER_LOCK(intSave);
778     if (sigcb->count != 1) {
779         SCHEDULER_UNLOCK(intSave);
780         PRINT_ERR("sig error count : %d\n", sigcb->count);
781         return sp;
782     }
783 
784     LosProcessCB *process = OsCurrProcessGet();
785     VOID *saveContext = sigcb->sigContext;
786     sigcb->sigContext = NULL;
787     sigcb->count--;
788     process->sigShare = 0;
789     OsProcessExitCodeSignalClear(process);
790     SCHEDULER_UNLOCK(intSave);
791     return saveContext;
792 }
793 
794 #endif
795