* There was no reason to copy the "userland calls exit_thread()" stub with interrupts

turned off - accessing userland memory. Now, arch_thread_enter_userspace() does that
  job, and as a result, may also fail.
* dump_thread() now directly prints the info of the current thread when used without
  argument (rather than iterating the thread list to look for the current thread).
* If arch_thread_init_tls() fails upon thread creation, the function will now return
  an error.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19775 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2007-01-12 18:26:32 +00:00
parent f5fa54f798
commit 8fc075ac5c
7 changed files with 43 additions and 46 deletions

View File

@ -23,7 +23,7 @@ status_t arch_thread_init_tls(struct thread *thread);
void arch_thread_context_switch(struct thread *t_from, struct thread *t_to);
status_t arch_thread_init_kthread_stack(struct thread *t, int (*start_func)(void), void (*entry_func)(void), void (*exit_func)(void));
void arch_thread_dump_info(void *info);
void arch_thread_enter_uspace(struct thread *t, addr_t entry, void *args1, void *args2);
status_t arch_thread_enter_userspace(struct thread *t, addr_t entry, void *args1, void *args2);
void arch_thread_switch_kstack_and_call(struct thread *t, addr_t new_kstack, void (*func)(void *), void *arg);
// ToDo: doing this this way is an ugly hack - please fix me!

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2002-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
@ -100,7 +100,9 @@ struct arch_thread;
void __x86_setup_system_time(uint32 cv_factor);
void i386_context_switch(struct arch_thread *old_state, struct arch_thread *new_state, addr_t new_pgdir);
void i386_enter_uspace(addr_t entry, void *args1, void *args2, addr_t ustack_top);
void x86_userspace_thread_exit(void);
void x86_end_userspace_thread_exit(void);
void x86_enter_userspace(addr_t entry, void *args1, void *args2, addr_t ustack_top);
void i386_set_tss_and_kstack(addr_t kstack);
void i386_switch_stack_and_call(addr_t stack, void (*func)(void *), void *arg);
void i386_swap_pgdir(addr_t new_pgdir);

View File

@ -206,10 +206,11 @@ arch_thread_dump_info(void *info)
}
void
arch_thread_enter_uspace(struct thread *thread, addr_t entry, void *arg1, void *arg2)
status_t
arch_thread_enter_userspace(struct thread *thread, addr_t entry, void *arg1, void *arg2)
{
panic("arch_thread_enter_uspace(): not yet implemented\n");
return B_ERROR;
}

View File

