summaryrefslogtreecommitdiff
path: root/components/lwp/lwp.c
diff options
context:
space:
mode:
Diffstat (limited to 'components/lwp/lwp.c')
-rw-r--r--components/lwp/lwp.c268
1 files changed, 170 insertions, 98 deletions
diff --git a/components/lwp/lwp.c b/components/lwp/lwp.c
index 7e85aaff9e..27d9f2f234 100644
--- a/components/lwp/lwp.c
+++ b/components/lwp/lwp.c
@@ -12,6 +12,8 @@
* 2023-02-20 wangxiaoyao inv icache before new app startup
* 2023-02-20 wangxiaoyao fix bug on foreground app switch
* 2023-10-16 Shell Support a new backtrace framework
+ * 2023-11-17 xqyjlj add process group and session support
+ * 2023-11-30 Shell add lwp_startup()
*/
#define DBG_TAG "lwp"
@@ -39,7 +41,7 @@
#include "lwp_arch_comm.h"
#include "lwp_signal.h"
#include "lwp_dbg.h"
-#include "console.h"
+#include <terminal/terminal.h>
#ifdef ARCH_MM_MMU
#include <lwp_user_mm.h>
@@ -59,16 +61,31 @@ static const char elf_magic[] = {0x7f, 'E', 'L', 'F'};
#ifdef DFS_USING_WORKDIR
extern char working_directory[];
#endif
-static struct termios stdin_termios, old_stdin_termios;
-int load_ldso(struct rt_lwp *lwp, char *exec_name, char *const argv[], char *const envp[]);
-
-struct termios *get_old_termios(void)
+/**
+ * @brief The default console is only a backup device with lowest priority.
+ * It's always recommended to scratch the console from the boot arguments.
+ * And dont forget to register the device with a higher priority.
+ */
+static rt_err_t lwp_default_console_setup(void)
{
- return &old_stdin_termios;
+ rt_device_t bakdev = rt_device_find("ttyS0");
+ rt_err_t rc;
+
+ if (bakdev)
+ {
+ lwp_console_register_backend(bakdev, LWP_CONSOLE_LOWEST_PRIOR);
+ rc = RT_EOK;
+ }
+ else
+ {
+ rc = -RT_EINVAL;
+ }
+
+ return rc;
}
-int lwp_component_init(void)
+static int lwp_component_init(void)
{
int rc;
if ((rc = lwp_tid_init()) != RT_EOK)
@@ -83,10 +100,99 @@ int lwp_component_init(void)
{
LOG_E("%s: rt_channel_component_init failed", __func__);
}
+ else if ((rc = lwp_futex_init()) != RT_EOK)
+ {
+ LOG_E("%s: lwp_futex_init() failed", __func__);
+ }
+ else if ((rc = lwp_default_console_setup()) != RT_EOK)
+ {
+ LOG_E("%s: lwp_default_console_setup() failed", __func__);
+ }
return rc;
}
INIT_COMPONENT_EXPORT(lwp_component_init);
+rt_weak int lwp_startup_debug_request(void)
+{
+ return 0;
+}
+
+#define LATENCY_TIMES (3)
+#define LATENCY_IN_MSEC (128)
+#define LWP_CONSOLE_PATH "CONSOLE=/dev/console"
+const char *init_search_path[] = {
+ "/sbin/init",
+ "/bin/init",
+};
+
+/**
+ * Startup process 0 and do the essential works
+ * This is the "Hello World" point of RT-Smart
+ */
+static int lwp_startup(void)
+{
+ int error;
+
+ const char *init_path;
+ char *argv[] = {0, "&"};
+ char *envp[] = {LWP_CONSOLE_PATH, 0};
+
+#ifdef LWP_DEBUG
+ int command;
+ int countdown = LATENCY_TIMES;
+ while (countdown)
+ {
+ command = lwp_startup_debug_request();
+ if (command)
+ {
+ return 0;
+ }
+ rt_kprintf("Press any key to stop init process startup ... %d\n", countdown);
+ countdown -= 1;
+ rt_thread_mdelay(LATENCY_IN_MSEC);
+ }
+ rt_kprintf("Starting init ...\n");
+#endif
+
+ for (size_t i = 0; i < sizeof(init_search_path)/sizeof(init_search_path[0]); i++)
+ {
+ struct stat s;
+ init_path = init_search_path[i];
+ error = stat(init_path, &s);
+ if (error == 0)
+ {
+ argv[0] = (void *)init_path;
+ error = lwp_execve((void *)init_path, 0, sizeof(argv)/sizeof(argv[0]), argv, envp);
+ if (error < 0)
+ {
+ LOG_E("%s: failed to startup process 0 (init)\n"
+ "Switching to legacy mode...", __func__);
+ }
+ else if (error != 1)
+ {
+ LOG_E("%s: pid 1 is already allocated", __func__);
+ error = -EBUSY;
+ }
+ else
+ {
+ rt_lwp_t p = lwp_from_pid_locked(1);
+ p->sig_protected = 0;
+
+ error = 0;
+ }
+ break;
+ }
+ }
+
+ if (error)
+ {
+ LOG_E("%s: init program not found\n"
+ "Switching to legacy mode...", __func__);
+ }
+ return error;
+}
+INIT_APP_EXPORT(lwp_startup);
+
void lwp_setcwd(char *buf)
{
struct rt_lwp *lwp = RT_NULL;
@@ -100,11 +206,11 @@ void lwp_setcwd(char *buf)
lwp = (struct rt_lwp *)rt_thread_self()->lwp;
if (lwp)
{
- rt_strncpy(lwp->working_directory, buf, DFS_PATH_MAX);
+ rt_strncpy(lwp->working_directory, buf, DFS_PATH_MAX - 1);
}
else
{
- rt_strncpy(working_directory, buf, DFS_PATH_MAX);
+ rt_strncpy(working_directory, buf, DFS_PATH_MAX - 1);
}
return ;
@@ -114,8 +220,13 @@ char *lwp_getcwd(void)
{
char *dir_buf = RT_NULL;
struct rt_lwp *lwp = RT_NULL;
+ rt_thread_t thread = rt_thread_self();
+
+ if (thread)
+ {
+ lwp = (struct rt_lwp *)thread->lwp;
+ }
- lwp = (struct rt_lwp *)rt_thread_self()->lwp;
if (lwp)
{
if(lwp->working_directory[0] != '/')
@@ -1077,25 +1188,35 @@ void lwp_cleanup(struct rt_thread *tid)
return;
}
-static void lwp_copy_stdio_fdt(struct rt_lwp *lwp)
+static void lwp_execve_setup_stdio(struct rt_lwp *lwp)
{
- struct dfs_file *d;
struct dfs_fdtable *lwp_fdt;
+ struct dfs_file *cons_file;
+ int cons_fd;
lwp_fdt = &lwp->fdt;
+
+ /* open console */
+ cons_fd = open("/dev/console", O_RDWR);
+ if (cons_fd < 0)
+ {
+ LOG_E("%s: Cannot open console tty", __func__);
+ return ;
+ }
+ LOG_D("%s: open console as fd %d", __func__, cons_fd);
+
/* init 4 fds */
lwp_fdt->fds = rt_calloc(4, sizeof(void *));
if (lwp_fdt->fds)
{
+ cons_file = fd_get(cons_fd);
lwp_fdt->maxfd = 4;
- d = fd_get(0);
- fdt_fd_associate_file(lwp_fdt, 0, d);
- d = fd_get(1);
- fdt_fd_associate_file(lwp_fdt, 1, d);
- d = fd_get(2);
- fdt_fd_associate_file(lwp_fdt, 2, d);
+ fdt_fd_associate_file(lwp_fdt, 0, cons_file);
+ fdt_fd_associate_file(lwp_fdt, 1, cons_file);
+ fdt_fd_associate_file(lwp_fdt, 2, cons_file);
}
+ close(cons_fd);
return;
}
@@ -1197,11 +1318,8 @@ pid_t lwp_execve(char *filename, int debug, int argc, char **argv, char **envp)
int result;
struct rt_lwp *lwp;
char *thread_name;
- char *argv_last = argv[argc - 1];
- int bg = 0;
struct process_aux *aux;
int tid = 0;
- int ret;
if (filename == RT_NULL)
{
@@ -1213,7 +1331,7 @@ pid_t lwp_execve(char *filename, int debug, int argc, char **argv, char **envp)
return -EACCES;
}
- lwp = lwp_create(LWP_CREATE_FLAG_ALLOC_PID);
+ lwp = lwp_create(LWP_CREATE_FLAG_ALLOC_PID | LWP_CREATE_FLAG_NOTRACE_EXEC);
if (lwp == RT_NULL)
{
@@ -1236,12 +1354,6 @@ pid_t lwp_execve(char *filename, int debug, int argc, char **argv, char **envp)
}
#endif
- if (argv_last[0] == '&' && argv_last[1] == '\0')
- {
- argc--;
- bg = 1;
- }
-
if ((aux = lwp_argscopy(lwp, argc, argv, envp)) == RT_NULL)
{
lwp_tid_put(tid);
@@ -1263,7 +1375,7 @@ pid_t lwp_execve(char *filename, int debug, int argc, char **argv, char **envp)
rt_thread_t thread = RT_NULL;
rt_uint32_t priority = 25, tick = 200;
- lwp_copy_stdio_fdt(lwp);
+ lwp_execve_setup_stdio(lwp);
/* obtain the base name */
thread_name = strrchr(filename, '/');
@@ -1284,88 +1396,46 @@ pid_t lwp_execve(char *filename, int debug, int argc, char **argv, char **envp)
if (thread != RT_NULL)
{
struct rt_lwp *self_lwp;
+ rt_session_t session;
+ rt_processgroup_t group;
thread->tid = tid;
lwp_tid_set_thread(tid, thread);
LOG_D("lwp kernel => (0x%08x, 0x%08x)\n", (rt_size_t)thread->stack_addr,
(rt_size_t)thread->stack_addr + thread->stack_size);
self_lwp = lwp_self();
+
+ /* when create init, self_lwp == null */
+ if (self_lwp == RT_NULL && lwp_to_pid(lwp) != 1)
+ {
+ self_lwp = lwp_from_pid_and_lock(1);
+ }
+
if (self_lwp)
{
- //lwp->tgroup_leader = &thread; //add thread group leader for lwp
- lwp->__pgrp = tid;
- lwp->session = self_lwp->session;
/* lwp add to children link */
lwp_children_register(self_lwp, lwp);
}
- else
- {
- //lwp->tgroup_leader = &thread; //add thread group leader for lwp
- lwp->__pgrp = tid;
- }
- if (!bg)
- {
- if (lwp->session == -1)
- {
- struct tty_struct *tty = RT_NULL;
- struct rt_lwp *old_lwp;
- tty = (struct tty_struct *)console_tty_get();
- old_lwp = tty->foreground;
- if (old_lwp)
- {
- rt_mutex_take(&tty->lock, RT_WAITING_FOREVER);
- ret = tty_push(&tty->head, old_lwp);
- rt_mutex_release(&tty->lock);
- if (ret < 0)
- {
- lwp_tid_put(tid);
- lwp_ref_dec(lwp);
- LOG_E("malloc fail!\n");
- return -ENOMEM;
- }
- }
+ session = RT_NULL;
+ group = RT_NULL;
- lwp->tty = tty;
- lwp->tty->pgrp = lwp->__pgrp;
- lwp->tty->session = lwp->session;
- lwp->tty->foreground = lwp;
- tcgetattr(1, &stdin_termios);
- old_stdin_termios = stdin_termios;
- stdin_termios.c_lflag |= ICANON | ECHO | ECHOCTL;
- tcsetattr(1, 0, &stdin_termios);
+ group = lwp_pgrp_create(lwp);
+ if (group)
+ {
+ lwp_pgrp_insert(group, lwp);
+ if (self_lwp == RT_NULL)
+ {
+ session = lwp_session_create(lwp);
+ lwp_session_insert(session, group);
}
else
{
- if (self_lwp != RT_NULL)
- {
- rt_mutex_take(&self_lwp->tty->lock, RT_WAITING_FOREVER);
- ret = tty_push(&self_lwp->tty->head, self_lwp);
- rt_mutex_release(&self_lwp->tty->lock);
- if (ret < 0)
- {
- lwp_tid_put(tid);
- lwp_ref_dec(lwp);
- LOG_E("malloc fail!\n");
- return -ENOMEM;
- }
-
- lwp->tty = self_lwp->tty;
- lwp->tty->pgrp = lwp->__pgrp;
- lwp->tty->session = lwp->session;
- lwp->tty->foreground = lwp;
- }
- else
- {
- lwp->tty = RT_NULL;
- }
-
+ session = lwp_session_find(lwp_sid_get_byprocess(self_lwp));
+ lwp_session_insert(session, group);
}
}
- else
- {
- lwp->background = RT_TRUE;
- }
+
thread->lwp = lwp;
#ifndef ARCH_MM_MMU
struct lwp_app_head *app_head = (struct lwp_app_head*)lwp->text_entry;
@@ -1381,6 +1451,8 @@ pid_t lwp_execve(char *filename, int debug, int argc, char **argv, char **envp)
#endif /* not defined ARCH_MM_MMU */
rt_list_insert_after(&lwp->t_grp, &thread->sibling);
+ lwp->did_exec = RT_TRUE;
+
if (debug && rt_dbg_ops)
{
lwp->debug = debug;
@@ -1482,30 +1554,30 @@ rt_err_t lwp_backtrace_frame(rt_thread_t uthread, struct rt_hw_backtrace_frame *
char **argv;
rt_lwp_t lwp;
- if (uthread->lwp)
+ if (uthread && uthread->lwp && rt_scheduler_is_available())
{
lwp = uthread->lwp;
argv = lwp_get_command_line_args(lwp);
if (argv)
{
- LOG_RAW("please use: addr2line -e %s -a -f", argv[0]);
+ rt_kprintf("please use: addr2line -e %s -a -f", argv[0]);
lwp_free_command_line_args(argv);
}
else
{
- LOG_RAW("please use: addr2line -e %s -a -f", lwp->cmd);
+ rt_kprintf("please use: addr2line -e %s -a -f", lwp->cmd);
}
while (nesting < RT_BACKTRACE_LEVEL_MAX_NR)
{
- LOG_RAW(" 0x%lx", frame->pc);
+ rt_kprintf(" 0x%lx", frame->pc);
if (rt_hw_backtrace_frame_unwind(uthread, frame))
{
break;
}
nesting++;
}
- LOG_RAW("\n");
+ rt_kprintf("\n");
rc = RT_EOK;
}
return rc;