kernel/thread: Refactor thread-local-storage initialization and updating.
* TLS slots are not in any way architecture-specific; we do not even have a mechanism by which they could be made so at present. Thus, the initialization of them can be moved to common code, and out of the per-architecture implementations. * When dealing with a fork()ed thread, it will already have a TLS array with values set in it. Therefore, do not overwrite the whole array, but instead only update the specific values which have changed on fork. This fixes at least part of #17896.
This commit is contained in:
@@ -21,7 +21,6 @@
|
|||||||
#include <commpage.h>
|
#include <commpage.h>
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <thread.h>
|
#include <thread.h>
|
||||||
#include <tls.h>
|
|
||||||
#include <vm/vm_types.h>
|
#include <vm/vm_types.h>
|
||||||
#include <vm/VMAddressSpace.h>
|
#include <vm/VMAddressSpace.h>
|
||||||
#include <arch_vm.h>
|
#include <arch_vm.h>
|
||||||
@@ -117,20 +116,12 @@ arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop,
|
|||||||
status_t
|
status_t
|
||||||
arch_thread_init_tls(Thread *thread)
|
arch_thread_init_tls(Thread *thread)
|
||||||
{
|
{
|
||||||
uint32 tls[TLS_FIRST_FREE_SLOT];
|
thread->user_local_storage =
|
||||||
|
thread->user_stack_base + thread->user_stack_size;
|
||||||
thread->user_local_storage = thread->user_stack_base
|
return B_OK;
|
||||||
+ thread->user_stack_size;
|
|
||||||
|
|
||||||
// initialize default TLS fields
|
|
||||||
memset(tls, 0, sizeof(tls));
|
|
||||||
tls[TLS_BASE_ADDRESS_SLOT] = thread->user_local_storage;
|
|
||||||
tls[TLS_THREAD_ID_SLOT] = thread->id;
|
|
||||||
tls[TLS_USER_THREAD_SLOT] = (addr_t)thread->user_thread;
|
|
||||||
|
|
||||||
return user_memcpy((void *)thread->user_local_storage, tls, sizeof(tls));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
arm_swap_pgdir(uint32_t pageDirectoryAddress)
|
arm_swap_pgdir(uint32_t pageDirectoryAddress)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <thread.h>
|
#include <thread.h>
|
||||||
#include <team.h>
|
#include <team.h>
|
||||||
#include <tls.h>
|
|
||||||
#include <vm/vm_types.h>
|
#include <vm/vm_types.h>
|
||||||
#include <vm/VMAddressSpace.h>
|
#include <vm/VMAddressSpace.h>
|
||||||
|
|
||||||
@@ -80,18 +79,9 @@ arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop,
|
|||||||
status_t
|
status_t
|
||||||
arch_thread_init_tls(Thread *thread)
|
arch_thread_init_tls(Thread *thread)
|
||||||
{
|
{
|
||||||
addr_t tls[TLS_FIRST_FREE_SLOT];
|
thread->user_local_storage =
|
||||||
|
thread->user_stack_base + thread->user_stack_size;
|
||||||
thread->user_local_storage = thread->user_stack_base
|
return B_OK;
|
||||||
+ thread->user_stack_size;
|
|
||||||
|
|
||||||
// initialize default TLS fields
|
|
||||||
memset(tls, 0, sizeof(tls));
|
|
||||||
tls[TLS_BASE_ADDRESS_SLOT] = thread->user_local_storage;
|
|
||||||
tls[TLS_THREAD_ID_SLOT] = thread->id;
|
|
||||||
tls[TLS_USER_THREAD_SLOT] = (addr_t)thread->user_thread;
|
|
||||||
|
|
||||||
return user_memcpy((void*)thread->user_local_storage, tls, sizeof(tls));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
#include <int.h>
|
#include <int.h>
|
||||||
#include <team.h>
|
#include <team.h>
|
||||||
#include <thread.h>
|
#include <thread.h>
|
||||||
#include <tls.h>
|
|
||||||
#include <vm/vm_types.h>
|
#include <vm/vm_types.h>
|
||||||
#include <vm/VMAddressSpace.h>
|
#include <vm/VMAddressSpace.h>
|
||||||
|
|
||||||
@@ -184,26 +183,12 @@ arch_team_init_team_struct(Team* p, bool kernel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Initializes the user-space TLS local storage pointer in
|
|
||||||
the thread structure, and the reserved TLS slots.
|
|
||||||
|
|
||||||
Is called from _create_user_thread_kentry().
|
|
||||||
*/
|
|
||||||
status_t
|
status_t
|
||||||
arch_thread_init_tls(Thread* thread)
|
arch_thread_init_tls(Thread *thread)
|
||||||
{
|
{
|
||||||
addr_t tls[TLS_FIRST_FREE_SLOT];
|
thread->user_local_storage =
|
||||||
|
thread->user_stack_base + thread->user_stack_size;
|
||||||
thread->user_local_storage = thread->user_stack_base
|
return B_OK;
|
||||||
+ thread->user_stack_size;
|
|
||||||
|
|
||||||
// initialize default TLS fields
|
|
||||||
memset(tls, 0, sizeof(tls));
|
|
||||||
tls[TLS_BASE_ADDRESS_SLOT] = thread->user_local_storage;
|
|
||||||
tls[TLS_THREAD_ID_SLOT] = thread->id;
|
|
||||||
tls[TLS_USER_THREAD_SLOT] = (addr_t)thread->user_thread;
|
|
||||||
|
|
||||||
return user_memcpy((void*)thread->user_local_storage, tls, sizeof(tls));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -659,9 +659,28 @@ enter_userspace(Thread* thread, UserThreadEntryArguments* args)
|
|||||||
userThread->pending_signals = 0;
|
userThread->pending_signals = 0;
|
||||||
clear_ac();
|
clear_ac();
|
||||||
|
|
||||||
if (args->forkArgs != NULL) {
|
// initialize default TLS fields
|
||||||
// This is a fork()ed thread. Copy the fork args onto the stack and
|
addr_t tls[TLS_FIRST_FREE_SLOT];
|
||||||
// free them.
|
memset(tls, 0, sizeof(tls));
|
||||||
|
tls[TLS_BASE_ADDRESS_SLOT] = thread->user_local_storage;
|
||||||
|
tls[TLS_THREAD_ID_SLOT] = thread->id;
|
||||||
|
tls[TLS_USER_THREAD_SLOT] = (addr_t)thread->user_thread;
|
||||||
|
|
||||||
|
if (args->forkArgs == NULL) {
|
||||||
|
if (user_memcpy((void*)thread->user_local_storage, tls, sizeof(tls)) != B_OK)
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
} else {
|
||||||
|
// This is a fork()ed thread.
|
||||||
|
|
||||||
|
// Update select TLS values, do not clear the whole array.
|
||||||
|
set_ac();
|
||||||
|
addr_t* userTls = (addr_t*)thread->user_local_storage;
|
||||||
|
ASSERT(userTls[TLS_BASE_ADDRESS_SLOT] == thread->user_local_storage);
|
||||||
|
userTls[TLS_THREAD_ID_SLOT] = tls[TLS_THREAD_ID_SLOT];
|
||||||
|
userTls[TLS_USER_THREAD_SLOT] = tls[TLS_USER_THREAD_SLOT];
|
||||||
|
clear_ac();
|
||||||
|
|
||||||
|
// Copy the fork args onto the stack and free them.
|
||||||
arch_fork_arg archArgs = *args->forkArgs;
|
arch_fork_arg archArgs = *args->forkArgs;
|
||||||
free(args->forkArgs);
|
free(args->forkArgs);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user