@ -306,18 +306,22 @@ arch_thread_dump_info(void *info)
/** Sets up initial thread context and enters user space
*/
void
arch_thread_enter_uspace(struct thread *t, addr_t entry, void *args1, void *args2)
status_t
arch_thread_enter_userspace(struct thread *t, addr_t entry, void *args1, void *args2)
{
addr_t ustack_top = t->user_stack_base + t->user_stack_size;
addr_t stackTop = t->user_stack_base + t->user_stack_size;
uint32 codeSize = (addr_t)x86_end_userspace_thread_exit
- (addr_t)x86_userspace_thread_exit;
TRACE(("arch_thread_enter_uspace: entry 0x%lx, args %p %p, ustack_top 0x%lx\n",
entry, args1, args2, ustack_top));
entry, args1, args2, stackTop));
// access the new stack to make sure the memory page is present
// while interrupts are disabled.
// XXX does this belong there, should caller take care of it?
*(uint32 *)(ustack_top - 8) = 0;
// copy the little stub that calls exit_thread() when the thread entry
// function returns
stackTop -= codeSize;
if (user_memcpy((void *)stackTop, x86_userspace_thread_exit, codeSize) < B_OK)
return B_BAD_ADDRESS;
disable_interrupts();
@ -326,7 +330,10 @@ arch_thread_enter_uspace(struct thread *t, addr_t entry, void *args1, void *args
// set the CPU dependent GDT entry for TLS
set_tls_context(t);
i386_enter_uspace(entry, args1, args2, ustack_top - 4);
x86_enter_userspace(entry, args1, args2, stackTop);
return B_OK;
// never gets here
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2003-2005, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2003-2007, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*
* Copyright 2001, Travis Geiselbrecht. All rights reserved.
@ -126,20 +126,20 @@ FUNCTION(i386_swap_pgdir):
movl %eax,%cr3
ret
/* thread exit stub */
/* thread exit stub - is copied to the userspace stack in arch_thread_enter_uspace() */
.align 4
i386_uspace_exit_stub:
FUNCTION(x86_userspace_thread_exit):
pushl %eax
movl $1, %ecx
lea (%esp), %edx
lea (%esp), %edx
movl $SYSCALL_EXIT_THREAD, %eax;
int $99
int $99
.align 4
i386_uspace_exit_stub_end:
FUNCTION(x86_end_userspace_thread_exit):
/* void i386_enter_uspace(addr entry, void *args1, void *args2, addr ustack_top); */
FUNCTION(i386_enter_uspace):
/* void x86_enter_userspace(addr entry, void *args1, void *args2, addr stackTop); */
FUNCTION(x86_enter_userspace):
movl 4(%esp),%eax // get entry point
movl 8(%esp),%edx // get arguments
movl 12(%esp),%edi
@ -150,16 +150,6 @@ FUNCTION(i386_enter_uspace):
//movw $0x33 + cpu_num,%fs -> fs points to the TLS storage (CPU dependent segment)
movw %cx,%gs
// copy exit stub to stack
movl $i386_uspace_exit_stub_end, %esi
_copy_more:
lea -4(%esi), %esi
lea -4(%ebx), %ebx
mov (%esi), %ecx
mov %ecx, (%ebx)
cmp $i386_uspace_exit_stub, %esi
jg _copy_more
// push the args onto the user stack
movl %edi,-4(%ebx) // args1
movl %edx,-8(%ebx) // args2

View File

@ -819,10 +819,8 @@ team_create_thread_start(void *args)
team->state = TEAM_STATE_NORMAL;
// jump to the entry point in user space
arch_thread_enter_uspace(t, entry, uspa, NULL);
// never gets here
return B_OK;
return arch_thread_enter_userspace(t, entry, uspa, NULL);
// only returns in case of error
}

View File

@ -309,9 +309,10 @@ _create_user_thread_kentry(void)
thread_at_kernel_exit();
// jump to the entry point in user space
arch_thread_enter_uspace(thread, (addr_t)thread->entry, thread->args1, thread->args2);
arch_thread_enter_userspace(thread, (addr_t)thread->entry,
thread->args1, thread->args2);
// never get here
// only get here if the above call fails
return 0;
}
@ -462,14 +463,12 @@ create_thread(const char *name, team_id teamID, thread_entry_func entry,
(void **)&thread->user_stack_base, B_BASE_ADDRESS,
thread->user_stack_size + TLS_SIZE, B_NO_LOCK,
B_READ_AREA | B_WRITE_AREA | B_STACK_AREA);
if (thread->user_stack_area < 0) {
// great, we have a fully running thread without a stack
dprintf("create_thread: unable to create user stack!\n");
if (thread->user_stack_area < B_OK
|| arch_thread_init_tls(thread) < B_OK) {
// great, we have a fully running thread without a (usable) stack
dprintf("create_thread: unable to create proper user stack!\n");
status = thread->user_stack_area;
kill_thread(thread->id);
} else {
// now that the TLS area is allocated, initialize TLS
arch_thread_init_tls(thread);
}
// copy the user entry over to the args field in the thread struct
@ -603,8 +602,8 @@ dump_thread_info(int argc, char **argv)
}
if (argc == 1) {
name = NULL;
id = thread_get_current_thread()->id;
_dump_thread_info(thread_get_current_thread());
return 0;
} else {
name = argv[1];
id = strtoul(argv[1], NULL, 0);