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

View File

@ -21,7 +21,6 @@
#include <commpage.h>
#include <kernel.h>
#include <thread.h>
#include <tls.h>
#include <vm/vm_types.h>
#include <vm/VMAddressSpace.h>
#include <arch_vm.h>
@ -117,20 +116,12 @@ arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop,
status_t
arch_thread_init_tls(Thread *thread)
{
uint32 tls[TLS_FIRST_FREE_SLOT];
thread->user_local_storage = thread->user_stack_base
+ 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));
thread->user_local_storage =
thread->user_stack_base + thread->user_stack_size;
return B_OK;
}
void
arm_swap_pgdir(uint32_t pageDirectoryAddress)
{

View File

@ -13,7 +13,6 @@
#include <kernel.h>
#include <thread.h>
#include <team.h>
#include <tls.h>
#include <vm/vm_types.h>
#include <vm/VMAddressSpace.h>
@ -80,18 +79,9 @@ arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop,
status_t
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;
// 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));
thread->user_local_storage =
thread->user_stack_base + thread->user_stack_size;
return B_OK;
}

View File

@ -18,7 +18,6 @@
#include <int.h>
#include <team.h>
#include <thread.h>
#include <tls.h>
#include <vm/vm_types.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
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;
// 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));
thread->user_local_storage =
thread->user_stack_base + thread->user_stack_size;
return B_OK;
}

View File

@ -659,9 +659,28 @@ enter_userspace(Thread* thread, UserThreadEntryArguments* args)
userThread->pending_signals = 0;
clear_ac();
if (args->forkArgs != NULL) {
// This is a fork()ed thread. Copy the fork args onto the stack and
// free them.
// initialize default TLS fields
addr_t tls[TLS_FIRST_FREE_SLOT];
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;
free(args->forkArgs);