237 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			237 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | /*
 | ||
|  |  * Copyright (c) 2006-2023, RT-Thread Development Team | ||
|  |  * | ||
|  |  * SPDX-License-Identifier: Apache-2.0 | ||
|  |  * | ||
|  |  * Change Logs: | ||
|  |  * Date           Author       Notes | ||
|  |  * 2020-02-23     Jesven       first version. | ||
|  |  * 2023-07-06     Shell        update the generation, pending and delivery API | ||
|  |  * 2023-11-22     Shell        support for job control signal | ||
|  |  */ | ||
|  | 
 | ||
|  | #ifndef __LWP_SIGNAL_H__
 | ||
|  | #define __LWP_SIGNAL_H__
 | ||
|  | 
 | ||
|  | #include "syscall_generic.h"
 | ||
|  | 
 | ||
|  | #include <rtthread.h>
 | ||
|  | #include <sys/signal.h>
 | ||
|  | 
 | ||
|  | #ifdef __cplusplus
 | ||
|  | extern "C" { | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #define _USIGNAL_SIGMASK(signo) (1u << ((signo)-1))
 | ||
|  | #define LWP_SIG_NO_IGN_SET                                   \
 | ||
|  |     (_USIGNAL_SIGMASK(SIGCONT) | _USIGNAL_SIGMASK(SIGSTOP) | \ | ||
|  |      _USIGNAL_SIGMASK(SIGKILL)) | ||
|  | #define LWP_SIG_IGNORE_SET                                  \
 | ||
|  |     (_USIGNAL_SIGMASK(SIGCHLD) | _USIGNAL_SIGMASK(SIGURG) | \ | ||
|  |      _USIGNAL_SIGMASK(SIGWINCH) /* from 4.3 BSD, not POSIX.1 */) | ||
|  | #define LWP_SIG_JOBCTL_SET                                   \
 | ||
|  |     (_USIGNAL_SIGMASK(SIGCONT) | _USIGNAL_SIGMASK(SIGSTOP) | \ | ||
|  |      _USIGNAL_SIGMASK(SIGTSTP) | _USIGNAL_SIGMASK(SIGTTIN) | \ | ||
|  |      _USIGNAL_SIGMASK(SIGTTOU)) | ||
|  | #define LWP_SIG_STOP_SET                                     \
 | ||
|  |     (_USIGNAL_SIGMASK(SIGSTOP) | _USIGNAL_SIGMASK(SIGTSTP) | \ | ||
|  |      _USIGNAL_SIGMASK(SIGTTIN) | _USIGNAL_SIGMASK(SIGTTOU)) | ||
|  | #define LWP_SIG_ACT_DFL ((lwp_sighandler_t)0)
 | ||
|  | #define LWP_SIG_ACT_IGN ((lwp_sighandler_t)1)
 | ||
|  | #define LWP_SIG_USER_SA_FLAGS                                             \
 | ||
|  |     (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART | \ | ||
|  |      SA_NODEFER | SA_RESETHAND | SA_EXPOSE_TAGBITS) | ||
|  | #define LWP_SIG_INVALID_TIMER ((timer_t)-1)
 | ||
|  | 
 | ||
|  | typedef enum | ||
|  | { | ||
|  |     LWP_SIG_MASK_CMD_BLOCK, | ||
|  |     LWP_SIG_MASK_CMD_UNBLOCK, | ||
|  |     LWP_SIG_MASK_CMD_SET_MASK, | ||
|  |     __LWP_SIG_MASK_CMD_WATERMARK | ||
|  | } lwp_sig_mask_cmd_t; | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * LwP implementation of POSIX signal | ||
|  |  */ | ||
|  | struct lwp_signal | ||
|  | { | ||
|  |     timer_t real_timer; | ||
|  |     struct lwp_sigqueue sig_queue; | ||
|  |     rt_thread_t sig_dispatch_thr[_LWP_NSIG]; | ||
|  | 
 | ||
|  |     lwp_sighandler_t sig_action[_LWP_NSIG]; | ||
|  |     lwp_sigset_t sig_action_mask[_LWP_NSIG]; | ||
|  | 
 | ||
|  |     lwp_sigset_t sig_action_nodefer; | ||
|  |     lwp_sigset_t sig_action_onstack; | ||
|  |     lwp_sigset_t sig_action_restart; | ||
|  |     lwp_sigset_t sig_action_siginfo; | ||
|  |     lwp_sigset_t sig_action_nocldstop; | ||
|  |     lwp_sigset_t sig_action_nocldwait; | ||
|  | }; | ||
|  | 
 | ||
|  | struct rt_lwp; | ||
|  | struct rt_processgroup; | ||
|  | 
 | ||
|  | #ifndef ARCH_MM_MMU
 | ||
|  | void lwp_sighandler_set(int sig, lwp_sighandler_t func); | ||
|  | void lwp_thread_sighandler_set(int sig, lwp_sighandler_t func); | ||
|  | #endif
 | ||
|  | 
 | ||
|  | rt_inline void lwp_sigqueue_init(lwp_sigqueue_t sigq) | ||
|  | { | ||
|  |     rt_memset(&sigq->sigset_pending, 0, sizeof(lwp_sigset_t)); | ||
|  |     rt_list_init(&sigq->siginfo_list); | ||
|  | } | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @brief release the signal queue | ||
|  |  * | ||
|  |  * @param sigq target signal queue | ||
|  |  */ | ||
|  | void lwp_sigqueue_clear(lwp_sigqueue_t sigq); | ||
|  | 
 | ||
|  | rt_err_t lwp_signal_init(struct lwp_signal *sig); | ||
|  | 
 | ||
|  | rt_err_t lwp_signal_detach(struct lwp_signal *signal); | ||
|  | 
 | ||
|  | rt_inline void lwp_thread_signal_detach(struct lwp_thread_signal *tsig) | ||
|  | { | ||
|  |     lwp_sigqueue_clear(&tsig->sig_queue); | ||
|  | } | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @brief send a signal to the process | ||
|  |  * | ||
|  |  * @param lwp the process to be killed | ||
|  |  * @param signo the signal number | ||
|  |  * @param code as in siginfo | ||
|  |  * @param value as in siginfo | ||
|  |  * @return rt_err_t RT_EINVAL if the parameter is invalid, RT_EOK as | ||
|  |  * successful | ||
|  |  * | ||
|  |  * @note the *signal_kill have the same definition of a successful return as | ||
|  |  *       kill() in IEEE Std 1003.1-2017 | ||
|  |  */ | ||
|  | rt_err_t lwp_signal_kill(struct rt_lwp *lwp, long signo, long code, | ||
|  |                          lwp_siginfo_ext_t value); | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @brief set or examine the signal action of signo | ||
|  |  * | ||
|  |  * @param signo signal number | ||
|  |  * @param act the signal action | ||
|  |  * @param oact the old signal action | ||
|  |  * @return rt_err_t | ||
|  |  */ | ||
|  | rt_err_t lwp_signal_action(struct rt_lwp *lwp, int signo, | ||
|  |                            const struct lwp_sigaction *restrict act, | ||
|  |                            struct lwp_sigaction *restrict oact); | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @brief send a signal to the thread | ||
|  |  * | ||
|  |  * @param thread target thread | ||
|  |  * @param signo the signal number | ||
|  |  * @param code as in siginfo | ||
|  |  * @param value as in siginfo | ||
|  |  * @return rt_err_t RT_EINVAL if the parameter is invalid, RT_EOK as | ||
|  |  * successful | ||
|  |  */ | ||
|  | rt_err_t lwp_thread_signal_kill(rt_thread_t thread, long signo, long code, | ||
|  |                                 lwp_siginfo_ext_t value); | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @brief set signal mask of target thread | ||
|  |  * | ||
|  |  * @param thread the target thread | ||
|  |  * @param how command | ||
|  |  * @param sigset operand | ||
|  |  * @param oset the address to old set | ||
|  |  * @return rt_err_t | ||
|  |  */ | ||
|  | rt_err_t lwp_thread_signal_mask(rt_thread_t thread, lwp_sig_mask_cmd_t how, | ||
|  |                                 const lwp_sigset_t *sigset, lwp_sigset_t *oset); | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @brief Catch signal if exists and no return, otherwise return with no | ||
|  |  * side effect | ||
|  |  * | ||
|  |  * @param exp_frame the exception frame on kernel stack | ||
|  |  */ | ||
|  | void lwp_thread_signal_catch(void *exp_frame); | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @brief Check if it's okay to suspend for current lwp thread | ||
|  |  * | ||
|  |  * @param thread target thread | ||
|  |  * @param suspend_flag suspend flag of target thread | ||
|  |  * @return int 1 if can be suspended, otherwise not | ||
|  |  */ | ||
|  | int lwp_thread_signal_suspend_check(rt_thread_t thread, int suspend_flag); | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @brief Asynchronously wait for signal | ||
|  |  * | ||
|  |  * @param thread target thread | ||
|  |  * @param sigset the signals to be waited | ||
|  |  * @param info address of user siginfo | ||
|  |  * @param timeout timeout of waiting | ||
|  |  * @return rt_err_t | ||
|  |  */ | ||
|  | rt_err_t lwp_thread_signal_timedwait(rt_thread_t thread, lwp_sigset_t *sigset, | ||
|  |                                      siginfo_t *usi, struct timespec *timeout); | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @brief Examine the set of signals that are blocked from delivery to the | ||
|  |  * calling thread and that are pending on the process or the calling thread | ||
|  |  * | ||
|  |  * @param thread target thread | ||
|  |  * @param sigset where mask of pending signals is returned | ||
|  |  */ | ||
|  | void lwp_thread_signal_pending(rt_thread_t thread, lwp_sigset_t *sigset); | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @brief send a signal to the process group | ||
|  |  * | ||
|  |  * @param pgrp target process group | ||
|  |  * @param signo the signal number | ||
|  |  * @param code as in siginfo | ||
|  |  * @param value as in siginfo | ||
|  |  * @return rt_err_t RT_EINVAL if the parameter is invalid, RT_EOK as | ||
|  |  * successful | ||
|  |  */ | ||
|  | rt_err_t lwp_pgrp_signal_kill(struct rt_processgroup *pgrp, long signo, | ||
|  |                               long code, lwp_siginfo_ext_t value); | ||
|  | 
 | ||
|  | rt_inline int lwp_sigismember(lwp_sigset_t *set, int _sig) | ||
|  | { | ||
|  |     unsigned long sig = _sig - 1; | ||
|  | 
 | ||
|  |     if (_LWP_NSIG_WORDS == 1) | ||
|  |     { | ||
|  |         return 1 & (set->sig[0] >> sig); | ||
|  |     } | ||
|  |     else | ||
|  |     { | ||
|  |         return 1 & (set->sig[sig / _LWP_NSIG_BPW] >> (sig % _LWP_NSIG_BPW)); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | struct itimerspec; | ||
|  | 
 | ||
|  | rt_bool_t lwp_sigisign(struct rt_lwp *lwp, int _sig); | ||
|  | 
 | ||
|  | rt_err_t lwp_signal_setitimer(struct rt_lwp *lwp, int which, | ||
|  |                               const struct itimerspec *restrict new, | ||
|  |                               struct itimerspec *restrict old); | ||
|  | 
 | ||
|  | rt_bool_t lwp_signal_restart_syscall(struct rt_lwp *lwp, int error_code); | ||
|  | 
 | ||
|  | #ifdef __cplusplus
 | ||
|  | } | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #endif /* __LWP_SIGNAL_H__ */
 |