Просмотр исходного кода

解决fork和clone时由于开启RT_BACKTRACE_FUNCTION_NAME后,新线程的栈指针问题

shaojinchun 4 лет назад
Родитель
Сommit
1a1abd486a

+ 1 - 1
bsp/qemu-vexpress-a9/.config

@@ -81,7 +81,7 @@ CONFIG_PV_OFFSET=0xa0000000
 # CONFIG_RT_IOREMAP_LATE is not set
 CONFIG_ARCH_ARM_CORTEX_A=y
 CONFIG_ARCH_ARM_CORTEX_A9=y
-# CONFIG_RT_BACKTRACE_FUNCTION_NAME is not set
+CONFIG_RT_BACKTRACE_FUNCTION_NAME=y
 
 #
 # RT-Thread Components

+ 1 - 0
bsp/qemu-vexpress-a9/rtconfig.h

@@ -59,6 +59,7 @@
 #define PV_OFFSET 0xa0000000
 #define ARCH_ARM_CORTEX_A
 #define ARCH_ARM_CORTEX_A9
+#define RT_BACKTRACE_FUNCTION_NAME
 
 /* RT-Thread Components */
 

+ 34 - 21
components/lwp/arch/arm/cortex-a/lwp_gcc.S

@@ -29,7 +29,7 @@
 .text
 
 /*
- * void lwp_user_entry(args, text, data);
+ * void lwp_user_entry(args, text, data, kstack);
  */
 .global lwp_user_entry
 .type lwp_user_entry, % function
@@ -39,6 +39,7 @@ lwp_user_entry:
     orr     r9, #Mode_USR
     cpsid i
     msr     spsr, r9
+    mov     sp, r3
 
     ldr     r3, =0x80000000 ;/* user stack top */
     /* set data address. */
@@ -63,32 +64,26 @@ set_user_context:
     mov pc, lr
 
 /*
-int lwp_set_thread_context(void *new_thread_stack, void *origin_thread_stack, void *user_stack, void **thread_sp, int tid);
+void lwp_set_thread_context(void *exit_addr, void *new_thread_stack, void *user_stack, void **thread_sp);
 */
 .global lwp_set_thread_context
 lwp_set_thread_context:
-    sub r12, r1, sp /* origin, r12 = origin sp offset */
-    sub r0, r0, r12 /* new sp */
-    stmfd r0!, {lr}
-    stmfd r0!, {lr}
-    stmfd r0!, {r12}
-    sub r12, sp, fp  /* new, r1 = origin fp offset */
-    sub r1, r0, r12
-    add r1, #12  /* new fp */
-    stmfd r0!, {r1} /* fp */
-    stmfd r0!, {r1 - r10}
+    sub r1, #(10 * 4 + 4 * 4) /* {r4 - r12, lr} , {r4, r5, spsr, u_pc} */
+    stmfd r1!, {r0}
     mov r12, #0
-    stmfd r0!, {r12} /* new thread return value */
-    mrs r1, cpsr
-    stmfd r0!, {r1} /* spsr */
-    mov r1, #0
-    stmfd r0!, {r1} /* now user lr is 0 */
-    stmfd r0!, {r2} /* user sp */
+    stmfd r1!, {r12}
+    stmfd r1!, {r1 - r12}
+    stmfd r1!, {r12} /* new thread return value */
+    mrs r12, cpsr
+    orr r12, #(1 << 7) /* disable irq */
+    stmfd r1!, {r12} /* spsr */
+    mov r12, #0
+    stmfd r1!, {r12} /* now user lr is 0 */
+    stmfd r1!, {r2} /* user sp */
 #ifdef RT_USING_FPU
-    stmfd r0!, {r1} /* not use fpu */
+    stmfd r1!, {r12} /* not use fpu */
 #endif
-    str r0, [r3]
-    ldr r0, [sp]
+    str r1, [r3]
     mov pc, lr
 
 .global lwp_get_user_sp
@@ -98,11 +93,29 @@ lwp_get_user_sp:
     cps #Mode_SVC
     mov pc, lr
 
+.global sys_fork
+.global sys_fork_exit
+sys_fork:
+    push {r4 - r12, lr}
+    bl _sys_fork
+sys_fork_exit:
+    pop {r4 - r12, lr}
+    b svc_exit
+
+.global sys_clone
+.global sys_clone_exit
+sys_clone:
+    push {r4 - r12, lr}
+    bl _sys_clone
+sys_clone_exit:
+    pop {r4 - r12, lr}
+    b svc_exit
 /*
 void lwp_exec_user(void *args, void *kernel_stack, void *user_entry)
 */
 .global lwp_exec_user
 lwp_exec_user:
+    cpsid i
     mov sp, r1
     mov lr, r2
     mov r2, #Mode_USR

