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:
Augustin Cavalier
2023-03-29 11:24:17 -04:00
parent ed24eb5ff1
commit d86a240aec
4 changed files with 33 additions and 48 deletions
+4 -13
View File
@@ -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)
{ {
+3 -13
View File
@@ -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));
} }
+4 -19
View File
@@ -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));
} }
+22 -3
View File
@@ -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);