Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 64 additions & 8 deletions components/drivers/tty/console.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,74 @@
#endif /* RT_TTY_DEBUG */
#include <rtdbg.h>

#include <ipc/waitqueue.h>
#include <ipc/ringbuffer.h>

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)
{
struct tty_struct *console = NULL;
int len = 0;
int lens = 0;
char ch = 0;
char buf[1024] = {0};

console = (struct tty_struct *)dev;
RT_ASSERT(console != RT_NULL);
Expand All @@ -41,17 +100,14 @@ static void console_rx_notify(struct rt_device *dev)
break;
}
lens += len;
buf[lens-1] = ch;
if (lens > 1024)
rt_ringbuffer_put(&console_rx_ringbuffer, (void *)&ch, sizeof(ch));
if (lens > rb_bufsz)
{
break;
}
}

if (console->ldisc->ops->receive_buf)
{
console->ldisc->ops->receive_buf((struct tty_struct *)console, buf, lens);
}
if (console_rx_thread)
rt_wqueue_wakeup(&console_rx_wqueue, 0);
}

struct tty_struct *console_tty_get(void)
Expand Down
12 changes: 9 additions & 3 deletions components/drivers/tty/n_tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
#define ECHO_BLOCK 256
#define ECHO_DISCARD_WATERMARK RT_TTY_BUF - (ECHO_BLOCK + 32)


struct n_tty_data
{
/* producer-published */
Expand Down Expand Up @@ -136,6 +135,12 @@ rt_inline int test_and_clear_bit(int nr, volatile void *addr)
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)
{
int num = 0;
Expand Down Expand Up @@ -174,6 +179,7 @@ rt_inline unsigned long __ffs(unsigned long word)

return num;
}
#endif

#define BITS_PER_LONG 32
#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
Expand Down Expand Up @@ -703,13 +709,13 @@ static void __isig(int sig, struct tty_struct *tty)
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);
tty->foreground = old_lwp;
}
else
{
lwp_kill(lwp_to_pid(lwp), sig);
lwp_signal_kill(lwp, sig, SI_USER, 0);
}
}
}
Expand Down
36 changes: 1 addition & 35 deletions components/drivers/tty/tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,26 +126,6 @@ struct rt_lwp *tty_pop(struct tty_node **head, struct rt_lwp *target_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(&current->signal_mask, sig) ||
current->signal_handler[sig-1] == SIG_IGN);
}

/**
* tty_check_change - check for POSIX terminal changes
* @tty: tty to check
Expand All @@ -160,7 +140,6 @@ static int is_ignored(int sig)
int __tty_check_change(struct tty_struct *tty, int sig)
{
pid_t pgrp = 0, tty_pgrp = 0;
struct rt_lwp *lwp = tty->foreground;
int ret = 0;
int level = 0;

Expand All @@ -182,20 +161,7 @@ int __tty_check_change(struct tty_struct *tty, int sig)

if (tty_pgrp && (pgrp != tty->pgrp))
{
if (is_ignored(sig))
{
if (sig == SIGTTIN)
{
ret = -EIO;
}
}
else
{
if (lwp)
{
lwp_kill(lwp_to_pid(lwp), sig);
}
}
lwp_signal_kill(current, sig, SI_USER, 0);
}
rt_hw_interrupt_enable(level);

Expand Down
90 changes: 88 additions & 2 deletions components/libc/compilers/common/ctime.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
* 2021-05-01 Meco Man support fixed timezone
* 2021-07-21 Meco Man implement that change/set timezone APIs
* 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"
Expand Down Expand Up @@ -713,9 +715,56 @@ struct timer_obj
clockid_t clockid;
#ifdef RT_USING_SMART
pid_t pid;
struct rt_work *work;
#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)
{
struct timer_obj *timer;
Expand All @@ -735,7 +784,24 @@ static void rtthread_timer_wrapper(void *timerobj)
rt_ktime_hrtimer_start(&timer->hrtimer);
}
#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
if(timer->sigev_notify_function != RT_NULL)
{
Expand Down Expand Up @@ -802,7 +868,27 @@ int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid)
num %= 100;
timer->sigev_signo = evp->sigev_signo;
#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
timer->sigev_notify_function = evp->sigev_notify_function;
timer->val = evp->sigev_value;
Expand Down
Loading