+ 2 - 2
components/lwp/lwp.c

@@ -45,7 +45,7 @@
 
 static const char elf_magic[] = {0x7f, 'E', 'L', 'F'};
 
-extern void lwp_user_entry(void *args, const void *text, void *data, void *user_stack);
+extern void lwp_user_entry(void *args, const void *text, void *data, void *k_stack);
 extern int libc_stdio_get_console(void);
 
 /**
@@ -868,7 +868,7 @@ static void lwp_thread_entry(void *parameter)
     }
 #endif
 
-    lwp_user_entry(lwp->args, lwp->text_entry, lwp->data_entry, RT_NULL);
+    lwp_user_entry(lwp->args, lwp->text_entry, lwp->data_entry, tid->stack_addr + tid->stack_size);
 }
 
 struct rt_lwp *lwp_self(void)

+ 25 - 27
components/lwp/lwp_syscall.c

@@ -1239,9 +1239,12 @@ fail:
  *          start_args
  *          */
 #define SYS_CLONE_ARGS_NR 7
-int lwp_set_thread_context(void *new_thread_stack, void *origin_thread_stack,
-        void *user_stack, void **thread_sp, int tid);
-long sys_clone(void *arg[])
+int lwp_set_thread_context(void (*exit)(void), void *new_thread_stack,
+        void *user_stack, void **thread_sp);
+
+long sys_clone(void *arg[]);
+void sys_clone_exit(void);
+long _sys_clone(void *arg[])
 {
     rt_base_t level = 0;
     struct rt_lwp *lwp = 0;
@@ -1336,16 +1339,14 @@ long sys_clone(void *arg[])
     rt_hw_interrupt_enable(level);
 
     /* copy origin stack */
-    rt_memcpy(thread->stack_addr, self->stack_addr, ALLOC_KERNEL_STACK_SIZE);
+    rt_memcpy(thread->stack_addr, self->stack_addr, thread->stack_size);
     lwp_tid_set_thread(tid, thread);
-    tid = lwp_set_thread_context((void *)((char *)thread->stack_addr + ALLOC_KERNEL_STACK_SIZE),
-            (void *)((char *)self->stack_addr + ALLOC_KERNEL_STACK_SIZE), user_stack, &thread->sp, tid);
-    if (tid)
-    {
-        rt_thread_startup(thread);
-    }
+    lwp_set_thread_context(sys_clone_exit,
+            (void *)((char *)thread->stack_addr + thread->stack_size),
+            user_stack, &thread->sp);
+    /* new thread never reach there */
+    rt_thread_startup(thread);
     return (long)tid;
-
 fail:
     lwp_tid_put(tid);
     if (lwp)
@@ -1434,7 +1435,9 @@ static int lwp_copy_files(struct rt_lwp *dst, struct rt_lwp *src)
     return -1;
 }
 
-int sys_fork(void)
+int sys_fork(void);
+void sys_fork_exit(void);
+int _sys_fork(void)
 {
     rt_base_t level;
     int tid = 0;
@@ -1531,23 +1534,18 @@ int sys_fork(void)
     user_stack = lwp_get_user_sp();
     rt_hw_interrupt_enable(level);
 
-    tid = lwp_set_thread_context((void *)((char *)thread->stack_addr + thread->stack_size),
-            (void *)((char *)self_thread->stack_addr + self_thread->stack_size), user_stack, &thread->sp, tid);
-    if (tid)
-    {
-        level = rt_hw_interrupt_disable();
-        if (rt_console_get_foreground() == self_lwp)
-        {
-            rt_console_set_foreground(lwp);
-        }
-        rt_hw_interrupt_enable(level);
-        rt_thread_startup(thread);
-        return lwp_to_pid(lwp);
-    }
-    else
+    lwp_set_thread_context(sys_fork_exit,
+            (void *)((char *)thread->stack_addr + thread->stack_size),
+            user_stack, &thread->sp);
+    /* new thread never reach there */
+    level = rt_hw_interrupt_disable();
+    if (rt_console_get_foreground() == self_lwp)
     {
-        return 0;
+        rt_console_set_foreground(lwp);
     }
+    rt_hw_interrupt_enable(level);
+    rt_thread_startup(thread);
+    return lwp_to_pid(lwp);
 fail:
     if (tid != 0)
     {

+ 1 - 1
libcpu/Kconfig

@@ -104,7 +104,7 @@ config ARCH_ARM_CORTEX_A9
     select ARCH_ARM_CORTEX_A
 
 config RT_BACKTRACE_FUNCTION_NAME
-    bool "To show function name when backtrace. Warning: Don't selet it when use fork/clone!"
+    bool "To show function name when backtrace."
     default n
     depends on ARCH_ARM_CORTEX_A