Removed the broken arch_thread::current_iframe field and switched to the
same mechanism as NewOS, ie. using the iframe "stack" pointer (using the new i386_get_current_iframe() function). Implemented fork() support functions arch_{store|restore}_fork_frame(). git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9292 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
21942ca92a
commit
adf29fcdda
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright 2002-2004, The OpenBeOS Team. All rights reserved.
|
** Copyright 2002-2004, The Haiku Team. All rights reserved.
|
||||||
** Distributed under the terms of the OpenBeOS License.
|
** Distributed under the terms of the Haiku License.
|
||||||
**
|
**
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||||
** Distributed under the terms of the NewOS License.
|
** Distributed under the terms of the NewOS License.
|
||||||
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
// from arch_interrupts.S
|
// from arch_interrupts.S
|
||||||
extern void i386_stack_init(struct farcall *interrupt_stack_offset);
|
extern void i386_stack_init(struct farcall *interrupt_stack_offset);
|
||||||
|
extern void i386_restore_frame_from_syscall(struct iframe frame);
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -43,6 +44,32 @@ i386_pop_iframe(struct thread *thread)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Returns the current iframe structure of the running thread.
|
||||||
|
* This function must only be called in a context where it's actually
|
||||||
|
* sure that such iframe exists; ie. from syscalls, but usually not
|
||||||
|
* from standard kernel threads.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static struct iframe *
|
||||||
|
i386_get_current_iframe(void)
|
||||||
|
{
|
||||||
|
struct thread *thread = thread_get_current_thread();
|
||||||
|
|
||||||
|
ASSERT(thread->arch_info.iframe_ptr >= 0);
|
||||||
|
return thread->arch_info.iframes[thread->arch_info.iframe_ptr - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline uint32
|
||||||
|
get_fs_register(void)
|
||||||
|
{
|
||||||
|
uint32 fs;
|
||||||
|
|
||||||
|
asm("movl %%fs,%0" : "=r" (fs));
|
||||||
|
return fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
set_fs_register(uint32 segment)
|
set_fs_register(uint32 segment)
|
||||||
{
|
{
|
||||||
@ -85,9 +112,9 @@ arch_thread_init_thread_struct(struct thread *t)
|
|||||||
int
|
int
|
||||||
arch_thread_init_kthread_stack(struct thread *t, int (*start_func)(void), void (*entry_func)(void), void (*exit_func)(void))
|
arch_thread_init_kthread_stack(struct thread *t, int (*start_func)(void), void (*entry_func)(void), void (*exit_func)(void))
|
||||||
{
|
{
|
||||||
unsigned int *kstack = (unsigned int *)t->kernel_stack_base;
|
addr_t *kstack = (addr_t *)t->kernel_stack_base;
|
||||||
unsigned int kstack_size = KSTACK_SIZE;
|
addr_t kstack_size = KSTACK_SIZE;
|
||||||
unsigned int *kstack_top = kstack + kstack_size / sizeof(unsigned int);
|
addr_t *kstack_top = kstack + kstack_size / sizeof(addr_t);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
TRACE(("arch_thread_initialize_kthread_stack: kstack 0x%p, start_func 0x%p, entry_func 0x%p\n",
|
TRACE(("arch_thread_initialize_kthread_stack: kstack 0x%p, start_func 0x%p, entry_func 0x%p\n",
|
||||||
@ -120,7 +147,7 @@ arch_thread_init_kthread_stack(struct thread *t, int (*start_func)(void), void (
|
|||||||
|
|
||||||
// save the stack position
|
// save the stack position
|
||||||
t->arch_info.current_stack.esp = kstack_top;
|
t->arch_info.current_stack.esp = kstack_top;
|
||||||
t->arch_info.current_stack.ss = (int *)KERNEL_DATA_SEG;
|
t->arch_info.current_stack.ss = (addr_t *)KERNEL_DATA_SEG;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -249,7 +276,7 @@ arch_thread_enter_uspace(struct thread *t, addr_t entry, void *args1, void *args
|
|||||||
status_t
|
status_t
|
||||||
arch_setup_signal_frame(struct thread *t, struct sigaction *sa, int sig, int sig_mask)
|
arch_setup_signal_frame(struct thread *t, struct sigaction *sa, int sig, int sig_mask)
|
||||||
{
|
{
|
||||||
struct iframe *frame = t->arch_info.current_iframe;
|
struct iframe *frame = i386_get_current_iframe();
|
||||||
uint32 *stack_ptr = (uint32 *)frame->user_esp;
|
uint32 *stack_ptr = (uint32 *)frame->user_esp;
|
||||||
uint32 *code_ptr;
|
uint32 *code_ptr;
|
||||||
uint32 *regs_ptr;
|
uint32 *regs_ptr;
|
||||||
@ -264,6 +291,7 @@ arch_setup_signal_frame(struct thread *t, struct sigaction *sa, int sig, int sig
|
|||||||
frame->eax = frame->orig_eax;
|
frame->eax = frame->orig_eax;
|
||||||
frame->edx = frame->orig_edx;
|
frame->edx = frame->orig_edx;
|
||||||
frame->eip -= 2;
|
frame->eip -= 2;
|
||||||
|
// undos the "int $99" syscall interrupt (so that it'll be called again)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,14 +351,12 @@ int64
|
|||||||
arch_restore_signal_frame(void)
|
arch_restore_signal_frame(void)
|
||||||
{
|
{
|
||||||
struct thread *t = thread_get_current_thread();
|
struct thread *t = thread_get_current_thread();
|
||||||
struct iframe *frame;
|
struct iframe *frame = i386_get_current_iframe();
|
||||||
uint32 *stack;
|
uint32 *stack;
|
||||||
struct vregs *regs;
|
struct vregs *regs;
|
||||||
|
|
||||||
TRACE(("### arch_restore_signal_frame: entry\n"));
|
TRACE(("### arch_restore_signal_frame: entry\n"));
|
||||||
|
|
||||||
frame = t->arch_info.current_iframe;
|
|
||||||
|
|
||||||
stack = (uint32 *)frame->user_esp;
|
stack = (uint32 *)frame->user_esp;
|
||||||
t->sig_block_mask = stack[0];
|
t->sig_block_mask = stack[0];
|
||||||
regs = (struct vregs *)stack[1];
|
regs = (struct vregs *)stack[1];
|
||||||
@ -345,13 +371,13 @@ arch_restore_signal_frame(void)
|
|||||||
frame->edi = regs->_reserved_2[0];
|
frame->edi = regs->_reserved_2[0];
|
||||||
frame->esi = regs->_reserved_2[1];
|
frame->esi = regs->_reserved_2[1];
|
||||||
frame->ebp = regs->_reserved_2[2];
|
frame->ebp = regs->_reserved_2[2];
|
||||||
|
|
||||||
i386_frstor((void *)(®s->xregs));
|
i386_frstor((void *)(®s->xregs));
|
||||||
|
|
||||||
TRACE(("### arch_restore_signal_frame: exit\n"));
|
TRACE(("### arch_restore_signal_frame: exit\n"));
|
||||||
|
|
||||||
frame->orig_eax = -1; /* disable syscall checks */
|
frame->orig_eax = -1; /* disable syscall checks */
|
||||||
|
|
||||||
return (int64)frame->eax | ((int64)frame->edx << 32);
|
return (int64)frame->eax | ((int64)frame->edx << 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,7 +385,7 @@ arch_restore_signal_frame(void)
|
|||||||
void
|
void
|
||||||
arch_check_syscall_restart(struct thread *t)
|
arch_check_syscall_restart(struct thread *t)
|
||||||
{
|
{
|
||||||
struct iframe *frame = t->arch_info.current_iframe;
|
struct iframe *frame = i386_get_current_iframe();
|
||||||
|
|
||||||
if ((status_t)frame->orig_eax >= 0 && (status_t)frame->eax == EINTR) {
|
if ((status_t)frame->orig_eax >= 0 && (status_t)frame->eax == EINTR) {
|
||||||
frame->eax = frame->orig_eax;
|
frame->eax = frame->orig_eax;
|
||||||
@ -368,3 +394,45 @@ arch_check_syscall_restart(struct thread *t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Saves everything needed to restore the frame in the child fork in the
|
||||||
|
* arch_fork_arg structure to be passed to arch_restore_fork_frame().
|
||||||
|
* Also makes sure to return the right value.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
arch_store_fork_frame(struct arch_fork_arg *arg)
|
||||||
|
{
|
||||||
|
struct iframe *frame = i386_get_current_iframe();
|
||||||
|
|
||||||
|
// we need to copy the threads current iframe
|
||||||
|
arg->iframe = *frame;
|
||||||
|
|
||||||
|
// we also want fork() to return 0 for the child
|
||||||
|
arg->iframe.eax = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Restores the frame from a forked team as specified by the provided
|
||||||
|
* arch_fork_arg structure.
|
||||||
|
* Needs to be called from within the child team, ie. instead of
|
||||||
|
* arch_thread_enter_uspace() as thread "starter".
|
||||||
|
* This function does not return to the caller, but will enter userland
|
||||||
|
* in the child team at the same position where the parent team left of.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
arch_restore_fork_frame(struct arch_fork_arg *arg)
|
||||||
|
{
|
||||||
|
struct thread *thread = thread_get_current_thread();
|
||||||
|
|
||||||
|
i386_set_tss_and_kstack(thread->kernel_stack_base + KSTACK_SIZE);
|
||||||
|
|
||||||
|
// set the CPU dependent GDT entry for TLS (set the current %fs register)
|
||||||
|
set_tls_context(thread);
|
||||||
|
|
||||||
|
// patch up %fs register of the frame
|
||||||
|
arg->iframe.fs = get_fs_register();
|
||||||
|
|
||||||
|
i386_restore_frame_from_syscall(arg->iframe);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user