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