* 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:
@@ -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);
|
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));
|
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_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);
|
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!
|
// ToDo: doing this this way is an ugly hack - please fix me!
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2006, Axel Dörfler, [email protected]. All rights reserved.
|
* Copyright 2002-2007, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
||||||
@@ -100,7 +100,9 @@ struct arch_thread;
|
|||||||
|
|
||||||
void __x86_setup_system_time(uint32 cv_factor);
|
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_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_set_tss_and_kstack(addr_t kstack);
|
||||||
void i386_switch_stack_and_call(addr_t stack, void (*func)(void *), void *arg);
|
void i386_switch_stack_and_call(addr_t stack, void (*func)(void *), void *arg);
|
||||||
void i386_swap_pgdir(addr_t new_pgdir);
|
void i386_swap_pgdir(addr_t new_pgdir);
|
||||||
|
|||||||
@@ -206,10 +206,11 @@ arch_thread_dump_info(void *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
status_t
|
||||||
arch_thread_enter_uspace(struct thread *thread, addr_t entry, void *arg1, void *arg2)
|
arch_thread_enter_userspace(struct thread *thread, addr_t entry, void *arg1, void *arg2)
|
||||||
{
|
{
|
||||||
panic("arch_thread_enter_uspace(): not yet implemented\n");
|
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
|
/** Sets up initial thread context and enters user space
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
status_t
|
||||||
arch_thread_enter_uspace(struct thread *t, addr_t entry, void *args1, void *args2)
|
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",
|
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
|
// copy the little stub that calls exit_thread() when the thread entry
|
||||||
// while interrupts are disabled.
|
// function returns
|
||||||
// XXX does this belong there, should caller take care of it?
|
stackTop -= codeSize;
|
||||||
*(uint32 *)(ustack_top - 8) = 0;
|
|
||||||
|
if (user_memcpy((void *)stackTop, x86_userspace_thread_exit, codeSize) < B_OK)
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
disable_interrupts();
|
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 the CPU dependent GDT entry for TLS
|
||||||
set_tls_context(t);
|
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.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
* Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||||
@@ -126,20 +126,20 @@ FUNCTION(i386_swap_pgdir):
|
|||||||
movl %eax,%cr3
|
movl %eax,%cr3
|
||||||
ret
|
ret
|
||||||
|
|
||||||
/* thread exit stub */
|
/* thread exit stub - is copied to the userspace stack in arch_thread_enter_uspace() */
|
||||||
.align 4
|
.align 4
|
||||||
i386_uspace_exit_stub:
|
FUNCTION(x86_userspace_thread_exit):
|
||||||
pushl %eax
|
pushl %eax
|
||||||
movl $1, %ecx
|
movl $1, %ecx
|
||||||
lea (%esp), %edx
|
lea (%esp), %edx
|
||||||
movl $SYSCALL_EXIT_THREAD, %eax;
|
movl $SYSCALL_EXIT_THREAD, %eax;
|
||||||
int $99
|
int $99
|
||||||
.align 4
|
.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); */
|
/* void x86_enter_userspace(addr entry, void *args1, void *args2, addr stackTop); */
|
||||||
FUNCTION(i386_enter_uspace):
|
FUNCTION(x86_enter_userspace):
|
||||||
movl 4(%esp),%eax // get entry point
|
movl 4(%esp),%eax // get entry point
|
||||||
movl 8(%esp),%edx // get arguments
|
movl 8(%esp),%edx // get arguments
|
||||||
movl 12(%esp),%edi
|
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 $0x33 + cpu_num,%fs -> fs points to the TLS storage (CPU dependent segment)
|
||||||
movw %cx,%gs
|
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
|
// push the args onto the user stack
|
||||||
movl %edi,-4(%ebx) // args1
|
movl %edi,-4(%ebx) // args1
|
||||||
movl %edx,-8(%ebx) // args2
|
movl %edx,-8(%ebx) // args2
|
||||||
|
|||||||
@@ -819,10 +819,8 @@ team_create_thread_start(void *args)
|
|||||||
team->state = TEAM_STATE_NORMAL;
|
team->state = TEAM_STATE_NORMAL;
|
||||||
|
|
||||||
// jump to the entry point in user space
|
// jump to the entry point in user space
|
||||||
arch_thread_enter_uspace(t, entry, uspa, NULL);
|
return arch_thread_enter_userspace(t, entry, uspa, NULL);
|
||||||
|
// only returns in case of error
|
||||||
// never gets here
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -309,9 +309,10 @@ _create_user_thread_kentry(void)
|
|||||||
thread_at_kernel_exit();
|
thread_at_kernel_exit();
|
||||||
|
|
||||||
// jump to the entry point in user space
|
// 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;
|
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,
|
(void **)&thread->user_stack_base, B_BASE_ADDRESS,
|
||||||
thread->user_stack_size + TLS_SIZE, B_NO_LOCK,
|
thread->user_stack_size + TLS_SIZE, B_NO_LOCK,
|
||||||
B_READ_AREA | B_WRITE_AREA | B_STACK_AREA);
|
B_READ_AREA | B_WRITE_AREA | B_STACK_AREA);
|
||||||
if (thread->user_stack_area < 0) {
|
if (thread->user_stack_area < B_OK
|
||||||
// great, we have a fully running thread without a stack
|
|| arch_thread_init_tls(thread) < B_OK) {
|
||||||
dprintf("create_thread: unable to create user stack!\n");
|
// 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;
|
status = thread->user_stack_area;
|
||||||
kill_thread(thread->id);
|
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
|
// 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) {
|
if (argc == 1) {
|
||||||
name = NULL;
|
_dump_thread_info(thread_get_current_thread());
|
||||||
id = thread_get_current_thread()->id;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
name = argv[1];
|
name = argv[1];
|
||||||
id = strtoul(argv[1], NULL, 0);
|
id = strtoul(argv[1], NULL, 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user