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