* 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:
parent
f5fa54f798
commit
8fc075ac5c
@ -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!
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user