[component/lwp] support more feature of signal from IEEE Std 1003.1-2017 (#7828)
Signed-off-by: Shell <smokewood@qq.com>
This commit is contained in:
parent
c732cc0083
commit
58e0ddf287
|
@ -20,7 +20,67 @@
|
||||||
#endif /* RT_TTY_DEBUG */
|
#endif /* RT_TTY_DEBUG */
|
||||||
#include <rtdbg.h>
|
#include <rtdbg.h>
|
||||||
|
|
||||||
|
#include <ipc/waitqueue.h>
|
||||||
|
#include <ipc/ringbuffer.h>
|
||||||
|
|
||||||
static struct tty_struct console_dev;
|
static struct tty_struct console_dev;
|
||||||
|
static struct rt_ringbuffer console_rx_ringbuffer;
|
||||||
|
static struct rt_wqueue console_rx_wqueue;
|
||||||
|
static rt_thread_t console_rx_thread;
|
||||||
|
static const size_t rb_bufsz = 0x1000;
|
||||||
|
|
||||||
|
static void console_rx_work(void *parameter)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
char ch;
|
||||||
|
int lens;
|
||||||
|
static char buf[0x1000];
|
||||||
|
|
||||||
|
struct tty_struct *console;
|
||||||
|
console = &console_dev;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
rt_wqueue_wait(&console_rx_wqueue, 0, RT_WAITING_FOREVER);
|
||||||
|
lens = 0;
|
||||||
|
|
||||||
|
while (lens < sizeof(buf))
|
||||||
|
{
|
||||||
|
len = rt_ringbuffer_get(&console_rx_ringbuffer, (void *)&ch, sizeof(ch));
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lens += len;
|
||||||
|
buf[lens-1] = ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lens && console->ldisc->ops->receive_buf)
|
||||||
|
{
|
||||||
|
console->ldisc->ops->receive_buf((struct tty_struct *)console, buf, lens);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rx_thread_init(void)
|
||||||
|
{
|
||||||
|
void *rb_buffer;
|
||||||
|
rt_thread_t thread;
|
||||||
|
|
||||||
|
rb_buffer = rt_malloc(rb_bufsz);
|
||||||
|
rt_ringbuffer_init(&console_rx_ringbuffer, rb_buffer, rb_bufsz);
|
||||||
|
rt_wqueue_init(&console_rx_wqueue);
|
||||||
|
|
||||||
|
thread = rt_thread_create("console_rx", console_rx_work, &console_dev, rb_bufsz, 10, 10);
|
||||||
|
if (thread != RT_NULL)
|
||||||
|
{
|
||||||
|
rt_thread_startup(thread);
|
||||||
|
console_rx_thread = thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
INIT_COMPONENT_EXPORT(rx_thread_init);
|
||||||
|
|
||||||
static void console_rx_notify(struct rt_device *dev)
|
static void console_rx_notify(struct rt_device *dev)
|
||||||
{
|
{
|
||||||
|
@ -28,7 +88,6 @@ static void console_rx_notify(struct rt_device *dev)
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int lens = 0;
|
int lens = 0;
|
||||||
char ch = 0;
|
char ch = 0;
|
||||||
char buf[1024] = {0};
|
|
||||||
|
|
||||||
console = (struct tty_struct *)dev;
|
console = (struct tty_struct *)dev;
|
||||||
RT_ASSERT(console != RT_NULL);
|
RT_ASSERT(console != RT_NULL);
|
||||||
|
@ -41,17 +100,14 @@ static void console_rx_notify(struct rt_device *dev)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
lens += len;
|
lens += len;
|
||||||
buf[lens-1] = ch;
|
rt_ringbuffer_put(&console_rx_ringbuffer, (void *)&ch, sizeof(ch));
|
||||||
if (lens > 1024)
|
if (lens > rb_bufsz)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (console_rx_thread)
|
||||||
if (console->ldisc->ops->receive_buf)
|
rt_wqueue_wakeup(&console_rx_wqueue, 0);
|
||||||
{
|
|
||||||
console->ldisc->ops->receive_buf((struct tty_struct *)console, buf, lens);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tty_struct *console_tty_get(void)
|
struct tty_struct *console_tty_get(void)
|
||||||
|
|
|
@ -50,7 +50,6 @@
|
||||||
#define ECHO_BLOCK 256
|
#define ECHO_BLOCK 256
|
||||||
#define ECHO_DISCARD_WATERMARK RT_TTY_BUF - (ECHO_BLOCK + 32)
|
#define ECHO_DISCARD_WATERMARK RT_TTY_BUF - (ECHO_BLOCK + 32)
|
||||||
|
|
||||||
|
|
||||||
struct n_tty_data
|
struct n_tty_data
|
||||||
{
|
{
|
||||||
/* producer-published */
|
/* producer-published */
|
||||||
|
@ -136,6 +135,12 @@ rt_inline int test_and_clear_bit(int nr, volatile void *addr)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
rt_inline unsigned long __ffs(unsigned long word)
|
||||||
|
{
|
||||||
|
return __builtin_ffsl(word);
|
||||||
|
}
|
||||||
|
#else
|
||||||
rt_inline unsigned long __ffs(unsigned long word)
|
rt_inline unsigned long __ffs(unsigned long word)
|
||||||
{
|
{
|
||||||
int num = 0;
|
int num = 0;
|
||||||
|
@ -174,6 +179,7 @@ rt_inline unsigned long __ffs(unsigned long word)
|
||||||
|
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#define BITS_PER_LONG 32
|
#define BITS_PER_LONG 32
|
||||||
#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
|
#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
|
||||||
|
@ -703,13 +709,13 @@ static void __isig(int sig, struct tty_struct *tty)
|
||||||
ld->ops->set_termios(tty, &old_termios);
|
ld->ops->set_termios(tty, &old_termios);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tty_sigaddset(&lwp->signal_mask, SIGTTOU);
|
lwp_signal_kill(lwp, SIGTTOU, SI_USER, 0);
|
||||||
old_lwp = tty_pop(&tty->head, RT_NULL);
|
old_lwp = tty_pop(&tty->head, RT_NULL);
|
||||||
tty->foreground = old_lwp;
|
tty->foreground = old_lwp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lwp_kill(lwp_to_pid(lwp), sig);
|
lwp_signal_kill(lwp, sig, SI_USER, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,26 +126,6 @@ struct rt_lwp *tty_pop(struct tty_node **head, struct rt_lwp *target_lwp)
|
||||||
return lwp;
|
return lwp;
|
||||||
}
|
}
|
||||||
|
|
||||||
rt_inline int tty_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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int is_ignored(int sig)
|
|
||||||
{
|
|
||||||
return (tty_sigismember(¤t->signal_mask, sig) ||
|
|
||||||
current->signal_handler[sig-1] == SIG_IGN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tty_check_change - check for POSIX terminal changes
|
* tty_check_change - check for POSIX terminal changes
|
||||||
* @tty: tty to check
|
* @tty: tty to check
|
||||||
|
@ -160,7 +140,6 @@ static int is_ignored(int sig)
|
||||||
int __tty_check_change(struct tty_struct *tty, int sig)
|
int __tty_check_change(struct tty_struct *tty, int sig)
|
||||||
{
|
{
|
||||||
pid_t pgrp = 0, tty_pgrp = 0;
|
pid_t pgrp = 0, tty_pgrp = 0;
|
||||||
struct rt_lwp *lwp = tty->foreground;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int level = 0;
|
int level = 0;
|
||||||
|
|
||||||
|
@ -182,20 +161,7 @@ int __tty_check_change(struct tty_struct *tty, int sig)
|
||||||
|
|
||||||
if (tty_pgrp && (pgrp != tty->pgrp))
|
if (tty_pgrp && (pgrp != tty->pgrp))
|
||||||
{
|
{
|
||||||
if (is_ignored(sig))
|
lwp_signal_kill(current, sig, SI_USER, 0);
|
||||||
{
|
|
||||||
if (sig == SIGTTIN)
|
|
||||||
{
|
|
||||||
ret = -EIO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (lwp)
|
|
||||||
{
|
|
||||||
lwp_kill(lwp_to_pid(lwp), sig);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
rt_hw_interrupt_enable(level);
|
rt_hw_interrupt_enable(level);
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
* 2021-05-01 Meco Man support fixed timezone
|
* 2021-05-01 Meco Man support fixed timezone
|
||||||
* 2021-07-21 Meco Man implement that change/set timezone APIs
|
* 2021-07-21 Meco Man implement that change/set timezone APIs
|
||||||
* 2023-07-03 xqyjlj refactor posix time and timer
|
* 2023-07-03 xqyjlj refactor posix time and timer
|
||||||
|
* 2023-07-16 Shell update signal generation routine for lwp
|
||||||
|
* adapt to new api and do the signal handling in thread context
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "sys/time.h"
|
#include "sys/time.h"
|
||||||
|
@ -713,9 +715,56 @@ struct timer_obj
|
||||||
clockid_t clockid;
|
clockid_t clockid;
|
||||||
#ifdef RT_USING_SMART
|
#ifdef RT_USING_SMART
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
struct rt_work *work;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef RT_USING_SMART
|
||||||
|
struct lwp_timer_event_param
|
||||||
|
{
|
||||||
|
struct rt_work work;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
int tid;
|
||||||
|
pid_t pid;
|
||||||
|
};
|
||||||
|
int signo;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void _lwp_timer_event_from_tid(struct rt_work *work, void *param)
|
||||||
|
{
|
||||||
|
rt_err_t ret;
|
||||||
|
struct lwp_timer_event_param *data = (void *)work;
|
||||||
|
rt_thread_t thread;
|
||||||
|
|
||||||
|
RT_ASSERT(data->tid);
|
||||||
|
|
||||||
|
thread = lwp_tid_get_thread(data->tid);
|
||||||
|
ret = lwp_thread_signal_kill(thread, data->signo, SI_TIMER, 0);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
LOG_W("%s: Do kill failed(tid %d) returned %d", __func__, data->tid, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
rt_free(work);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _lwp_timer_event_from_pid(struct rt_work *work, void *param)
|
||||||
|
{
|
||||||
|
rt_err_t ret;
|
||||||
|
struct lwp_timer_event_param *data = (void *)work;
|
||||||
|
|
||||||
|
ret = lwp_signal_kill(lwp_from_pid(data->pid), data->signo, SI_TIMER, 0);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
LOG_W("%s: Do kill failed(pid %d) returned %d", __func__, data->pid, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
rt_free(work);
|
||||||
|
}
|
||||||
|
#endif /* RT_USING_SMART */
|
||||||
|
|
||||||
static void rtthread_timer_wrapper(void *timerobj)
|
static void rtthread_timer_wrapper(void *timerobj)
|
||||||
{
|
{
|
||||||
struct timer_obj *timer;
|
struct timer_obj *timer;
|
||||||
|
@ -735,7 +784,24 @@ static void rtthread_timer_wrapper(void *timerobj)
|
||||||
rt_ktime_hrtimer_start(&timer->hrtimer);
|
rt_ktime_hrtimer_start(&timer->hrtimer);
|
||||||
}
|
}
|
||||||
#ifdef RT_USING_SMART
|
#ifdef RT_USING_SMART
|
||||||
sys_kill(timer->pid, timer->sigev_signo);
|
/* this field is named as tid in musl */
|
||||||
|
int tid = *(int *)&timer->sigev_notify_function;
|
||||||
|
struct lwp_timer_event_param *data = (void *)timer->work;
|
||||||
|
data->signo = timer->sigev_signo;
|
||||||
|
|
||||||
|
if (!tid)
|
||||||
|
{
|
||||||
|
data->pid = timer->pid;
|
||||||
|
rt_work_init(timer->work, _lwp_timer_event_from_pid, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data->tid = tid;
|
||||||
|
rt_work_init(timer->work, _lwp_timer_event_from_tid, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rt_work_submit(timer->work, 0))
|
||||||
|
RT_ASSERT(0);
|
||||||
#else
|
#else
|
||||||
if(timer->sigev_notify_function != RT_NULL)
|
if(timer->sigev_notify_function != RT_NULL)
|
||||||
{
|
{
|
||||||
|
@ -802,7 +868,27 @@ int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid)
|
||||||
num %= 100;
|
num %= 100;
|
||||||
timer->sigev_signo = evp->sigev_signo;
|
timer->sigev_signo = evp->sigev_signo;
|
||||||
#ifdef RT_USING_SMART
|
#ifdef RT_USING_SMART
|
||||||
timer->pid = lwp_self()->pid;
|
struct rt_work *work;
|
||||||
|
struct rt_lwp *lwp = lwp_self();
|
||||||
|
|
||||||
|
work = rt_malloc(sizeof(struct lwp_timer_event_param));
|
||||||
|
if (!work)
|
||||||
|
{
|
||||||
|
rt_set_errno(ENOMEM);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lwp)
|
||||||
|
{
|
||||||
|
timer->pid = lwp_self()->pid;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timer->pid = 0; /* pid 0 is never used */
|
||||||
|
}
|
||||||
|
|
||||||
|
timer->work = work;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
timer->sigev_notify_function = evp->sigev_notify_function;
|
timer->sigev_notify_function = evp->sigev_notify_function;
|
||||||
timer->val = evp->sigev_value;
|
timer->val = evp->sigev_value;
|
||||||
|
|
|
@ -1,15 +1,20 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*
|
*
|
||||||
* Change Logs:
|
* Change Logs:
|
||||||
* Date Author Notes
|
* Date Author Notes
|
||||||
* 2021-05-18 Jesven first version
|
* 2021-05-18 Jesven first version
|
||||||
|
* 2023-07-16 Shell Move part of the codes to C from asm in signal handling
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <armv8.h>
|
||||||
#include <rthw.h>
|
#include <rthw.h>
|
||||||
#include <rtthread.h>
|
#include <rtthread.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <lwp_signal.h>
|
||||||
|
|
||||||
#ifdef ARCH_MM_MMU
|
#ifdef ARCH_MM_MMU
|
||||||
|
|
||||||
|
@ -92,3 +97,75 @@ int arch_expand_user_stack(void *addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
#define ALGIN_BYTES (16)
|
||||||
|
|
||||||
|
struct signal_ucontext
|
||||||
|
{
|
||||||
|
rt_int64_t sigreturn;
|
||||||
|
lwp_sigset_t save_sigmask;
|
||||||
|
|
||||||
|
siginfo_t si;
|
||||||
|
|
||||||
|
rt_align(16)
|
||||||
|
struct rt_hw_exp_stack frame;
|
||||||
|
};
|
||||||
|
|
||||||
|
void *arch_signal_ucontext_restore(rt_base_t user_sp)
|
||||||
|
{
|
||||||
|
struct signal_ucontext *new_sp;
|
||||||
|
new_sp = (void *)user_sp;
|
||||||
|
|
||||||
|
if (lwp_user_accessable(new_sp, sizeof(*new_sp)))
|
||||||
|
{
|
||||||
|
lwp_thread_signal_mask(rt_thread_self(), LWP_SIG_MASK_CMD_SET_MASK, &new_sp->save_sigmask, RT_NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_I("User frame corrupted during signal handling\nexiting...");
|
||||||
|
sys_exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (char *)&new_sp->frame + sizeof(struct rt_hw_exp_stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *arch_signal_ucontext_save(rt_base_t user_sp, siginfo_t *psiginfo,
|
||||||
|
struct rt_hw_exp_stack *exp_frame,
|
||||||
|
rt_base_t elr, rt_base_t spsr,
|
||||||
|
lwp_sigset_t *save_sig_mask)
|
||||||
|
{
|
||||||
|
struct signal_ucontext *new_sp;
|
||||||
|
new_sp = (void *)(user_sp - sizeof(struct signal_ucontext));
|
||||||
|
|
||||||
|
if (lwp_user_accessable(new_sp, sizeof(*new_sp)))
|
||||||
|
{
|
||||||
|
/* push psiginfo */
|
||||||
|
if (psiginfo)
|
||||||
|
{
|
||||||
|
memcpy(&new_sp->si, psiginfo, sizeof(*psiginfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* exp frame is already aligned as AAPCS64 required */
|
||||||
|
memcpy(&new_sp->frame, exp_frame, sizeof(*exp_frame));
|
||||||
|
|
||||||
|
/* fix the 3 fields in exception frame, so that memcpy will be fine */
|
||||||
|
new_sp->frame.pc = elr;
|
||||||
|
new_sp->frame.cpsr = spsr;
|
||||||
|
new_sp->frame.sp_el0 = user_sp;
|
||||||
|
|
||||||
|
/* copy the save_sig_mask */
|
||||||
|
memcpy(&new_sp->save_sigmask, save_sig_mask, sizeof(lwp_sigset_t));
|
||||||
|
|
||||||
|
/* copy lwp_sigreturn */
|
||||||
|
const size_t lwp_sigreturn_bytes = 8;
|
||||||
|
extern void lwp_sigreturn(void);
|
||||||
|
/* -> ensure that the sigreturn start at the outer most boundary */
|
||||||
|
memcpy(&new_sp->sigreturn, &lwp_sigreturn, lwp_sigreturn_bytes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_I("%s: User stack overflow", __func__);
|
||||||
|
sys_exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_sp;
|
||||||
|
}
|
||||||
|
|
|
@ -36,6 +36,28 @@ rt_inline void icache_invalid_all(void)
|
||||||
asm volatile ("ic ialluis\n\tisb sy":::"memory");
|
asm volatile ("ic ialluis\n\tisb sy":::"memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Save signal-related context to user stack
|
||||||
|
*
|
||||||
|
* @param user_sp the current sp of user
|
||||||
|
* @param exp_frame exception frame to resume former execution
|
||||||
|
* @param psiginfo pointer to the siginfo
|
||||||
|
* @param elr pc of former execution
|
||||||
|
* @param spsr program status of former execution
|
||||||
|
* @return void* the new user sp
|
||||||
|
*/
|
||||||
|
void *arch_signal_ucontext_save(rt_base_t user_sp, siginfo_t *psiginfo,
|
||||||
|
struct rt_hw_exp_stack *exp_frame,
|
||||||
|
rt_base_t elr, rt_base_t spsr,
|
||||||
|
lwp_sigset_t *save_sig_mask);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Restore the signal mask after return
|
||||||
|
*
|
||||||
|
* @param user_sp sp of user
|
||||||
|
* @return void*
|
||||||
|
*/
|
||||||
|
void *arch_signal_ucontext_restore(rt_base_t user_sp);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*
|
*
|
||||||
* Change Logs:
|
* Change Logs:
|
||||||
* Date Author Notes
|
* Date Author Notes
|
||||||
* 2021-05-18 Jesven first version
|
* 2021-05-18 Jesven first version
|
||||||
|
* 2023-07-16 Shell Move part of the codes to C from asm in signal handling
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
@ -192,8 +193,9 @@ arch_syscall_exit:
|
||||||
add sp, sp, #0x40
|
add sp, sp, #0x40
|
||||||
RESTORE_FPU sp
|
RESTORE_FPU sp
|
||||||
|
|
||||||
.global arch_ret_to_user
|
/* the sp is reset to the outer most level */
|
||||||
arch_ret_to_user:
|
START_POINT(arch_ret_to_user)
|
||||||
|
/* save exception frame */
|
||||||
SAVE_FPU sp
|
SAVE_FPU sp
|
||||||
stp x0, x1, [sp, #-0x10]!
|
stp x0, x1, [sp, #-0x10]!
|
||||||
stp x2, x3, [sp, #-0x10]!
|
stp x2, x3, [sp, #-0x10]!
|
||||||
|
@ -216,12 +218,16 @@ arch_ret_to_user:
|
||||||
stp x0, x1, [sp, #-0x10]!
|
stp x0, x1, [sp, #-0x10]!
|
||||||
stp x29, x30, [sp, #-0x10]!
|
stp x29, x30, [sp, #-0x10]!
|
||||||
|
|
||||||
|
/* pre-action */
|
||||||
bl lwp_check_debug
|
bl lwp_check_debug
|
||||||
|
|
||||||
bl lwp_check_exit_request
|
bl lwp_check_exit_request
|
||||||
cbz w0, 1f
|
cbz w0, 1f
|
||||||
|
/* exit on event */
|
||||||
mov x0, xzr
|
mov x0, xzr
|
||||||
b sys_exit
|
b sys_exit
|
||||||
1:
|
1:
|
||||||
|
/* check if dbg ops exist */
|
||||||
ldr x0, =rt_dbg_ops
|
ldr x0, =rt_dbg_ops
|
||||||
ldr x0, [x0]
|
ldr x0, [x0]
|
||||||
cbz x0, 3f
|
cbz x0, 3f
|
||||||
|
@ -236,9 +242,17 @@ arch_ret_to_user:
|
||||||
bic x2, x2, x1
|
bic x2, x2, x1
|
||||||
msr spsr_el1, x2
|
msr spsr_el1, x2
|
||||||
3:
|
3:
|
||||||
bl lwp_signal_check
|
|
||||||
cmp x0, xzr
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* push 2 dummy words to simulate a exception frame of interrupt
|
||||||
|
*/
|
||||||
|
add sp, sp, #-0x10
|
||||||
|
mov x0, sp
|
||||||
|
bl lwp_thread_signal_catch
|
||||||
|
add sp, sp, #0x10
|
||||||
|
|
||||||
|
/* check debug */
|
||||||
|
/* restore exception frame */
|
||||||
ldp x29, x30, [sp], #0x10
|
ldp x29, x30, [sp], #0x10
|
||||||
ldp x0, x1, [sp], #0x10
|
ldp x0, x1, [sp], #0x10
|
||||||
msr fpcr, x0
|
msr fpcr, x0
|
||||||
|
@ -261,14 +275,14 @@ arch_ret_to_user:
|
||||||
ldp x0, x1, [sp], #0x10
|
ldp x0, x1, [sp], #0x10
|
||||||
RESTORE_FPU sp
|
RESTORE_FPU sp
|
||||||
|
|
||||||
bne user_do_signal
|
|
||||||
|
|
||||||
stp x0, x1, [sp, #-0x10]!
|
stp x0, x1, [sp, #-0x10]!
|
||||||
ldr x0, =rt_dbg_ops
|
ldr x0, =rt_dbg_ops
|
||||||
ldr x0, [x0]
|
ldr x0, [x0]
|
||||||
cmp x0, xzr
|
cmp x0, xzr
|
||||||
ldp x0, x1, [sp], #0x10
|
ldp x0, x1, [sp], #0x10
|
||||||
beq 1f
|
beq 1f
|
||||||
|
|
||||||
|
/* save */
|
||||||
SAVE_FPU sp
|
SAVE_FPU sp
|
||||||
stp x0, x1, [sp, #-0x10]!
|
stp x0, x1, [sp, #-0x10]!
|
||||||
stp x2, x3, [sp, #-0x10]!
|
stp x2, x3, [sp, #-0x10]!
|
||||||
|
@ -289,8 +303,11 @@ arch_ret_to_user:
|
||||||
mrs x1, fpsr
|
mrs x1, fpsr
|
||||||
stp x0, x1, [sp, #-0x10]!
|
stp x0, x1, [sp, #-0x10]!
|
||||||
stp x29, x30, [sp, #-0x10]!
|
stp x29, x30, [sp, #-0x10]!
|
||||||
|
|
||||||
mrs x0, elr_el1
|
mrs x0, elr_el1
|
||||||
bl dbg_attach_req
|
bl dbg_attach_req
|
||||||
|
|
||||||
|
/* restore */
|
||||||
ldp x29, x30, [sp], #0x10
|
ldp x29, x30, [sp], #0x10
|
||||||
ldp x0, x1, [sp], #0x10
|
ldp x0, x1, [sp], #0x10
|
||||||
msr fpcr, x0
|
msr fpcr, x0
|
||||||
|
@ -313,6 +330,7 @@ arch_ret_to_user:
|
||||||
RESTORE_FPU sp
|
RESTORE_FPU sp
|
||||||
1:
|
1:
|
||||||
eret
|
eret
|
||||||
|
START_POINT_END(arch_ret_to_user)
|
||||||
|
|
||||||
.global lwp_check_debug
|
.global lwp_check_debug
|
||||||
lwp_check_debug:
|
lwp_check_debug:
|
||||||
|
@ -371,26 +389,28 @@ lwp_check_debug_quit:
|
||||||
|
|
||||||
arch_signal_quit:
|
arch_signal_quit:
|
||||||
msr daifset, #3
|
msr daifset, #3
|
||||||
/*
|
|
||||||
drop stack data
|
|
||||||
*/
|
|
||||||
add sp, sp, #CONTEXT_SIZE
|
|
||||||
bl lwp_signal_restore
|
|
||||||
/* x0 is user_ctx : ori sp, pc, cpsr */
|
|
||||||
ldr x1, [x0]
|
|
||||||
ldr x2, [x0, #8]
|
|
||||||
ldr x3, [x0, #16]
|
|
||||||
msr spsr_el1, x3
|
|
||||||
msr elr_el1, x2
|
|
||||||
add x1, x1, #16
|
|
||||||
msr sp_el0, x1
|
|
||||||
|
|
||||||
|
/* drop current exception frame */
|
||||||
|
add sp, sp, #CONTEXT_SIZE
|
||||||
|
mrs x0, sp_el0
|
||||||
|
bl arch_signal_ucontext_restore
|
||||||
|
add x0, x0, #-CONTEXT_SIZE
|
||||||
|
msr sp_el0, x0
|
||||||
|
|
||||||
|
/* restore previous exception frame */
|
||||||
msr spsel, #0
|
msr spsel, #0
|
||||||
|
|
||||||
|
ldp x2, x3, [sp], #0x10
|
||||||
|
msr elr_el1, x2
|
||||||
|
msr spsr_el1, x3
|
||||||
|
|
||||||
ldp x29, x30, [sp], #0x10
|
ldp x29, x30, [sp], #0x10
|
||||||
|
// msr sp_el0, x29
|
||||||
|
|
||||||
ldp x28, x29, [sp], #0x10
|
ldp x28, x29, [sp], #0x10
|
||||||
msr fpcr, x28
|
msr fpcr, x28
|
||||||
msr fpsr, x29
|
msr fpsr, x29
|
||||||
|
|
||||||
ldp x28, x29, [sp], #0x10
|
ldp x28, x29, [sp], #0x10
|
||||||
ldp x26, x27, [sp], #0x10
|
ldp x26, x27, [sp], #0x10
|
||||||
ldp x24, x25, [sp], #0x10
|
ldp x24, x25, [sp], #0x10
|
||||||
|
@ -412,65 +432,69 @@ arch_signal_quit:
|
||||||
|
|
||||||
b arch_ret_to_user
|
b arch_ret_to_user
|
||||||
|
|
||||||
user_do_signal:
|
/**
|
||||||
msr spsel, #0
|
* rt_noreturn
|
||||||
SAVE_FPU sp
|
* void arch_thread_signal_enter(
|
||||||
stp x0, x1, [sp, #-0x10]!
|
* int signo, -> x0
|
||||||
stp x2, x3, [sp, #-0x10]!
|
* siginfo_t *psiginfo, -> x1
|
||||||
stp x4, x5, [sp, #-0x10]!
|
* void *exp_frame, -> x2
|
||||||
stp x6, x7, [sp, #-0x10]!
|
* void *entry_uaddr, -> x3
|
||||||
stp x8, x9, [sp, #-0x10]!
|
* lwp_sigset_t *save_sig_mask, -> x4
|
||||||
stp x10, x11, [sp, #-0x10]!
|
* )
|
||||||
stp x12, x13, [sp, #-0x10]!
|
*/
|
||||||
stp x14, x15, [sp, #-0x10]!
|
.global arch_thread_signal_enter
|
||||||
stp x16, x17, [sp, #-0x10]!
|
arch_thread_signal_enter:
|
||||||
stp x18, x19, [sp, #-0x10]!
|
mov x19, x0
|
||||||
stp x20, x21, [sp, #-0x10]!
|
mov x20, x2 /* exp_frame */
|
||||||
stp x22, x23, [sp, #-0x10]!
|
mov x21, x3
|
||||||
stp x24, x25, [sp, #-0x10]!
|
|
||||||
stp x26, x27, [sp, #-0x10]!
|
|
||||||
stp x28, x29, [sp, #-0x10]!
|
|
||||||
mrs x28, fpcr
|
|
||||||
mrs x29, fpsr
|
|
||||||
stp x28, x29, [sp, #-0x10]!
|
|
||||||
stp x29, x30, [sp, #-0x10]!
|
|
||||||
|
|
||||||
sub sp, sp, #0x10
|
/**
|
||||||
adr x0, lwp_sigreturn
|
* move exception frame to user stack
|
||||||
ldr w1, [x0]
|
*/
|
||||||
str w1, [sp]
|
mrs x0, sp_el0
|
||||||
ldr w1, [x0, #4]
|
mrs x3, elr_el1
|
||||||
str w1, [sp, #4]
|
mov x5, x4
|
||||||
|
/** FIXME: spsr must restore from exception frame */
|
||||||
|
mrs x4, spsr_el1
|
||||||
|
|
||||||
mov x20, sp /* lwp_sigreturn */
|
/* arch_signal_ucontext_save(user_sp, psiginfo, exp_frame, elr, spsr, save_sig_mask); */
|
||||||
mov x0, sp
|
bl arch_signal_ucontext_save
|
||||||
|
|
||||||
dc cvau, x0
|
dc cvau, x0
|
||||||
dsb sy
|
dsb sy
|
||||||
ic ialluis
|
ic ialluis
|
||||||
dsb sy
|
dsb sy
|
||||||
|
|
||||||
msr spsel, #1
|
/**
|
||||||
|
* @brief Prepare the environment for signal handler
|
||||||
|
*/
|
||||||
|
|
||||||
mrs x1, elr_el1
|
/** drop exp frame on kernel stack, reset kernel sp */
|
||||||
mrs x2, spsr_el1
|
add sp, x20, #CONTEXT_SIZE
|
||||||
bl lwp_signal_backup
|
|
||||||
/* x0 is signal */
|
/** reset user sp */
|
||||||
mov x19, x0
|
msr sp_el0, x0
|
||||||
bl lwp_sighandler_get
|
/** set the return address to the sigreturn */
|
||||||
adds x1, x0, xzr
|
mov x30, x0
|
||||||
|
|
||||||
|
/** set the entry address of signal handler */
|
||||||
|
msr elr_el1, x21
|
||||||
|
|
||||||
|
/* siginfo is above the return address */
|
||||||
|
add x2, x30, 16
|
||||||
|
add x1, x2, #CONTEXT_SIZE
|
||||||
mov x0, x19
|
mov x0, x19
|
||||||
bne 1f
|
|
||||||
mov x1, x20
|
/**
|
||||||
1:
|
* handler(signo, psi, ucontext);
|
||||||
msr elr_el1, x1
|
*/
|
||||||
mov x30, x20
|
|
||||||
eret
|
eret
|
||||||
|
|
||||||
lwp_debugreturn:
|
lwp_debugreturn:
|
||||||
mov x8, 0xf000
|
mov x8, 0xf000
|
||||||
svc #0
|
svc #0
|
||||||
|
|
||||||
|
.global lwp_sigreturn
|
||||||
lwp_sigreturn:
|
lwp_sigreturn:
|
||||||
mov x8, #0xe000
|
mov x8, #0xe000
|
||||||
svc #0
|
svc #0
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*
|
*
|
||||||
* Change Logs:
|
* Change Logs:
|
||||||
* Date Author Notes
|
* Date Author Notes
|
||||||
* 2019-10-28 Jesven first version
|
* 2019-10-28 Jesven first version
|
||||||
|
* 2023-07-16 Shell Move part of the codes to C from asm in signal handling
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <rthw.h>
|
#include <rthw.h>
|
||||||
#include <rtthread.h>
|
#include <rtthread.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#ifdef ARCH_MM_MMU
|
#ifdef ARCH_MM_MMU
|
||||||
|
|
||||||
|
@ -54,7 +56,7 @@ void arch_kuser_init(rt_aspace_t aspace, void *vectors)
|
||||||
{
|
{
|
||||||
const size_t kuser_size = 0x1000;
|
const size_t kuser_size = 0x1000;
|
||||||
int err;
|
int err;
|
||||||
extern char __kuser_helper_start[], __kuser_helper_end[];
|
extern char *__kuser_helper_start, *__kuser_helper_end;
|
||||||
int kuser_sz = __kuser_helper_end - __kuser_helper_start;
|
int kuser_sz = __kuser_helper_end - __kuser_helper_start;
|
||||||
|
|
||||||
err = rt_aspace_map_static(aspace, &kuser_varea, &vectors, kuser_size,
|
err = rt_aspace_map_static(aspace, &kuser_varea, &vectors, kuser_size,
|
||||||
|
@ -109,6 +111,88 @@ int arch_expand_user_stack(void *addr)
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#define ALGIN_BYTES 8
|
||||||
|
#define lwp_sigreturn_bytes 8
|
||||||
|
struct signal_regs {
|
||||||
|
rt_base_t lr;
|
||||||
|
rt_base_t spsr;
|
||||||
|
rt_base_t r0_to_r12[13];
|
||||||
|
rt_base_t ip;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct signal_ucontext
|
||||||
|
{
|
||||||
|
rt_base_t sigreturn[lwp_sigreturn_bytes / sizeof(rt_base_t)];
|
||||||
|
lwp_sigset_t save_sigmask;
|
||||||
|
|
||||||
|
siginfo_t si;
|
||||||
|
|
||||||
|
rt_align(8)
|
||||||
|
struct signal_regs frame;
|
||||||
|
};
|
||||||
|
|
||||||
|
void *arch_signal_ucontext_restore(rt_base_t user_sp)
|
||||||
|
{
|
||||||
|
struct signal_ucontext *new_sp;
|
||||||
|
rt_base_t ip;
|
||||||
|
new_sp = (void *)user_sp;
|
||||||
|
|
||||||
|
if (lwp_user_accessable(new_sp, sizeof(*new_sp)))
|
||||||
|
{
|
||||||
|
lwp_thread_signal_mask(rt_thread_self(), LWP_SIG_MASK_CMD_SET_MASK, &new_sp->save_sigmask, RT_NULL);
|
||||||
|
ip = new_sp->frame.ip;
|
||||||
|
/* let user restore its lr from frame.ip */
|
||||||
|
new_sp->frame.ip = new_sp->frame.lr;
|
||||||
|
/* kernel will pick eip from frame.lr */
|
||||||
|
new_sp->frame.lr = ip;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_I("User frame corrupted during signal handling\nexiting...");
|
||||||
|
sys_exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (void *)&new_sp->frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *arch_signal_ucontext_save(rt_base_t lr, siginfo_t *psiginfo,
|
||||||
|
struct signal_regs *exp_frame, rt_base_t user_sp,
|
||||||
|
lwp_sigset_t *save_sig_mask)
|
||||||
|
{
|
||||||
|
rt_base_t spsr;
|
||||||
|
struct signal_ucontext *new_sp;
|
||||||
|
new_sp = (void *)(user_sp - sizeof(struct signal_ucontext));
|
||||||
|
|
||||||
|
if (lwp_user_accessable(new_sp, sizeof(*new_sp)))
|
||||||
|
{
|
||||||
|
/* push psiginfo */
|
||||||
|
if (psiginfo)
|
||||||
|
{
|
||||||
|
memcpy(&new_sp->si, psiginfo, sizeof(*psiginfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&new_sp->frame.r0_to_r12, exp_frame, sizeof(new_sp->frame.r0_to_r12) + sizeof(rt_base_t));
|
||||||
|
new_sp->frame.lr = lr;
|
||||||
|
|
||||||
|
__asm__ volatile("mrs %0, spsr":"=r"(spsr));
|
||||||
|
new_sp->frame.spsr = spsr;
|
||||||
|
|
||||||
|
/* copy the save_sig_mask */
|
||||||
|
memcpy(&new_sp->save_sigmask, save_sig_mask, sizeof(lwp_sigset_t));
|
||||||
|
|
||||||
|
/* copy lwp_sigreturn */
|
||||||
|
extern void lwp_sigreturn(void);
|
||||||
|
/* -> ensure that the sigreturn start at the outer most boundary */
|
||||||
|
memcpy(&new_sp->sigreturn, &lwp_sigreturn, lwp_sigreturn_bytes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_I("%s: User stack overflow", __func__);
|
||||||
|
sys_exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_sp;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef LWP_ENABLE_ASID
|
#ifdef LWP_ENABLE_ASID
|
||||||
#define MAX_ASID_BITS 8
|
#define MAX_ASID_BITS 8
|
||||||
|
|
|
@ -40,6 +40,12 @@ rt_inline void icache_invalid_all(void)
|
||||||
|
|
||||||
unsigned int arch_get_asid(struct rt_lwp *lwp);
|
unsigned int arch_get_asid(struct rt_lwp *lwp);
|
||||||
|
|
||||||
|
struct signal_regs;
|
||||||
|
void *arch_signal_ucontext_restore(rt_base_t user_sp);
|
||||||
|
void *arch_signal_ucontext_save(rt_base_t lr, siginfo_t *psiginfo,
|
||||||
|
struct signal_regs *exp_frame, rt_base_t user_sp,
|
||||||
|
lwp_sigset_t *save_sig_mask);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
* Change Logs:
|
* Change Logs:
|
||||||
* Date Author Notes
|
* Date Author Notes
|
||||||
* 2018-12-10 Jesven first version
|
* 2018-12-10 Jesven first version
|
||||||
|
* 2023-07-16 Shell Move part of the codes to C from asm in signal handling
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "rtconfig.h"
|
#include "rtconfig.h"
|
||||||
|
@ -191,7 +192,7 @@ arch_syscall_exit:
|
||||||
|
|
||||||
.global arch_ret_to_user
|
.global arch_ret_to_user
|
||||||
arch_ret_to_user:
|
arch_ret_to_user:
|
||||||
push {r0-r3, r12, lr}
|
push {r0-r12, lr}
|
||||||
bl lwp_check_debug
|
bl lwp_check_debug
|
||||||
bl lwp_check_exit_request
|
bl lwp_check_exit_request
|
||||||
cmp r0, #0
|
cmp r0, #0
|
||||||
|
@ -199,10 +200,10 @@ arch_ret_to_user:
|
||||||
mov r0, #0
|
mov r0, #0
|
||||||
b sys_exit
|
b sys_exit
|
||||||
1:
|
1:
|
||||||
bl lwp_signal_check
|
mov r0, sp
|
||||||
cmp r0, #0
|
/* r0 -> exp frame */
|
||||||
pop {r0-r3, r12, lr}
|
bl lwp_thread_signal_catch
|
||||||
bne user_do_signal
|
pop {r0-r12, lr}
|
||||||
|
|
||||||
push {r0}
|
push {r0}
|
||||||
ldr r0, =rt_dbg_ops
|
ldr r0, =rt_dbg_ops
|
||||||
|
@ -273,35 +274,65 @@ lwp_check_debug_quit:
|
||||||
|
|
||||||
arch_signal_quit:
|
arch_signal_quit:
|
||||||
cpsid i
|
cpsid i
|
||||||
|
/* drop context of signal handler */
|
||||||
pop {r0 - r3, r12}
|
pop {r0 - r3, r12}
|
||||||
pop {r4, r5, lr}
|
pop {r4, r5, lr}
|
||||||
pop {lr}
|
pop {lr}
|
||||||
bl lwp_signal_restore
|
|
||||||
/* r0 is user_ctx : ori sp, pc, cpsr*/
|
/* restore context */
|
||||||
ldr r1, [r0]
|
|
||||||
ldr r2, [r0, #4]
|
|
||||||
ldr r3, [r0, #8]
|
|
||||||
msr spsr_cxsf, r3
|
|
||||||
mov lr, r2
|
|
||||||
cps #Mode_SYS
|
cps #Mode_SYS
|
||||||
mov sp, r1
|
mov r0, sp
|
||||||
|
cps #Mode_SVC
|
||||||
|
bl arch_signal_ucontext_restore
|
||||||
|
|
||||||
|
/* lr <- *(&frame.ip) */
|
||||||
|
ldr lr, [r0]
|
||||||
|
cps #Mode_SYS
|
||||||
|
mov sp, r0
|
||||||
|
|
||||||
|
/* drop ip in the frame and restore cpsr */
|
||||||
|
pop {r0}
|
||||||
|
pop {r0}
|
||||||
|
msr spsr_cxsf, r0
|
||||||
pop {r0-r12, lr}
|
pop {r0-r12, lr}
|
||||||
cps #Mode_SVC
|
cps #Mode_SVC
|
||||||
|
|
||||||
b arch_ret_to_user
|
b arch_ret_to_user
|
||||||
|
|
||||||
user_do_signal:
|
/**
|
||||||
mov r0, r0
|
* rt_noreturn
|
||||||
|
* void arch_thread_signal_enter(
|
||||||
|
* int signo, -> r0
|
||||||
|
* siginfo_t *psiginfo, -> r1
|
||||||
|
* void *exp_frame, -> r2
|
||||||
|
* void *entry_uaddr, -> r3
|
||||||
|
* lwp_sigset_t *save_sig_mask, -> ??
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
.global arch_thread_signal_enter
|
||||||
|
arch_thread_signal_enter:
|
||||||
|
mov r4, r0
|
||||||
|
mov r5, r3
|
||||||
|
|
||||||
cps #Mode_SYS
|
cps #Mode_SYS
|
||||||
push {r0-r12, lr}
|
mov r0, lr
|
||||||
|
mov r3, sp
|
||||||
|
cps #Mode_SVC
|
||||||
|
bl arch_signal_ucontext_save
|
||||||
|
|
||||||
sub sp, #8
|
/* reset user sp */
|
||||||
ldr r0, =lwp_sigreturn
|
cps #Mode_SYS
|
||||||
ldr r1, [r0]
|
mov sp, r0
|
||||||
str r1, [sp]
|
mov lr, r0
|
||||||
ldr r1, [r0, #4]
|
cps #Mode_SVC
|
||||||
str r1, [sp, #4]
|
|
||||||
|
|
||||||
mov r1, sp
|
/* r1,r2 <- new_user_sp */
|
||||||
|
mov r1, r0
|
||||||
|
mov r2, r0
|
||||||
|
/* r0 <- signo */
|
||||||
|
mov r0, r4
|
||||||
|
|
||||||
|
mov r1, r0
|
||||||
mcr p15, 0, r1, c7, c11, 1 ;//dc cmvau
|
mcr p15, 0, r1, c7, c11, 1 ;//dc cmvau
|
||||||
add r1, #4
|
add r1, #4
|
||||||
mcr p15, 0, r1, c7, c11, 1 ;//dc cmvau
|
mcr p15, 0, r1, c7, c11, 1 ;//dc cmvau
|
||||||
|
@ -311,27 +342,25 @@ user_do_signal:
|
||||||
dsb
|
dsb
|
||||||
isb
|
isb
|
||||||
|
|
||||||
mov r5, sp ;//if func is 0
|
/* r4 <- &sigreturn */
|
||||||
mov lr, sp
|
mov r4, r2
|
||||||
|
|
||||||
add r0, sp, #8 /* lwp_sigreturn */
|
/* lr <- user_handler() */
|
||||||
cps #Mode_SVC
|
mov lr, r5
|
||||||
mov r1, lr
|
|
||||||
mrs r2, spsr
|
|
||||||
bl lwp_signal_backup
|
|
||||||
/* r0 is signal */
|
|
||||||
mov r4, r0
|
|
||||||
bl lwp_sighandler_get
|
|
||||||
mov lr, r0
|
|
||||||
cmp lr, #0
|
cmp lr, #0
|
||||||
moveq lr, r5
|
moveq lr, r4
|
||||||
mov r0, r4
|
|
||||||
|
/* r1 <- siginfo */
|
||||||
|
mov r1, r2
|
||||||
|
add r1, #8
|
||||||
|
/* handler(signo, siginfo, ucontext) */
|
||||||
movs pc, lr
|
movs pc, lr
|
||||||
|
|
||||||
lwp_debugreturn:
|
lwp_debugreturn:
|
||||||
mov r7, #0xf000
|
mov r7, #0xf000
|
||||||
svc #0
|
svc #0
|
||||||
|
|
||||||
|
.global lwp_sigreturn
|
||||||
lwp_sigreturn:
|
lwp_sigreturn:
|
||||||
mov r7, #0xe000
|
mov r7, #0xe000
|
||||||
svc #0
|
svc #0
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
* 2021-03-04 lizhirui modify for new version of rt-smart
|
* 2021-03-04 lizhirui modify for new version of rt-smart
|
||||||
* 2021-11-22 JasonHu add lwp_set_thread_context
|
* 2021-11-22 JasonHu add lwp_set_thread_context
|
||||||
* 2021-11-30 JasonHu add clone/fork support
|
* 2021-11-30 JasonHu add clone/fork support
|
||||||
|
* 2023-07-16 Shell Move part of the codes to C from asm in signal handling
|
||||||
*/
|
*/
|
||||||
#include <rthw.h>
|
#include <rthw.h>
|
||||||
#include <rtthread.h>
|
#include <rtthread.h>
|
||||||
|
@ -34,6 +35,7 @@
|
||||||
#include <cpuport.h>
|
#include <cpuport.h>
|
||||||
#include <encoding.h>
|
#include <encoding.h>
|
||||||
#include <stack.h>
|
#include <stack.h>
|
||||||
|
#include <cache.h>
|
||||||
|
|
||||||
extern rt_ubase_t MMUTable[];
|
extern rt_ubase_t MMUTable[];
|
||||||
|
|
||||||
|
@ -245,6 +247,79 @@ int arch_set_thread_context(void (*exit)(void), void *new_thread_stack,
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ALGIN_BYTES (16)
|
||||||
|
|
||||||
|
struct signal_ucontext
|
||||||
|
{
|
||||||
|
rt_int64_t sigreturn;
|
||||||
|
lwp_sigset_t save_sigmask;
|
||||||
|
|
||||||
|
siginfo_t si;
|
||||||
|
|
||||||
|
rt_align(16)
|
||||||
|
struct rt_hw_stack_frame frame;
|
||||||
|
};
|
||||||
|
|
||||||
|
void *arch_signal_ucontext_restore(rt_base_t user_sp)
|
||||||
|
{
|
||||||
|
struct signal_ucontext *new_sp;
|
||||||
|
new_sp = (void *)user_sp;
|
||||||
|
|
||||||
|
if (lwp_user_accessable(new_sp, sizeof(*new_sp)))
|
||||||
|
{
|
||||||
|
lwp_thread_signal_mask(rt_thread_self(), LWP_SIG_MASK_CMD_SET_MASK, &new_sp->save_sigmask, RT_NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_I("User frame corrupted during signal handling\nexiting...");
|
||||||
|
sys_exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (void *)&new_sp->frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *arch_signal_ucontext_save(int signo, siginfo_t *psiginfo,
|
||||||
|
struct rt_hw_stack_frame *exp_frame, rt_base_t user_sp,
|
||||||
|
lwp_sigset_t *save_sig_mask)
|
||||||
|
{
|
||||||
|
struct signal_ucontext *new_sp;
|
||||||
|
new_sp = (void *)(user_sp - sizeof(struct signal_ucontext));
|
||||||
|
|
||||||
|
if (lwp_user_accessable(new_sp, sizeof(*new_sp)))
|
||||||
|
{
|
||||||
|
/* push psiginfo */
|
||||||
|
if (psiginfo)
|
||||||
|
{
|
||||||
|
memcpy(&new_sp->si, psiginfo, sizeof(*psiginfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&new_sp->frame, exp_frame, sizeof(*exp_frame));
|
||||||
|
|
||||||
|
/* copy the save_sig_mask */
|
||||||
|
memcpy(&new_sp->save_sigmask, save_sig_mask, sizeof(lwp_sigset_t));
|
||||||
|
|
||||||
|
/* copy lwp_sigreturn */
|
||||||
|
const size_t lwp_sigreturn_bytes = 8;
|
||||||
|
extern void lwp_sigreturn(void);
|
||||||
|
/* -> ensure that the sigreturn start at the outer most boundary */
|
||||||
|
memcpy(&new_sp->sigreturn, &lwp_sigreturn, lwp_sigreturn_bytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* synchronize dcache & icache if target is
|
||||||
|
* a Harvard Architecture machine, otherwise
|
||||||
|
* do nothing
|
||||||
|
*/
|
||||||
|
rt_hw_sync_cache_local(&new_sp->sigreturn, 8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_I("%s: User stack overflow", __func__);
|
||||||
|
sys_exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_sp;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* void lwp_exec_user(void *args, void *kernel_stack, void *user_entry)
|
* void lwp_exec_user(void *args, void *kernel_stack, void *user_entry)
|
||||||
*/
|
*/
|
||||||
|
@ -253,9 +328,4 @@ void lwp_exec_user(void *args, void *kernel_stack, void *user_entry)
|
||||||
arch_start_umode(args, user_entry, (void *)USER_STACK_VEND, kernel_stack);
|
arch_start_umode(args, user_entry, (void *)USER_STACK_VEND, kernel_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *arch_get_usp_from_uctx(struct rt_user_context *uctx)
|
|
||||||
{
|
|
||||||
return uctx->sp;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* ARCH_MM_MMU */
|
#endif /* ARCH_MM_MMU */
|
||||||
|
|
|
@ -59,6 +59,11 @@ rt_inline void icache_invalid_all(void)
|
||||||
rt_hw_cpu_icache_invalidate_all();
|
rt_hw_cpu_icache_invalidate_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct rt_hw_stack_frame;
|
||||||
|
void *arch_signal_ucontext_restore(rt_base_t user_sp);
|
||||||
|
void *arch_signal_ucontext_save(int signo, siginfo_t *psiginfo,
|
||||||
|
struct rt_hw_stack_frame *exp_frame, rt_base_t user_sp,
|
||||||
|
lwp_sigset_t *save_sig_mask);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
* 2021-02-19 lizhirui port to new version of rt-smart
|
* 2021-02-19 lizhirui port to new version of rt-smart
|
||||||
* 2022-11-08 Wangxiaoyao Cleanup codes;
|
* 2022-11-08 Wangxiaoyao Cleanup codes;
|
||||||
* Support new context switch
|
* Support new context switch
|
||||||
|
* 2023-07-16 Shell Move part of the codes to C from asm in signal handling
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "rtconfig.h"
|
#include "rtconfig.h"
|
||||||
|
@ -89,9 +90,8 @@ arch_ret_to_user:
|
||||||
call sys_exit
|
call sys_exit
|
||||||
|
|
||||||
1:
|
1:
|
||||||
call lwp_signal_check
|
mv a0, sp
|
||||||
beqz a0, ret_to_user_exit
|
call lwp_thread_signal_catch
|
||||||
J user_do_signal
|
|
||||||
|
|
||||||
ret_to_user_exit:
|
ret_to_user_exit:
|
||||||
RESTORE_ALL
|
RESTORE_ALL
|
||||||
|
@ -103,129 +103,80 @@ ret_to_user_exit:
|
||||||
* And handle pending signals;
|
* And handle pending signals;
|
||||||
*/
|
*/
|
||||||
arch_signal_quit:
|
arch_signal_quit:
|
||||||
call lwp_signal_restore
|
LOAD a0, FRAME_OFF_SP(sp)
|
||||||
call arch_get_usp_from_uctx
|
call arch_signal_ucontext_restore
|
||||||
// return value is user sp
|
|
||||||
|
/* reset kernel sp to the stack */
|
||||||
|
STORE sp, FRAME_OFF_SP(a0)
|
||||||
|
/* return value is user sp */
|
||||||
mv sp, a0
|
mv sp, a0
|
||||||
|
|
||||||
// restore user sp before enter trap
|
/* restore user sp before enter trap */
|
||||||
addi a0, sp, CTX_REG_NR * REGBYTES
|
addi a0, sp, CTX_REG_NR * REGBYTES
|
||||||
csrw sscratch, a0
|
csrw sscratch, a0
|
||||||
|
|
||||||
|
|
||||||
RESTORE_ALL
|
RESTORE_ALL
|
||||||
SAVE_ALL
|
SAVE_ALL
|
||||||
j arch_ret_to_user
|
j arch_ret_to_user
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare and enter user signal handler
|
* rt_noreturn
|
||||||
* Move user exception frame and setup signal return
|
* void arch_thread_signal_enter(
|
||||||
* routine in user stack
|
* int signo, -> a0
|
||||||
|
* siginfo_t *psiginfo, -> a1
|
||||||
|
* void *exp_frame, -> a2
|
||||||
|
* void *entry_uaddr, -> a3
|
||||||
|
* lwp_sigset_t *save_sig_mask, -> a4
|
||||||
|
* )
|
||||||
*/
|
*/
|
||||||
user_do_signal:
|
.global arch_thread_signal_enter
|
||||||
/* prefetch ustack to avoid corrupted status in RESTORE/STORE pair below */
|
arch_thread_signal_enter:
|
||||||
LOAD t0, FRAME_OFF_SP(sp)
|
mv s3, a2
|
||||||
addi t1, t0, -CTX_REG_NR * REGBYTES
|
|
||||||
LOAD t2, (t0)
|
|
||||||
li t3, -0x1000
|
|
||||||
1:
|
|
||||||
add t0, t0, t3
|
|
||||||
LOAD t2, (t0)
|
|
||||||
bgt t0, t1, 1b
|
|
||||||
|
|
||||||
/** restore and backup kernel sp carefully to avoid leaking */
|
|
||||||
addi t0, sp, CTX_REG_NR * REGBYTES
|
|
||||||
csrw sscratch, t0
|
|
||||||
|
|
||||||
RESTORE_ALL
|
|
||||||
SAVE_ALL
|
|
||||||
|
|
||||||
/**
|
|
||||||
* save lwp_sigreturn in user memory
|
|
||||||
*/
|
|
||||||
mv s0, sp
|
|
||||||
la t0, lwp_sigreturn
|
|
||||||
la t1, lwp_sigreturn_end
|
|
||||||
// t1 <- size
|
|
||||||
sub t1, t1, t0
|
|
||||||
// s0 <- dst
|
|
||||||
sub s0, s0, t1
|
|
||||||
mv s2, t1
|
|
||||||
lwp_sigreturn_copy_loop:
|
|
||||||
addi t2, t1, -1
|
|
||||||
add t3, t0, t2
|
|
||||||
add t4, s0, t2
|
|
||||||
lb t5, 0(t3)
|
|
||||||
sb t5, 0(t4)
|
|
||||||
mv t1, t2
|
|
||||||
bnez t1, lwp_sigreturn_copy_loop
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 1. clear sscratch & restore kernel sp to
|
|
||||||
* enter kernel mode routine
|
|
||||||
* 2. storage exp frame address to restore context,
|
|
||||||
* by calling to lwp_signal_backup
|
|
||||||
* 3. storage lwp_sigreturn entry address
|
|
||||||
* 4. get signal id as param for signal handler
|
|
||||||
*/
|
|
||||||
mv s1, sp
|
|
||||||
csrrw sp, sscratch, x0
|
|
||||||
|
|
||||||
/**
|
|
||||||
* synchronize dcache & icache if target is
|
|
||||||
* a Harvard Architecture machine, otherwise
|
|
||||||
* do nothing
|
|
||||||
*/
|
|
||||||
mv a0, s0
|
|
||||||
mv a1, s2
|
|
||||||
call rt_hw_sync_cache_local
|
|
||||||
|
|
||||||
/**
|
|
||||||
* backup user sp (point to saved exception frame, skip sigreturn routine)
|
|
||||||
* And get signal id
|
|
||||||
|
|
||||||
* a0: user sp
|
|
||||||
* a1: user_pc (not used, marked as 0 to avoid abuse)
|
|
||||||
* a2: user_flag (not used, marked as 0 to avoid abuse)
|
|
||||||
*/
|
|
||||||
mv a0, s1
|
|
||||||
mv a1, zero
|
|
||||||
mv a2, zero
|
|
||||||
call lwp_signal_backup
|
|
||||||
|
|
||||||
/**
|
|
||||||
* backup signal id in s2,
|
|
||||||
* and get sighandler by signal id
|
|
||||||
*/
|
|
||||||
mv s2, a0
|
mv s2, a0
|
||||||
call lwp_sighandler_get
|
mv s1, a3
|
||||||
|
|
||||||
|
LOAD t0, FRAME_OFF_SP(a2)
|
||||||
|
mv a3, t0
|
||||||
|
call arch_signal_ucontext_save
|
||||||
|
|
||||||
|
/** restore kernel sp */
|
||||||
|
addi sp, s3, CTX_REG_NR * REGBYTES
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set regiter RA to user signal handler
|
* set regiter RA to user signal handler
|
||||||
* set sp to user sp & save kernel sp in sscratch
|
* set sp to user sp & save kernel sp in sscratch
|
||||||
*/
|
*/
|
||||||
mv ra, s0
|
mv ra, a0
|
||||||
csrw sscratch, sp
|
csrw sscratch, sp
|
||||||
mv sp, s0
|
mv sp, a0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* a0 is signal_handler,
|
* s1 is signal_handler,
|
||||||
* s1 = s0 == NULL ? lwp_sigreturn : s0;
|
* s1 = !s1 ? lwp_sigreturn : s1;
|
||||||
*/
|
*/
|
||||||
mv s1, s0
|
bnez s1, 1f
|
||||||
beqz a0, skip_user_signal_handler
|
mv s1, ra
|
||||||
mv s1, a0
|
|
||||||
|
|
||||||
skip_user_signal_handler:
|
1:
|
||||||
// enter user mode and enable interrupt when return to user mode
|
/* enter user mode and enable interrupt when return to user mode */
|
||||||
li t0, SSTATUS_SPP
|
li t0, SSTATUS_SPP
|
||||||
csrc sstatus, t0
|
csrc sstatus, t0
|
||||||
li t0, SSTATUS_SPIE
|
li t0, SSTATUS_SPIE
|
||||||
csrs sstatus, t0
|
csrs sstatus, t0
|
||||||
|
|
||||||
// sepc <- signal_handler
|
/* sepc <- signal_handler */
|
||||||
csrw sepc, s1
|
csrw sepc, s1
|
||||||
// a0 <- signal id
|
/* a0 <- signal id */
|
||||||
mv a0, s2
|
mv a0, s2
|
||||||
|
/* a1 <- siginfo */
|
||||||
|
add a1, sp, 16
|
||||||
|
/* dummy a2 */
|
||||||
|
mv a2, a1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* handler(signo, psi, ucontext);
|
||||||
|
*/
|
||||||
sret
|
sret
|
||||||
|
|
||||||
.align 3
|
.align 3
|
||||||
|
@ -234,6 +185,7 @@ lwp_debugreturn:
|
||||||
ecall
|
ecall
|
||||||
|
|
||||||
.align 3
|
.align 3
|
||||||
|
.global lwp_sigreturn
|
||||||
lwp_sigreturn:
|
lwp_sigreturn:
|
||||||
li a7, 0xfe
|
li a7, 0xfe
|
||||||
ecall
|
ecall
|
||||||
|
|
|
@ -13,6 +13,10 @@
|
||||||
* 2023-02-20 wangxiaoyao fix bug on foreground app switch
|
* 2023-02-20 wangxiaoyao fix bug on foreground app switch
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define DBG_TAG "LWP"
|
||||||
|
#define DBG_LVL DBG_WARNING
|
||||||
|
#include <rtdbg.h>
|
||||||
|
|
||||||
#include <rthw.h>
|
#include <rthw.h>
|
||||||
#include <rtthread.h>
|
#include <rtthread.h>
|
||||||
|
|
||||||
|
@ -32,12 +36,10 @@
|
||||||
#include "lwp.h"
|
#include "lwp.h"
|
||||||
#include "lwp_arch.h"
|
#include "lwp_arch.h"
|
||||||
#include "lwp_arch_comm.h"
|
#include "lwp_arch_comm.h"
|
||||||
|
#include "lwp_signal.h"
|
||||||
|
#include "lwp_dbg.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
|
|
||||||
#define DBG_TAG "LWP"
|
|
||||||
#define DBG_LVL DBG_WARNING
|
|
||||||
#include <rtdbg.h>
|
|
||||||
|
|
||||||
#ifdef ARCH_MM_MMU
|
#ifdef ARCH_MM_MMU
|
||||||
#include <lwp_user_mm.h>
|
#include <lwp_user_mm.h>
|
||||||
#endif /* end of ARCH_MM_MMU */
|
#endif /* end of ARCH_MM_MMU */
|
||||||
|
@ -1025,37 +1027,32 @@ out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* lwp thread clean up */
|
||||||
void lwp_cleanup(struct rt_thread *tid)
|
void lwp_cleanup(struct rt_thread *tid)
|
||||||
{
|
{
|
||||||
rt_base_t level;
|
rt_base_t level;
|
||||||
struct rt_lwp *lwp;
|
struct rt_lwp *lwp;
|
||||||
struct tty_node *tty_head = RT_NULL;
|
|
||||||
|
|
||||||
if (tid == NULL)
|
if (tid == NULL)
|
||||||
{
|
{
|
||||||
|
LOG_I("%s: invalid parameter tid == NULL", __func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
LOG_I("cleanup thread: %s, stack_addr: %08X", tid->parent.name, tid->stack_addr);
|
LOG_D("cleanup thread: %s, stack_addr: 0x%x", tid->parent.name, tid->stack_addr);
|
||||||
|
|
||||||
level = rt_hw_interrupt_disable();
|
level = rt_hw_interrupt_disable();
|
||||||
lwp = (struct rt_lwp *)tid->lwp;
|
lwp = (struct rt_lwp *)tid->lwp;
|
||||||
|
|
||||||
|
/* lwp thread cleanup */
|
||||||
lwp_tid_put(tid->tid);
|
lwp_tid_put(tid->tid);
|
||||||
rt_list_remove(&tid->sibling);
|
rt_list_remove(&tid->sibling);
|
||||||
rt_hw_interrupt_enable(level);
|
lwp_thread_signal_detach(&tid->signal);
|
||||||
if (lwp->tty != RT_NULL)
|
|
||||||
{
|
|
||||||
tty_head = lwp->tty->head;
|
|
||||||
}
|
|
||||||
if (!lwp_ref_dec(lwp))
|
|
||||||
{
|
|
||||||
if (tty_head)
|
|
||||||
{
|
|
||||||
tty_pop(&tty_head, lwp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
rt_hw_interrupt_enable(level);
|
||||||
|
|
||||||
|
/* tty will be release in lwp_ref_dec() if ref is cleared */
|
||||||
|
lwp_ref_dec(lwp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,8 +88,10 @@ struct rt_lwp
|
||||||
struct rt_lwp *sibling;
|
struct rt_lwp *sibling;
|
||||||
|
|
||||||
rt_list_t wait_list;
|
rt_list_t wait_list;
|
||||||
int32_t finish;
|
rt_bool_t finish;
|
||||||
int lwp_ret;
|
rt_bool_t terminated;
|
||||||
|
rt_bool_t background;
|
||||||
|
int lwp_ret;
|
||||||
|
|
||||||
void *text_entry;
|
void *text_entry;
|
||||||
uint32_t text_size;
|
uint32_t text_size;
|
||||||
|
@ -109,12 +111,8 @@ struct rt_lwp
|
||||||
struct dfs_fdtable fdt;
|
struct dfs_fdtable fdt;
|
||||||
char cmd[RT_NAME_MAX];
|
char cmd[RT_NAME_MAX];
|
||||||
|
|
||||||
int sa_flags;
|
/* POSIX signal */
|
||||||
lwp_sigset_t signal;
|
struct lwp_signal signal;
|
||||||
lwp_sigset_t signal_mask;
|
|
||||||
int signal_mask_bak;
|
|
||||||
rt_uint32_t signal_in_process;
|
|
||||||
lwp_sighandler_t signal_handler[_LWP_NSIG];
|
|
||||||
|
|
||||||
struct lwp_avl_struct *object_root;
|
struct lwp_avl_struct *object_root;
|
||||||
struct rt_mutex object_mutex;
|
struct rt_mutex object_mutex;
|
||||||
|
@ -123,10 +121,9 @@ struct rt_lwp
|
||||||
struct rt_wqueue wait_queue; /*for console */
|
struct rt_wqueue wait_queue; /*for console */
|
||||||
struct tty_struct *tty; /* NULL if no tty */
|
struct tty_struct *tty; /* NULL if no tty */
|
||||||
|
|
||||||
struct lwp_avl_struct *address_search_head; /* for addressed object fast rearch */
|
struct lwp_avl_struct *address_search_head; /* for addressed object fast search */
|
||||||
char working_directory[DFS_PATH_MAX];
|
char working_directory[DFS_PATH_MAX];
|
||||||
int debug;
|
int debug;
|
||||||
int background;
|
|
||||||
uint32_t bak_first_ins;
|
uint32_t bak_first_ins;
|
||||||
|
|
||||||
#ifdef LWP_ENABLE_ASID
|
#ifdef LWP_ENABLE_ASID
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*
|
*
|
||||||
* Change Logs:
|
* Change Logs:
|
||||||
* Date Author Notes
|
* Date Author Notes
|
||||||
|
* 2022-09-30 RT-Thread the general porting API for lwp
|
||||||
|
* 2023-07-18 Shell New signal arch API arch_thread_signal_enter
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __LWP_ARCH_COMM__
|
#ifndef __LWP_ARCH_COMM__
|
||||||
|
@ -54,4 +56,9 @@ void arch_set_thread_area(void *p);
|
||||||
void* arch_get_tidr(void);
|
void* arch_get_tidr(void);
|
||||||
void arch_set_tidr(void *p);
|
void arch_set_tidr(void *p);
|
||||||
|
|
||||||
|
/** entry point of architecture signal handling */
|
||||||
|
rt_noreturn void arch_thread_signal_enter(int signo, siginfo_t *psiginfo,
|
||||||
|
void *exp_frame, void *entry_uaddr,
|
||||||
|
lwp_sigset_t *save_sig_mask);
|
||||||
|
|
||||||
#endif /* __LWP_ARCH_COMM__ */
|
#endif /* __LWP_ARCH_COMM__ */
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2023-07-06 RT-Thread the first version
|
||||||
|
*/
|
||||||
|
#ifndef __LWP_CLONE_H__
|
||||||
|
#define __LWP_CLONE_H__
|
||||||
|
|
||||||
|
#define CLONE_VM 0x00000100
|
||||||
|
#define CLONE_FS 0x00000200
|
||||||
|
#define CLONE_FILES 0x00000400
|
||||||
|
#define CLONE_SIGHAND 0x00000800
|
||||||
|
#define CLONE_PTRACE 0x00002000
|
||||||
|
#define CLONE_VFORK 0x00004000
|
||||||
|
#define CLONE_PARENT 0x00008000
|
||||||
|
#define CLONE_THREAD 0x00010000
|
||||||
|
#define CLONE_NEWNS 0x00020000
|
||||||
|
#define CLONE_SYSVSEM 0x00040000
|
||||||
|
#define CLONE_SETTLS 0x00080000
|
||||||
|
#define CLONE_PARENT_SETTID 0x00100000
|
||||||
|
#define CLONE_CHILD_CLEARTID 0x00200000
|
||||||
|
#define CLONE_DETACHED 0x00400000
|
||||||
|
#define CLONE_UNTRACED 0x00800000
|
||||||
|
#define CLONE_CHILD_SETTID 0x01000000
|
||||||
|
#define CLONE_NEWCGROUP 0x02000000
|
||||||
|
#define CLONE_NEWUTS 0x04000000
|
||||||
|
#define CLONE_NEWIPC 0x08000000
|
||||||
|
#define CLONE_NEWUSER 0x10000000
|
||||||
|
#define CLONE_NEWPID 0x20000000
|
||||||
|
#define CLONE_NEWNET 0x40000000
|
||||||
|
#define CLONE_IO 0x80000000
|
||||||
|
|
||||||
|
/* arg[] -> flags
|
||||||
|
* stack
|
||||||
|
* new_tid
|
||||||
|
* tls
|
||||||
|
* set_clear_tid_address
|
||||||
|
* quit_func
|
||||||
|
* start_args
|
||||||
|
* */
|
||||||
|
#define SYS_CLONE_ARGS_NR 7
|
||||||
|
|
||||||
|
#endif /* __LWP_CLONE_H__ */
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2023-07-11 RT-Thread first version
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LWP_DBG_H__
|
||||||
|
#define __LWP_DBG_H__
|
||||||
|
|
||||||
|
#include <rtthread.h>
|
||||||
|
#include <rthw.h>
|
||||||
|
#include <lwp.h>
|
||||||
|
|
||||||
|
int dbg_thread_in_debug(void);
|
||||||
|
void dbg_register(struct dbg_ops_t *dbg_ops);
|
||||||
|
uint32_t dbg_get_ins(void);
|
||||||
|
void dbg_activate_step(void);
|
||||||
|
void dbg_deactivate_step(void);
|
||||||
|
int dbg_check_event(struct rt_hw_exp_stack *regs, unsigned long esr);
|
||||||
|
rt_channel_t gdb_server_channel(void);
|
||||||
|
int dbg_step_type(void);
|
||||||
|
void dbg_attach_req(void *pc);
|
||||||
|
int dbg_check_suspend(void);
|
||||||
|
|
||||||
|
#endif /* __LWP_DBG_H__ */
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include "lwp.h"
|
#include "lwp.h"
|
||||||
#include "lwp_pid.h"
|
#include "lwp_pid.h"
|
||||||
|
#include "lwp_signal.h"
|
||||||
#include "tty.h"
|
#include "tty.h"
|
||||||
|
|
||||||
#ifdef ARCH_MM_MMU
|
#ifdef ARCH_MM_MMU
|
||||||
|
@ -319,7 +320,7 @@ struct rt_lwp* lwp_new(void)
|
||||||
{
|
{
|
||||||
return lwp;
|
return lwp;
|
||||||
}
|
}
|
||||||
rt_memset(lwp, 0, sizeof(*lwp));
|
memset(lwp, 0, sizeof(*lwp));
|
||||||
//lwp->tgroup_leader = RT_NULL;
|
//lwp->tgroup_leader = RT_NULL;
|
||||||
rt_list_init(&lwp->wait_list);
|
rt_list_init(&lwp->wait_list);
|
||||||
lwp->leader = 0;
|
lwp->leader = 0;
|
||||||
|
@ -331,6 +332,8 @@ struct rt_lwp* lwp_new(void)
|
||||||
rt_wqueue_init(&lwp->wait_queue);
|
rt_wqueue_init(&lwp->wait_queue);
|
||||||
lwp->ref = 1;
|
lwp->ref = 1;
|
||||||
|
|
||||||
|
lwp_signal_init(&lwp->signal);
|
||||||
|
|
||||||
level = rt_hw_interrupt_disable();
|
level = rt_hw_interrupt_disable();
|
||||||
pid = lwp_pid_get();
|
pid = lwp_pid_get();
|
||||||
if (pid == 0)
|
if (pid == 0)
|
||||||
|
@ -475,34 +478,33 @@ void lwp_free(struct rt_lwp* lwp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* for parent */
|
/* for parent */
|
||||||
|
if (lwp->parent)
|
||||||
{
|
{
|
||||||
if (lwp->parent)
|
struct rt_thread *thread;
|
||||||
|
if (!rt_list_isempty(&lwp->wait_list))
|
||||||
{
|
{
|
||||||
struct rt_thread *thread;
|
thread = rt_list_entry(lwp->wait_list.next, struct rt_thread, tlist);
|
||||||
if (!rt_list_isempty(&lwp->wait_list))
|
thread->error = RT_EOK;
|
||||||
{
|
thread->msg_ret = (void*)(rt_size_t)lwp->lwp_ret;
|
||||||
thread = rt_list_entry(lwp->wait_list.next, struct rt_thread, tlist);
|
rt_thread_resume(thread);
|
||||||
thread->error = RT_EOK;
|
rt_hw_interrupt_enable(level);
|
||||||
thread->msg_ret = (void*)(rt_size_t)lwp->lwp_ret;
|
return;
|
||||||
rt_thread_resume(thread);
|
}
|
||||||
rt_hw_interrupt_enable(level);
|
else
|
||||||
return;
|
{
|
||||||
}
|
struct rt_lwp **it = &lwp->parent->first_child;
|
||||||
else
|
|
||||||
{
|
while (*it != lwp)
|
||||||
struct rt_lwp **it = &lwp->parent->first_child;
|
{
|
||||||
|
it = &(*it)->sibling;
|
||||||
while (*it != lwp)
|
}
|
||||||
{
|
*it = lwp->sibling;
|
||||||
it = &(*it)->sibling;
|
|
||||||
}
|
|
||||||
*it = lwp->sibling;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
lwp_pid_put(lwp_to_pid(lwp));
|
|
||||||
rt_hw_interrupt_enable(level);
|
|
||||||
rt_free(lwp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lwp_pid_put(lwp_to_pid(lwp));
|
||||||
|
rt_hw_interrupt_enable(level);
|
||||||
|
rt_free(lwp);
|
||||||
}
|
}
|
||||||
|
|
||||||
int lwp_ref_inc(struct rt_lwp *lwp)
|
int lwp_ref_inc(struct rt_lwp *lwp)
|
||||||
|
@ -537,6 +539,7 @@ int lwp_ref_dec(struct rt_lwp *lwp)
|
||||||
memset(&msg, 0, sizeof msg);
|
memset(&msg, 0, sizeof msg);
|
||||||
rt_raw_channel_send(gdb_server_channel(), &msg);
|
rt_raw_channel_send(gdb_server_channel(), &msg);
|
||||||
}
|
}
|
||||||
|
lwp_signal_detach(&lwp->signal);
|
||||||
|
|
||||||
#ifndef ARCH_MM_MMU
|
#ifndef ARCH_MM_MMU
|
||||||
#ifdef RT_LWP_USING_SHM
|
#ifdef RT_LWP_USING_SHM
|
||||||
|
@ -846,7 +849,7 @@ static void cmd_kill(int argc, char** argv)
|
||||||
sig = atoi(argv[3]);
|
sig = atoi(argv[3]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lwp_kill(pid, sig);
|
lwp_signal_kill(lwp_from_pid(pid), sig, SI_USER, 0);
|
||||||
}
|
}
|
||||||
MSH_CMD_EXPORT_ALIAS(cmd_kill, kill, send a signal to a process);
|
MSH_CMD_EXPORT_ALIAS(cmd_kill, kill, send a signal to a process);
|
||||||
|
|
||||||
|
@ -861,7 +864,7 @@ static void cmd_killall(int argc, char** argv)
|
||||||
|
|
||||||
while((pid = lwp_name2pid(argv[1])) > 0)
|
while((pid = lwp_name2pid(argv[1])) > 0)
|
||||||
{
|
{
|
||||||
lwp_kill(pid, SIGKILL);
|
lwp_signal_kill(lwp_from_pid(pid), SIGKILL, SI_USER, 0);
|
||||||
rt_thread_mdelay(100);
|
rt_thread_mdelay(100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -979,6 +982,11 @@ void lwp_terminate(struct rt_lwp *lwp)
|
||||||
}
|
}
|
||||||
|
|
||||||
level = rt_hw_interrupt_disable();
|
level = rt_hw_interrupt_disable();
|
||||||
|
|
||||||
|
/* stop the receiving of signals */
|
||||||
|
lwp->terminated = RT_TRUE;
|
||||||
|
|
||||||
|
/* broadcast exit request for sibling threads */
|
||||||
for (list = lwp->t_grp.next; list != &lwp->t_grp; list = list->next)
|
for (list = lwp->t_grp.next; list != &lwp->t_grp; list = list->next)
|
||||||
{
|
{
|
||||||
rt_thread_t thread;
|
rt_thread_t thread;
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
#ifndef LWP_PID_H__
|
#ifndef LWP_PID_H__
|
||||||
#define LWP_PID_H__
|
#define LWP_PID_H__
|
||||||
|
|
||||||
|
#include "lwp.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,39 +1,176 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2020, RT-Thread Development Team
|
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*
|
*
|
||||||
* Change Logs:
|
* Change Logs:
|
||||||
* Date Author Notes
|
* Date Author Notes
|
||||||
* 2020-02-23 Jesven first version.
|
* 2020-02-23 Jesven first version.
|
||||||
|
* 2023-07-06 Shell update the generation, pending and delivery API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LWP_SIGNAL_H__
|
#ifndef __LWP_SIGNAL_H__
|
||||||
#define LWP_SIGNAL_H__
|
#define __LWP_SIGNAL_H__
|
||||||
|
|
||||||
|
#include "syscall_generic.h"
|
||||||
|
|
||||||
#include <rtthread.h>
|
#include <rtthread.h>
|
||||||
|
#include <sys/signal.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int lwp_signal_check(void);
|
#define _USIGNAL_SIGMASK(signo) (1u << ((signo)-1))
|
||||||
int lwp_signal_backup(void *user_sp, void *user_pc, void* user_flag);
|
#define LWP_SIG_IGNORE_SET (_USIGNAL_SIGMASK(SIGCHLD) | _USIGNAL_SIGMASK(SIGURG))
|
||||||
struct rt_user_context *lwp_signal_restore(void);
|
#define LWP_SIG_ACT_DFL ((lwp_sighandler_t)0)
|
||||||
lwp_sighandler_t lwp_sighandler_get(int sig);
|
#define LWP_SIG_ACT_IGN ((lwp_sighandler_t)1)
|
||||||
void lwp_sighandler_set(int sig, lwp_sighandler_t func);
|
#define LWP_SIG_USER_SA_FLAGS \
|
||||||
|
(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART | \
|
||||||
|
SA_NODEFER | SA_RESETHAND | SA_EXPOSE_TAGBITS)
|
||||||
|
|
||||||
|
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 {
|
||||||
|
struct rt_mutex sig_lock;
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rt_lwp;
|
||||||
|
|
||||||
#ifndef ARCH_MM_MMU
|
#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);
|
void lwp_thread_sighandler_set(int sig, lwp_sighandler_t func);
|
||||||
#endif
|
#endif
|
||||||
int lwp_sigprocmask(int how, const lwp_sigset_t *sigset, lwp_sigset_t *oset);
|
|
||||||
int lwp_sigaction(int sig, const struct lwp_sigaction *act, struct lwp_sigaction * oact, size_t sigsetsize);
|
|
||||||
int lwp_thread_sigprocmask(int how, const lwp_sigset_t *sigset, lwp_sigset_t *oset);
|
|
||||||
|
|
||||||
int lwp_kill(pid_t pid, int sig);
|
rt_inline void lwp_sigqueue_init(lwp_sigqueue_t sigq)
|
||||||
int lwp_thread_kill(rt_thread_t thread, int sig);
|
{
|
||||||
|
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, long 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, long 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);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif /* __LWP_SIGNAL_H__ */
|
||||||
|
|
|
@ -11,8 +11,11 @@
|
||||||
* 2021-02-12 lizhirui add 64-bit support for sys_brk
|
* 2021-02-12 lizhirui add 64-bit support for sys_brk
|
||||||
* 2021-02-20 lizhirui fix some warnings
|
* 2021-02-20 lizhirui fix some warnings
|
||||||
* 2023-03-13 WangXiaoyao Format & fix syscall return value
|
* 2023-03-13 WangXiaoyao Format & fix syscall return value
|
||||||
|
* 2023-07-06 Shell adapt the signal API, and clone, fork to new implementation of lwp signal
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
/* RT-Thread System call */
|
/* RT-Thread System call */
|
||||||
#include <rtthread.h>
|
#include <rtthread.h>
|
||||||
#include <rthw.h>
|
#include <rthw.h>
|
||||||
|
@ -28,6 +31,7 @@
|
||||||
#include "syscall_generic.h"
|
#include "syscall_generic.h"
|
||||||
|
|
||||||
#include <lwp.h>
|
#include <lwp.h>
|
||||||
|
#include "lwp_signal.h"
|
||||||
#ifdef ARCH_MM_MMU
|
#ifdef ARCH_MM_MMU
|
||||||
#include <lwp_user_mm.h>
|
#include <lwp_user_mm.h>
|
||||||
#include <lwp_arch.h>
|
#include <lwp_arch.h>
|
||||||
|
@ -1007,11 +1011,80 @@ sysret_t sys_exec(char *filename, int argc, char **argv, char **envp)
|
||||||
return lwp_execve(filename, 0, argc, argv, envp);
|
return lwp_execve(filename, 0, argc, argv, envp);
|
||||||
}
|
}
|
||||||
|
|
||||||
sysret_t sys_kill(int pid, int sig)
|
sysret_t sys_kill(int pid, int signo)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
rt_err_t kret;
|
||||||
ret = lwp_kill(pid, sig);
|
sysret_t sysret;
|
||||||
return (ret < 0 ? GET_ERRNO() : ret);
|
rt_base_t level;
|
||||||
|
struct rt_lwp *lwp;
|
||||||
|
|
||||||
|
/* handling the semantics of sys_kill */
|
||||||
|
if (pid > 0)
|
||||||
|
{
|
||||||
|
/* TODO: lock the lwp strcut */
|
||||||
|
level = rt_hw_interrupt_disable();
|
||||||
|
lwp = lwp_from_pid(pid);
|
||||||
|
|
||||||
|
/* lwp_signal_kill() can handle NULL lwp */
|
||||||
|
if (lwp)
|
||||||
|
kret = lwp_signal_kill(lwp, signo, SI_USER, 0);
|
||||||
|
else
|
||||||
|
kret = -RT_ENOENT;
|
||||||
|
|
||||||
|
rt_hw_interrupt_enable(level);
|
||||||
|
}
|
||||||
|
else if (pid == 0)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* sig shall be sent to all processes (excluding an unspecified set
|
||||||
|
* of system processes) whose process group ID is equal to the process
|
||||||
|
* group ID of the sender, and for which the process has permission to
|
||||||
|
* send a signal.
|
||||||
|
*/
|
||||||
|
kret = -RT_ENOSYS;
|
||||||
|
}
|
||||||
|
else if (pid == -1)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* sig shall be sent to all processes (excluding an unspecified set
|
||||||
|
* of system processes) for which the process has permission to send
|
||||||
|
* that signal.
|
||||||
|
*/
|
||||||
|
kret = -RT_ENOSYS;
|
||||||
|
}
|
||||||
|
else /* pid < -1 */
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* sig shall be sent to all processes (excluding an unspecified set
|
||||||
|
* of system processes) whose process group ID is equal to the absolute
|
||||||
|
* value of pid, and for which the process has permission to send a signal.
|
||||||
|
*/
|
||||||
|
kret = -RT_ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (kret)
|
||||||
|
{
|
||||||
|
case -RT_ENOENT:
|
||||||
|
sysret = -ESRCH;
|
||||||
|
break;
|
||||||
|
case -RT_EINVAL:
|
||||||
|
sysret = -EINVAL;
|
||||||
|
break;
|
||||||
|
case -RT_ENOSYS:
|
||||||
|
sysret = -ENOSYS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kill() never returns ENOMEM, so return normally to caller.
|
||||||
|
* IEEE Std 1003.1-2017 says the kill() function is successful
|
||||||
|
* if the process has permission to send sig to any of the
|
||||||
|
* processes specified by pid.
|
||||||
|
*/
|
||||||
|
case -RT_ENOMEM:
|
||||||
|
default:
|
||||||
|
sysret = 0;
|
||||||
|
}
|
||||||
|
return sysret;
|
||||||
}
|
}
|
||||||
|
|
||||||
sysret_t sys_getpid(void)
|
sysret_t sys_getpid(void)
|
||||||
|
@ -1500,40 +1573,9 @@ fail:
|
||||||
}
|
}
|
||||||
return RT_NULL;
|
return RT_NULL;
|
||||||
}
|
}
|
||||||
#ifdef ARCH_MM_MMU
|
|
||||||
#define CLONE_VM 0x00000100
|
|
||||||
#define CLONE_FS 0x00000200
|
|
||||||
#define CLONE_FILES 0x00000400
|
|
||||||
#define CLONE_SIGHAND 0x00000800
|
|
||||||
#define CLONE_PTRACE 0x00002000
|
|
||||||
#define CLONE_VFORK 0x00004000
|
|
||||||
#define CLONE_PARENT 0x00008000
|
|
||||||
#define CLONE_THREAD 0x00010000
|
|
||||||
#define CLONE_NEWNS 0x00020000
|
|
||||||
#define CLONE_SYSVSEM 0x00040000
|
|
||||||
#define CLONE_SETTLS 0x00080000
|
|
||||||
#define CLONE_PARENT_SETTID 0x00100000
|
|
||||||
#define CLONE_CHILD_CLEARTID 0x00200000
|
|
||||||
#define CLONE_DETACHED 0x00400000
|
|
||||||
#define CLONE_UNTRACED 0x00800000
|
|
||||||
#define CLONE_CHILD_SETTID 0x01000000
|
|
||||||
#define CLONE_NEWCGROUP 0x02000000
|
|
||||||
#define CLONE_NEWUTS 0x04000000
|
|
||||||
#define CLONE_NEWIPC 0x08000000
|
|
||||||
#define CLONE_NEWUSER 0x10000000
|
|
||||||
#define CLONE_NEWPID 0x20000000
|
|
||||||
#define CLONE_NEWNET 0x40000000
|
|
||||||
#define CLONE_IO 0x80000000
|
|
||||||
|
|
||||||
/* arg[] -> flags
|
#ifdef ARCH_MM_MMU
|
||||||
* stack
|
#include "lwp_clone.h"
|
||||||
* new_tid
|
|
||||||
* tls
|
|
||||||
* set_clear_tid_address
|
|
||||||
* quit_func
|
|
||||||
* start_args
|
|
||||||
* */
|
|
||||||
#define SYS_CLONE_ARGS_NR 7
|
|
||||||
|
|
||||||
long _sys_clone(void *arg[])
|
long _sys_clone(void *arg[])
|
||||||
{
|
{
|
||||||
|
@ -1687,9 +1729,12 @@ static void lwp_struct_copy(struct rt_lwp *dst, struct rt_lwp *src)
|
||||||
dst->tty = src->tty;
|
dst->tty = src->tty;
|
||||||
rt_memcpy(dst->cmd, src->cmd, RT_NAME_MAX);
|
rt_memcpy(dst->cmd, src->cmd, RT_NAME_MAX);
|
||||||
|
|
||||||
dst->sa_flags = src->sa_flags;
|
rt_memcpy(&dst->signal.sig_action, &src->signal.sig_action, sizeof(dst->signal.sig_action));
|
||||||
dst->signal_mask = src->signal_mask;
|
rt_memcpy(&dst->signal.sig_action_mask, &src->signal.sig_action_mask, sizeof(dst->signal.sig_action_mask));
|
||||||
rt_memcpy(dst->signal_handler, src->signal_handler, sizeof dst->signal_handler);
|
rt_memcpy(&dst->signal.sig_action_nodefer, &src->signal.sig_action_nodefer, sizeof(dst->signal.sig_action_nodefer));
|
||||||
|
rt_memcpy(&dst->signal.sig_action_onstack, &src->signal.sig_action_onstack, sizeof(dst->signal.sig_action_onstack));
|
||||||
|
rt_memcpy(&dst->signal.sig_action_restart, &dst->signal.sig_action_restart, sizeof(dst->signal.sig_action_restart));
|
||||||
|
rt_memcpy(&dst->signal.sig_action_siginfo, &dst->signal.sig_action_siginfo, sizeof(dst->signal.sig_action_siginfo));
|
||||||
rt_strcpy(dst->working_directory, src->working_directory);
|
rt_strcpy(dst->working_directory, src->working_directory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1797,7 +1842,7 @@ sysret_t _sys_fork(void)
|
||||||
thread->user_entry = self_thread->user_entry;
|
thread->user_entry = self_thread->user_entry;
|
||||||
thread->user_stack = self_thread->user_stack;
|
thread->user_stack = self_thread->user_stack;
|
||||||
thread->user_stack_size = self_thread->user_stack_size;
|
thread->user_stack_size = self_thread->user_stack_size;
|
||||||
thread->signal_mask = self_thread->signal_mask;
|
thread->signal.sigset_mask = self_thread->signal.sigset_mask;
|
||||||
thread->thread_idr = self_thread->thread_idr;
|
thread->thread_idr = self_thread->thread_idr;
|
||||||
thread->lwp = (void *)lwp;
|
thread->lwp = (void *)lwp;
|
||||||
thread->tid = tid;
|
thread->tid = tid;
|
||||||
|
@ -2457,12 +2502,11 @@ sysret_t sys_execve(const char *path, char *const argv[], char *const envp[])
|
||||||
|
|
||||||
_swap_lwp_data(lwp, new_lwp, void *, args);
|
_swap_lwp_data(lwp, new_lwp, void *, args);
|
||||||
|
|
||||||
rt_memset(&thread->signal_mask, 0, sizeof(thread->signal_mask));
|
lwp_thread_signal_detach(&thread->signal);
|
||||||
rt_memset(&thread->signal_mask_bak, 0, sizeof(thread->signal_mask_bak));
|
rt_memset(&thread->signal.sigset_mask, 0, sizeof(thread->signal.sigset_mask));
|
||||||
lwp->sa_flags = 0;
|
|
||||||
rt_memset(&lwp->signal_mask, 0, sizeof(lwp->signal_mask));
|
lwp_signal_detach(&lwp->signal);
|
||||||
rt_memset(&lwp->signal_mask_bak, 0, sizeof(lwp->signal_mask_bak));
|
lwp_signal_init(&lwp->signal);
|
||||||
rt_memset(lwp->signal_handler, 0, sizeof(lwp->signal_handler));
|
|
||||||
|
|
||||||
/* to do: clsoe files with flag CLOEXEC */
|
/* to do: clsoe files with flag CLOEXEC */
|
||||||
|
|
||||||
|
@ -2470,6 +2514,9 @@ sysret_t sys_execve(const char *path, char *const argv[], char *const envp[])
|
||||||
|
|
||||||
rt_hw_interrupt_enable(level);
|
rt_hw_interrupt_enable(level);
|
||||||
|
|
||||||
|
/* setup the signal for the dummy lwp, so that is can be smoothly recycled */
|
||||||
|
lwp_signal_init(&new_lwp->signal);
|
||||||
|
|
||||||
lwp_ref_dec(new_lwp);
|
lwp_ref_dec(new_lwp);
|
||||||
arch_start_umode(lwp->args,
|
arch_start_umode(lwp->args,
|
||||||
lwp->text_entry,
|
lwp->text_entry,
|
||||||
|
@ -3267,9 +3314,10 @@ struct k_sigaction {
|
||||||
};
|
};
|
||||||
|
|
||||||
sysret_t sys_sigaction(int sig, const struct k_sigaction *act,
|
sysret_t sys_sigaction(int sig, const struct k_sigaction *act,
|
||||||
struct k_sigaction *oact, size_t sigsetsize)
|
struct k_sigaction *oact, size_t sigsetsize)
|
||||||
{
|
{
|
||||||
int ret = -RT_EINVAL;
|
int ret = -RT_EINVAL;
|
||||||
|
struct rt_lwp *lwp;
|
||||||
struct lwp_sigaction kact, *pkact = RT_NULL;
|
struct lwp_sigaction kact, *pkact = RT_NULL;
|
||||||
struct lwp_sigaction koact, *pkoact = RT_NULL;
|
struct lwp_sigaction koact, *pkoact = RT_NULL;
|
||||||
|
|
||||||
|
@ -3310,7 +3358,9 @@ sysret_t sys_sigaction(int sig, const struct k_sigaction *act,
|
||||||
pkact = &kact;
|
pkact = &kact;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = lwp_sigaction(sig, pkact, pkoact, sigsetsize);
|
lwp = lwp_self();
|
||||||
|
RT_ASSERT(lwp);
|
||||||
|
ret = lwp_signal_action(lwp, sig, pkact, pkoact);
|
||||||
#ifdef ARCH_MM_MMU
|
#ifdef ARCH_MM_MMU
|
||||||
if (ret == 0 && oact)
|
if (ret == 0 && oact)
|
||||||
{
|
{
|
||||||
|
@ -3324,6 +3374,12 @@ out:
|
||||||
return (ret < 0 ? GET_ERRNO() : ret);
|
return (ret < 0 ? GET_ERRNO() : ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mask_command_u2k[] = {
|
||||||
|
[SIG_BLOCK] = LWP_SIG_MASK_CMD_BLOCK,
|
||||||
|
[SIG_UNBLOCK] = LWP_SIG_MASK_CMD_UNBLOCK,
|
||||||
|
[SIG_SETMASK] = LWP_SIG_MASK_CMD_SET_MASK,
|
||||||
|
};
|
||||||
|
|
||||||
sysret_t sys_sigprocmask(int how, const sigset_t *sigset, sigset_t *oset, size_t size)
|
sysret_t sys_sigprocmask(int how, const sigset_t *sigset, sigset_t *oset, size_t size)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
@ -3377,7 +3433,7 @@ sysret_t sys_sigprocmask(int how, const sigset_t *sigset, sigset_t *oset, size_t
|
||||||
pnewset = (lwp_sigset_t *)sigset;
|
pnewset = (lwp_sigset_t *)sigset;
|
||||||
#endif /* ARCH_MM_MMU */
|
#endif /* ARCH_MM_MMU */
|
||||||
}
|
}
|
||||||
ret = lwp_sigprocmask(how, pnewset, poldset);
|
ret = lwp_thread_signal_mask(rt_thread_self(), mask_command_u2k[how], pnewset, poldset);
|
||||||
#ifdef ARCH_MM_MMU
|
#ifdef ARCH_MM_MMU
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
|
@ -3391,6 +3447,97 @@ sysret_t sys_sigprocmask(int how, const sigset_t *sigset, sigset_t *oset, size_t
|
||||||
return (ret < 0 ? -EFAULT: ret);
|
return (ret < 0 ? -EFAULT: ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sysret_t sys_sigpending(sigset_t *sigset, size_t sigsize)
|
||||||
|
{
|
||||||
|
sysret_t ret = 0;
|
||||||
|
lwp_sigset_t lwpset;
|
||||||
|
|
||||||
|
/* Verify and Get sigset, timeout */
|
||||||
|
if (!sigset || !lwp_user_accessable((void *)sigset, sigsize))
|
||||||
|
{
|
||||||
|
ret = -EFAULT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Fit sigset size to lwp set */
|
||||||
|
if (sizeof(lwpset) < sigsize)
|
||||||
|
{
|
||||||
|
LOG_I("%s: sigsize (%lx) extends lwp sigset chunk\n", __func__, sigsize);
|
||||||
|
sigsize = sizeof(lwpset);
|
||||||
|
}
|
||||||
|
|
||||||
|
lwp_thread_signal_pending(rt_thread_self(), &lwpset);
|
||||||
|
|
||||||
|
if (!lwp_put_to_user(sigset, &lwpset, sigsize))
|
||||||
|
RT_ASSERT(0); /* should never happened */
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
sysret_t sys_sigtimedwait(const sigset_t *sigset, siginfo_t *info, const struct timespec *timeout, size_t sigsize)
|
||||||
|
{
|
||||||
|
int sig;
|
||||||
|
size_t ret;
|
||||||
|
lwp_sigset_t lwpset;
|
||||||
|
siginfo_t kinfo;
|
||||||
|
struct timespec ktimeout;
|
||||||
|
struct timespec *ptimeout;
|
||||||
|
|
||||||
|
/* Fit sigset size to lwp set */
|
||||||
|
if (sizeof(lwpset) < sigsize)
|
||||||
|
{
|
||||||
|
LOG_I("%s: sigsize (%lx) extends lwp sigset chunk\n", __func__, sigsize);
|
||||||
|
sigsize = sizeof(lwpset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(&lwpset, 0, sizeof(lwpset));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify and Get sigset, timeout */
|
||||||
|
if (!sigset || !lwp_user_accessable((void *)sigset, sigsize))
|
||||||
|
{
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = lwp_get_from_user(&lwpset, (void *)sigset, sigsize);
|
||||||
|
RT_ASSERT(ret == sigsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeout)
|
||||||
|
{
|
||||||
|
if (!lwp_user_accessable((void *)timeout, sizeof(*timeout)))
|
||||||
|
return -EFAULT;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = lwp_get_from_user(&ktimeout, (void *)timeout, sizeof(*timeout));
|
||||||
|
ptimeout = &ktimeout;
|
||||||
|
RT_ASSERT(ret == sizeof(*timeout));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ptimeout = RT_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sig = lwp_thread_signal_timedwait(rt_thread_self(), &lwpset, &kinfo, ptimeout);
|
||||||
|
|
||||||
|
if (info)
|
||||||
|
{
|
||||||
|
if (!lwp_user_accessable((void *)info, sizeof(*info)))
|
||||||
|
return -EFAULT;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = lwp_put_to_user(info, &kinfo, sizeof(*info));
|
||||||
|
RT_ASSERT(ret == sizeof(*info));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sig;
|
||||||
|
}
|
||||||
|
|
||||||
sysret_t sys_tkill(int tid, int sig)
|
sysret_t sys_tkill(int tid, int sig)
|
||||||
{
|
{
|
||||||
#ifdef ARCH_MM_MMU
|
#ifdef ARCH_MM_MMU
|
||||||
|
@ -3400,7 +3547,7 @@ sysret_t sys_tkill(int tid, int sig)
|
||||||
|
|
||||||
level = rt_hw_interrupt_disable();
|
level = rt_hw_interrupt_disable();
|
||||||
thread = lwp_tid_get_thread(tid);
|
thread = lwp_tid_get_thread(tid);
|
||||||
ret = lwp_thread_kill(thread, sig);
|
ret = lwp_thread_signal_kill(thread, sig, SI_USER, 0);
|
||||||
rt_hw_interrupt_enable(level);
|
rt_hw_interrupt_enable(level);
|
||||||
return ret;
|
return ret;
|
||||||
#else
|
#else
|
||||||
|
@ -3461,7 +3608,7 @@ sysret_t sys_thread_sigprocmask(int how, const lwp_sigset_t *sigset, lwp_sigset_
|
||||||
pnewset = (lwp_sigset_t *)sigset;
|
pnewset = (lwp_sigset_t *)sigset;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
ret = lwp_thread_sigprocmask(how, pnewset, poldset);
|
ret = lwp_thread_signal_mask(rt_thread_self(), mask_command_u2k[how], pnewset, poldset);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -5169,7 +5316,7 @@ sysret_t sys_symlink(const char *existing, const char *new)
|
||||||
return (ret < 0 ? GET_ERRNO() : ret);
|
return (ret < 0 ? GET_ERRNO() : ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
const static struct rt_syscall_def func_table[] =
|
static const struct rt_syscall_def func_table[] =
|
||||||
{
|
{
|
||||||
SYSCALL_SIGN(sys_exit), /* 01 */
|
SYSCALL_SIGN(sys_exit), /* 01 */
|
||||||
SYSCALL_SIGN(sys_read),
|
SYSCALL_SIGN(sys_read),
|
||||||
|
@ -5391,6 +5538,15 @@ const static struct rt_syscall_def func_table[] =
|
||||||
SYSCALL_SIGN(sys_symlink),
|
SYSCALL_SIGN(sys_symlink),
|
||||||
SYSCALL_SIGN(sys_getaffinity), /* 180 */
|
SYSCALL_SIGN(sys_getaffinity), /* 180 */
|
||||||
SYSCALL_SIGN(sys_sysinfo),
|
SYSCALL_SIGN(sys_sysinfo),
|
||||||
|
SYSCALL_SIGN(sys_notimpl),
|
||||||
|
SYSCALL_SIGN(sys_notimpl),
|
||||||
|
SYSCALL_SIGN(sys_notimpl),
|
||||||
|
SYSCALL_SIGN(sys_notimpl), /* 185 */
|
||||||
|
SYSCALL_SIGN(sys_notimpl),
|
||||||
|
SYSCALL_SIGN(sys_sigpending),
|
||||||
|
SYSCALL_SIGN(sys_sigtimedwait),
|
||||||
|
SYSCALL_SIGN(sys_notimpl),
|
||||||
|
SYSCALL_SIGN(sys_notimpl), /* 190 */
|
||||||
};
|
};
|
||||||
|
|
||||||
const void *lwp_get_sys_api(rt_uint32_t number)
|
const void *lwp_get_sys_api(rt_uint32_t number)
|
||||||
|
@ -5408,6 +5564,10 @@ const void *lwp_get_sys_api(rt_uint32_t number)
|
||||||
{
|
{
|
||||||
func = func_table[number].func;
|
func = func_table[number].func;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_I("Unimplement syscall %d", number);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return func;
|
return func;
|
||||||
|
@ -5428,6 +5588,10 @@ const char *lwp_get_syscall_name(rt_uint32_t number)
|
||||||
{
|
{
|
||||||
name = (char*)func_table[number].name;
|
name = (char*)func_table[number].name;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_I("Unimplement syscall %d", number);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip sys_
|
// skip sys_
|
||||||
|
|
161
include/rtdef.h
161
include/rtdef.h
|
@ -218,6 +218,7 @@ typedef __gnuc_va_list va_list;
|
||||||
#define rt_used __attribute__((used))
|
#define rt_used __attribute__((used))
|
||||||
#define rt_align(n) __attribute__((aligned(n)))
|
#define rt_align(n) __attribute__((aligned(n)))
|
||||||
#define rt_weak __attribute__((weak))
|
#define rt_weak __attribute__((weak))
|
||||||
|
#define rt_noreturn __attribute__ ((noreturn))
|
||||||
#define rt_inline static __inline
|
#define rt_inline static __inline
|
||||||
#define RTT_API
|
#define RTT_API
|
||||||
#elif defined (__ADSPBLACKFIN__) /* for VisualDSP++ Compiler */
|
#elif defined (__ADSPBLACKFIN__) /* for VisualDSP++ Compiler */
|
||||||
|
@ -399,6 +400,7 @@ typedef int (*init_fn_t)(void);
|
||||||
#define RT_ETRAP 11 /**< Trap event */
|
#define RT_ETRAP 11 /**< Trap event */
|
||||||
#define RT_ENOENT 12 /**< No entry */
|
#define RT_ENOENT 12 /**< No entry */
|
||||||
#define RT_ENOSPC 13 /**< No space left */
|
#define RT_ENOSPC 13 /**< No space left */
|
||||||
|
#define RT_EPERM 14 /**< Operation not permitted */
|
||||||
|
|
||||||
/**@}*/
|
/**@}*/
|
||||||
|
|
||||||
|
@ -753,14 +755,20 @@ struct rt_wakeup
|
||||||
#define _LWP_NSIG_BPW 32
|
#define _LWP_NSIG_BPW 32
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define _LWP_NSIG_WORDS (_LWP_NSIG / _LWP_NSIG_BPW)
|
#define _LWP_NSIG_WORDS (RT_ALIGN(_LWP_NSIG, _LWP_NSIG_BPW) / _LWP_NSIG_BPW)
|
||||||
|
|
||||||
typedef void (*lwp_sighandler_t)(int);
|
typedef void (*lwp_sighandler_t)(int);
|
||||||
|
typedef void (*lwp_sigaction_t)(int signo, siginfo_t *info, void *context);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned long sig[_LWP_NSIG_WORDS];
|
unsigned long sig[_LWP_NSIG_WORDS];
|
||||||
} lwp_sigset_t;
|
} lwp_sigset_t;
|
||||||
|
|
||||||
|
#if _LWP_NSIG <= 64
|
||||||
|
#define lwp_sigmask(signo) ((lwp_sigset_t){.sig = {[0] = ((long)(1u << ((signo)-1)))}})
|
||||||
|
#define lwp_sigset_init(mask) ((lwp_sigset_t){.sig = {[0] = (long)(mask)}})
|
||||||
|
#endif
|
||||||
|
|
||||||
struct lwp_sigaction {
|
struct lwp_sigaction {
|
||||||
union {
|
union {
|
||||||
void (*_sa_handler)(int);
|
void (*_sa_handler)(int);
|
||||||
|
@ -771,6 +779,29 @@ struct lwp_sigaction {
|
||||||
void (*sa_restorer)(void);
|
void (*sa_restorer)(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct lwp_siginfo {
|
||||||
|
rt_list_t node;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int signo;
|
||||||
|
int code;
|
||||||
|
long value;
|
||||||
|
|
||||||
|
int from_tid;
|
||||||
|
pid_t from_pid;
|
||||||
|
} ksiginfo;
|
||||||
|
} *lwp_siginfo_t;
|
||||||
|
|
||||||
|
typedef struct lwp_sigqueue {
|
||||||
|
rt_list_t siginfo_list;
|
||||||
|
lwp_sigset_t sigset_pending;
|
||||||
|
} *lwp_sigqueue_t;
|
||||||
|
|
||||||
|
struct lwp_thread_signal {
|
||||||
|
lwp_sigset_t sigset_mask;
|
||||||
|
struct lwp_sigqueue sig_queue;
|
||||||
|
};
|
||||||
|
|
||||||
struct rt_user_context
|
struct rt_user_context
|
||||||
{
|
{
|
||||||
void *sp;
|
void *sp;
|
||||||
|
@ -779,120 +810,116 @@ struct rt_user_context
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef void (*rt_thread_cleanup_t)(struct rt_thread *tid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thread structure
|
* Thread structure
|
||||||
*/
|
*/
|
||||||
struct rt_thread
|
struct rt_thread
|
||||||
{
|
{
|
||||||
struct rt_object parent;
|
struct rt_object parent;
|
||||||
rt_list_t tlist; /**< the thread list */
|
rt_list_t tlist; /**< the thread list */
|
||||||
|
|
||||||
/* stack point and entry */
|
/* stack point and entry */
|
||||||
void *sp; /**< stack point */
|
void *sp; /**< stack point */
|
||||||
void *entry; /**< entry */
|
void *entry; /**< entry */
|
||||||
void *parameter; /**< parameter */
|
void *parameter; /**< parameter */
|
||||||
void *stack_addr; /**< stack address */
|
void *stack_addr; /**< stack address */
|
||||||
rt_uint32_t stack_size; /**< stack size */
|
rt_uint32_t stack_size; /**< stack size */
|
||||||
|
|
||||||
/* error code */
|
/* error code */
|
||||||
rt_err_t error; /**< error code */
|
rt_err_t error; /**< error code */
|
||||||
|
|
||||||
rt_uint8_t stat; /**< thread status */
|
rt_uint8_t stat; /**< thread status */
|
||||||
|
|
||||||
#ifdef RT_USING_SMP
|
#ifdef RT_USING_SMP
|
||||||
rt_uint8_t bind_cpu; /**< thread is bind to cpu */
|
rt_uint8_t bind_cpu; /**< thread is bind to cpu */
|
||||||
rt_uint8_t oncpu; /**< process on cpu */
|
rt_uint8_t oncpu; /**< process on cpu */
|
||||||
|
|
||||||
rt_uint16_t scheduler_lock_nest; /**< scheduler lock count */
|
rt_uint16_t scheduler_lock_nest; /**< scheduler lock count */
|
||||||
rt_uint16_t cpus_lock_nest; /**< cpus lock count */
|
rt_int16_t cpus_lock_nest; /**< cpus lock count */
|
||||||
rt_uint16_t critical_lock_nest; /**< critical lock count */
|
rt_uint16_t critical_lock_nest; /**< critical lock count */
|
||||||
#endif /*RT_USING_SMP*/
|
#endif /*RT_USING_SMP*/
|
||||||
|
|
||||||
/* priority */
|
/* priority */
|
||||||
rt_uint8_t current_priority; /**< current priority */
|
rt_uint8_t current_priority; /**< current priority */
|
||||||
rt_uint8_t init_priority; /**< initialized priority */
|
rt_uint8_t init_priority; /**< initialized priority */
|
||||||
#if RT_THREAD_PRIORITY_MAX > 32
|
#if RT_THREAD_PRIORITY_MAX > 32
|
||||||
rt_uint8_t number;
|
rt_uint8_t number;
|
||||||
rt_uint8_t high_mask;
|
rt_uint8_t high_mask;
|
||||||
#endif /* RT_THREAD_PRIORITY_MAX > 32 */
|
#endif /* RT_THREAD_PRIORITY_MAX > 32 */
|
||||||
rt_uint32_t number_mask; /**< priority number mask */
|
rt_uint32_t number_mask; /**< priority number mask */
|
||||||
|
|
||||||
#ifdef RT_USING_MUTEX
|
#ifdef RT_USING_MUTEX
|
||||||
/* object for IPC */
|
/* object for IPC */
|
||||||
rt_list_t taken_object_list;
|
rt_list_t taken_object_list;
|
||||||
rt_object_t pending_object;
|
rt_object_t pending_object;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef RT_USING_EVENT
|
#ifdef RT_USING_EVENT
|
||||||
/* thread event */
|
/* thread event */
|
||||||
rt_uint32_t event_set;
|
rt_uint32_t event_set;
|
||||||
rt_uint8_t event_info;
|
rt_uint8_t event_info;
|
||||||
#endif /* RT_USING_EVENT */
|
#endif /* RT_USING_EVENT */
|
||||||
|
|
||||||
#ifdef RT_USING_SIGNALS
|
#ifdef RT_USING_SIGNALS
|
||||||
rt_sigset_t sig_pending; /**< the pending signals */
|
rt_sigset_t sig_pending; /**< the pending signals */
|
||||||
rt_sigset_t sig_mask; /**< the mask bits of signal */
|
rt_sigset_t sig_mask; /**< the mask bits of signal */
|
||||||
|
|
||||||
#ifndef RT_USING_SMP
|
#ifndef RT_USING_SMP
|
||||||
void *sig_ret; /**< the return stack pointer from signal */
|
void *sig_ret; /**< the return stack pointer from signal */
|
||||||
#endif /* RT_USING_SMP */
|
#endif /* RT_USING_SMP */
|
||||||
rt_sighandler_t *sig_vectors; /**< vectors of signal handler */
|
rt_sighandler_t *sig_vectors; /**< vectors of signal handler */
|
||||||
void *si_list; /**< the signal infor list */
|
void *si_list; /**< the signal infor list */
|
||||||
#endif /* RT_USING_SIGNALS */
|
#endif /* RT_USING_SIGNALS */
|
||||||
|
|
||||||
#ifdef RT_USING_SMART
|
rt_ubase_t init_tick; /**< thread's initialized tick */
|
||||||
void *msg_ret; /**< the return msg */
|
rt_ubase_t remaining_tick; /**< remaining tick */
|
||||||
#endif
|
|
||||||
|
|
||||||
rt_ubase_t init_tick; /**< thread's initialized tick */
|
|
||||||
rt_ubase_t remaining_tick; /**< remaining tick */
|
|
||||||
|
|
||||||
#ifdef RT_USING_CPU_USAGE
|
#ifdef RT_USING_CPU_USAGE
|
||||||
rt_uint64_t duration_tick; /**< cpu usage tick */
|
rt_uint64_t duration_tick; /**< cpu usage tick */
|
||||||
#endif /* RT_USING_CPU_USAGE */
|
#endif /* RT_USING_CPU_USAGE */
|
||||||
|
|
||||||
#ifdef RT_USING_PTHREADS
|
#ifdef RT_USING_PTHREADS
|
||||||
void *pthread_data; /**< the handle of pthread data, adapt 32/64bit */
|
void *pthread_data; /**< the handle of pthread data, adapt 32/64bit */
|
||||||
#endif /* RT_USING_PTHREADS */
|
#endif /* RT_USING_PTHREADS */
|
||||||
|
|
||||||
struct rt_timer thread_timer; /**< built-in thread timer */
|
struct rt_timer thread_timer; /**< built-in thread timer */
|
||||||
|
|
||||||
void (*cleanup)(struct rt_thread *tid); /**< cleanup function when thread exit */
|
rt_thread_cleanup_t cleanup; /**< cleanup function when thread exit */
|
||||||
|
|
||||||
/* light weight process if present */
|
/* light weight process if present */
|
||||||
#ifdef RT_USING_SMART
|
#ifdef RT_USING_SMART
|
||||||
void *lwp;
|
void *msg_ret; /**< the return msg */
|
||||||
|
|
||||||
|
void *lwp; /**< the lwp reference */
|
||||||
/* for user create */
|
/* for user create */
|
||||||
void *user_entry;
|
void *user_entry;
|
||||||
void *user_stack;
|
void *user_stack;
|
||||||
rt_uint32_t user_stack_size;
|
rt_uint32_t user_stack_size;
|
||||||
rt_uint32_t *kernel_sp; /**< kernel stack point */
|
rt_uint32_t *kernel_sp; /**< kernel stack point */
|
||||||
rt_list_t sibling; /**< next thread of same process */
|
rt_list_t sibling; /**< next thread of same process */
|
||||||
|
|
||||||
|
struct lwp_thread_signal signal; /**< lwp signal for user-space thread */
|
||||||
|
struct rt_user_context user_ctx; /**< user space context */
|
||||||
|
struct rt_wakeup wakeup; /**< wakeup data */
|
||||||
|
int exit_request;
|
||||||
|
int tid;
|
||||||
|
|
||||||
lwp_sigset_t signal;
|
|
||||||
lwp_sigset_t signal_mask;
|
|
||||||
int signal_mask_bak;
|
|
||||||
rt_uint32_t signal_in_process;
|
|
||||||
#ifndef ARCH_MM_MMU
|
#ifndef ARCH_MM_MMU
|
||||||
lwp_sighandler_t signal_handler[32];
|
lwp_sighandler_t signal_handler[32];
|
||||||
#endif
|
#else
|
||||||
struct rt_user_context user_ctx;
|
int step_exec;
|
||||||
|
int debug_attach_req;
|
||||||
|
int debug_ret_user;
|
||||||
|
int debug_suspend;
|
||||||
|
struct rt_hw_exp_stack *regs;
|
||||||
|
void *thread_idr; /** lwp thread indicator */
|
||||||
|
int *clear_child_tid;
|
||||||
|
#endif /* ARCH_MM_MMU */
|
||||||
|
#endif /* RT_USING_SMART */
|
||||||
|
|
||||||
struct rt_wakeup wakeup; /**< wakeup data */
|
rt_ubase_t user_data; /**< private user data beyond this thread */
|
||||||
int exit_request;
|
|
||||||
#if defined(ARCH_MM_MMU)
|
|
||||||
int step_exec;
|
|
||||||
int debug_attach_req;
|
|
||||||
int debug_ret_user;
|
|
||||||
int debug_suspend;
|
|
||||||
struct rt_hw_exp_stack *regs;
|
|
||||||
void * thread_idr; /** lwp thread indicator */
|
|
||||||
int *clear_child_tid;
|
|
||||||
#endif
|
|
||||||
int tid;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
rt_ubase_t user_data; /**< private user data beyond this thread */
|
|
||||||
};
|
};
|
||||||
typedef struct rt_thread *rt_thread_t;
|
typedef struct rt_thread *rt_thread_t;
|
||||||
|
|
||||||
|
|
14
src/thread.c
14
src/thread.c
|
@ -262,10 +262,12 @@ static rt_err_t _thread_init(struct rt_thread *thread,
|
||||||
#ifdef RT_USING_SMART
|
#ifdef RT_USING_SMART
|
||||||
thread->lwp = RT_NULL;
|
thread->lwp = RT_NULL;
|
||||||
rt_list_init(&(thread->sibling));
|
rt_list_init(&(thread->sibling));
|
||||||
rt_memset(&thread->signal, 0, sizeof(lwp_sigset_t));
|
|
||||||
rt_memset(&thread->signal_mask, 0, sizeof(lwp_sigset_t));
|
/* lwp thread-signal init */
|
||||||
thread->signal_mask_bak = 0;
|
rt_memset(&thread->signal.sigset_mask, 0, sizeof(lwp_sigset_t));
|
||||||
thread->signal_in_process = 0;
|
rt_memset(&thread->signal.sig_queue.sigset_pending, 0, sizeof(lwp_sigset_t));
|
||||||
|
rt_list_init(&thread->signal.sig_queue.siginfo_list);
|
||||||
|
|
||||||
rt_memset(&thread->user_ctx, 0, sizeof thread->user_ctx);
|
rt_memset(&thread->user_ctx, 0, sizeof thread->user_ctx);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -935,7 +937,7 @@ rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg)
|
||||||
RTM_EXPORT(rt_thread_control);
|
RTM_EXPORT(rt_thread_control);
|
||||||
|
|
||||||
#ifdef RT_USING_SMART
|
#ifdef RT_USING_SMART
|
||||||
int lwp_suspend_sigcheck(rt_thread_t thread, int suspend_flag);
|
#include <lwp_signal.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void rt_thread_set_suspend_state(struct rt_thread *thread, int suspend_flag)
|
static void rt_thread_set_suspend_state(struct rt_thread *thread, int suspend_flag)
|
||||||
|
@ -1004,7 +1006,7 @@ rt_err_t rt_thread_suspend_with_flag(rt_thread_t thread, int suspend_flag)
|
||||||
RT_ASSERT(thread == rt_thread_self());
|
RT_ASSERT(thread == rt_thread_self());
|
||||||
}
|
}
|
||||||
#ifdef RT_USING_SMART
|
#ifdef RT_USING_SMART
|
||||||
if (lwp_suspend_sigcheck(thread, suspend_flag) == 0)
|
if (lwp_thread_signal_suspend_check(thread, suspend_flag) == 0)
|
||||||
{
|
{
|
||||||
/* not to suspend */
|
/* not to suspend */
|
||||||
rt_hw_interrupt_enable(level);
|
rt_hw_interrupt_enable(level);
|
||||||
|
|
Loading…
Reference in New Issue