LibC: Make pthread_t pointer to uthread instead of a thread id
This will allow getting info about other threads in userspace!
This commit is contained in:
@@ -431,52 +431,41 @@ namespace Kernel
|
|||||||
O_EXEC | O_RDWR
|
O_EXEC | O_RDWR
|
||||||
));
|
));
|
||||||
|
|
||||||
BAN::Vector<uint8_t> temp_buffer;
|
|
||||||
TRY(temp_buffer.resize(BAN::Math::min<size_t>(master_size, PAGE_SIZE)));
|
|
||||||
|
|
||||||
size_t bytes_copied = 0;
|
size_t bytes_copied = 0;
|
||||||
while (bytes_copied < master_size)
|
while (bytes_copied < master_size)
|
||||||
{
|
{
|
||||||
const size_t to_copy = BAN::Math::min(master_size - bytes_copied, temp_buffer.size());
|
uint8_t buffer[PAGE_SIZE];
|
||||||
|
const size_t to_copy = BAN::Math::min(master_size - bytes_copied, sizeof(buffer));
|
||||||
|
|
||||||
const vaddr_t vaddr = master_addr + bytes_copied;
|
const vaddr_t vaddr = master_addr + bytes_copied;
|
||||||
const paddr_t paddr = page_table.physical_address_of(vaddr & PAGE_ADDR_MASK);
|
const paddr_t paddr = page_table.physical_address_of(vaddr & PAGE_ADDR_MASK);
|
||||||
PageTable::with_fast_page(paddr, [&] {
|
PageTable::with_fast_page(paddr, [&] {
|
||||||
memcpy(temp_buffer.data(), PageTable::fast_page_as_ptr(vaddr % PAGE_SIZE), to_copy);
|
memcpy(buffer, PageTable::fast_page_as_ptr(vaddr % PAGE_SIZE), to_copy);
|
||||||
});
|
});
|
||||||
|
|
||||||
TRY(region->copy_data_to_region(bytes_copied, temp_buffer.data(), to_copy));
|
TRY(region->copy_data_to_region(bytes_copied, buffer, to_copy));
|
||||||
bytes_copied += to_copy;
|
bytes_copied += to_copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto uthread = TRY(BAN::UniqPtr<struct uthread>::create());
|
uthread uthread {};
|
||||||
*uthread = {
|
uthread.self = reinterpret_cast<struct uthread*>(region->vaddr() + master_size);
|
||||||
.self = reinterpret_cast<struct uthread*>(region->vaddr() + master_size),
|
uthread.master_tls_addr = reinterpret_cast<void*>(master_addr),
|
||||||
.master_tls_addr = reinterpret_cast<void*>(master_addr),
|
uthread.master_tls_size = master_size,
|
||||||
.master_tls_size = master_size,
|
uthread.master_tls_module_count = 1;
|
||||||
.master_tls_module_count = 1,
|
uthread.dynamic_tls = nullptr;
|
||||||
.dynamic_tls = nullptr,
|
uthread.dtv[0] = 0;
|
||||||
.cleanup_stack = nullptr,
|
uthread.dtv[1] = region->vaddr();
|
||||||
.id = 0,
|
|
||||||
.errno_ = 0,
|
|
||||||
.cancel_type = 0,
|
|
||||||
.cancel_state = 0,
|
|
||||||
.canceled = 0,
|
|
||||||
.specific_keys = {},
|
|
||||||
.specific_values = {},
|
|
||||||
.dtv = { 0, region->vaddr() }
|
|
||||||
};
|
|
||||||
|
|
||||||
TRY(region->copy_data_to_region(
|
TRY(region->copy_data_to_region(
|
||||||
master_size,
|
master_size,
|
||||||
reinterpret_cast<const uint8_t*>(uthread.ptr()),
|
reinterpret_cast<const uint8_t*>(&uthread),
|
||||||
sizeof(struct uthread)
|
sizeof(struct uthread)
|
||||||
));
|
));
|
||||||
|
|
||||||
TLSResult result;
|
return TLSResult {
|
||||||
result.addr = region->vaddr() + master_size;;
|
.region = BAN::move(region),
|
||||||
result.region = BAN::move(region);
|
.addr = region->vaddr() + master_size,
|
||||||
return result;
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> Process::add_mapped_region(BAN::UniqPtr<MemoryRegion>&& region)
|
BAN::ErrorOr<void> Process::add_mapped_region(BAN::UniqPtr<MemoryRegion>&& region)
|
||||||
|
|||||||
@@ -7,10 +7,7 @@
|
|||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
#define __need_pid_t
|
typedef struct uthread* pthread_t;
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
typedef pid_t pthread_t;
|
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,11 @@
|
|||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
#define __need_pid_t
|
||||||
#define __need_size_t
|
#define __need_size_t
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <bits/types/pthread_attr_t.h>
|
||||||
#include <bits/types/pthread_key_t.h>
|
#include <bits/types/pthread_key_t.h>
|
||||||
#include <bits/types/pthread_t.h>
|
#include <bits/types/pthread_t.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
@@ -36,18 +38,24 @@ typedef struct _dynamic_tls_t
|
|||||||
struct uthread
|
struct uthread
|
||||||
{
|
{
|
||||||
struct uthread* self;
|
struct uthread* self;
|
||||||
|
|
||||||
|
// TLS
|
||||||
void* master_tls_addr;
|
void* master_tls_addr;
|
||||||
size_t master_tls_size;
|
size_t master_tls_size;
|
||||||
size_t master_tls_module_count;
|
size_t master_tls_module_count;
|
||||||
_dynamic_tls_t* dynamic_tls;
|
_dynamic_tls_t* dynamic_tls;
|
||||||
_pthread_cleanup_t* cleanup_stack;
|
|
||||||
pthread_t id;
|
// LIBC
|
||||||
|
pid_t id;
|
||||||
|
pthread_attr_t attr;
|
||||||
int errno_;
|
int errno_;
|
||||||
int cancel_type;
|
int cancel_type;
|
||||||
int cancel_state;
|
int cancel_state;
|
||||||
volatile int canceled;
|
volatile int canceled;
|
||||||
|
_pthread_cleanup_t* cleanup_funcs;
|
||||||
pthread_key_t specific_keys[PTHREAD_KEYS_MAX];
|
pthread_key_t specific_keys[PTHREAD_KEYS_MAX];
|
||||||
void* specific_values[PTHREAD_KEYS_MAX];
|
void* specific_vals[PTHREAD_KEYS_MAX];
|
||||||
|
|
||||||
// FIXME: make this dynamic
|
// FIXME: make this dynamic
|
||||||
uintptr_t dtv[1 + 256];
|
uintptr_t dtv[1 + 256];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ void pthread_cleanup_push(void (*routine)(void*), void* arg);
|
|||||||
|
|
||||||
#define _pthread_equal(t1, t2) ((t1) == (t2))
|
#define _pthread_equal(t1, t2) ((t1) == (t2))
|
||||||
|
|
||||||
#define _pthread_self() (_get_uthread()->id)
|
#define _pthread_self() (_get_uthread())
|
||||||
|
|
||||||
#define _pthread_testcancel() do { \
|
#define _pthread_testcancel() do { \
|
||||||
struct uthread* uthread = _get_uthread(); \
|
struct uthread* uthread = _get_uthread(); \
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
struct pthread_trampoline_info_t
|
struct pthread_trampoline_info_t
|
||||||
{
|
{
|
||||||
struct uthread* uthread;
|
struct uthread* uthread;
|
||||||
bool detached;
|
|
||||||
void* (*start_routine)(void*);
|
void* (*start_routine)(void*);
|
||||||
void* arg;
|
void* arg;
|
||||||
};
|
};
|
||||||
@@ -61,8 +60,10 @@ asm(
|
|||||||
|
|
||||||
extern "C" void _pthread_trampoline_cpp(void* arg)
|
extern "C" void _pthread_trampoline_cpp(void* arg)
|
||||||
{
|
{
|
||||||
auto info = *reinterpret_cast<pthread_trampoline_info_t*>(arg);
|
auto info = *static_cast<pthread_trampoline_info_t*>(arg);
|
||||||
|
|
||||||
info.uthread->id = syscall(SYS_THREAD_GETID);
|
info.uthread->id = syscall(SYS_THREAD_GETID);
|
||||||
|
|
||||||
#if defined(__x86_64__)
|
#if defined(__x86_64__)
|
||||||
syscall(SYS_SET_FSBASE, info.uthread);
|
syscall(SYS_SET_FSBASE, info.uthread);
|
||||||
#elif defined(__i686__)
|
#elif defined(__i686__)
|
||||||
@@ -70,10 +71,14 @@ extern "C" void _pthread_trampoline_cpp(void* arg)
|
|||||||
#else
|
#else
|
||||||
#error
|
#error
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// NOTE: we have to get id and set TLS to for free to be able to use pthread_self
|
||||||
free(arg);
|
free(arg);
|
||||||
|
|
||||||
signal(SIGCANCEL, &_pthread_cancel_handler);
|
signal(SIGCANCEL, &_pthread_cancel_handler);
|
||||||
if (info.detached)
|
if (info.uthread->attr.detachstate == PTHREAD_CREATE_DETACHED)
|
||||||
pthread_detach(info.uthread->id);
|
pthread_detach(info.uthread);
|
||||||
|
|
||||||
pthread_exit(info.start_routine(info.arg));
|
pthread_exit(info.start_routine(info.arg));
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
@@ -115,10 +120,10 @@ static void free_uthread(uthread* uthread)
|
|||||||
void pthread_cleanup_pop(int execute)
|
void pthread_cleanup_pop(int execute)
|
||||||
{
|
{
|
||||||
uthread* uthread = _get_uthread();
|
uthread* uthread = _get_uthread();
|
||||||
ASSERT(uthread->cleanup_stack);
|
ASSERT(uthread->cleanup_funcs);
|
||||||
|
|
||||||
auto* cleanup = uthread->cleanup_stack;
|
auto* cleanup = uthread->cleanup_funcs;
|
||||||
uthread->cleanup_stack = cleanup->next;
|
uthread->cleanup_funcs = cleanup->next;
|
||||||
|
|
||||||
if (execute)
|
if (execute)
|
||||||
cleanup->routine(cleanup->arg);
|
cleanup->routine(cleanup->arg);
|
||||||
@@ -135,9 +140,9 @@ void pthread_cleanup_push(void (*routine)(void*), void* arg)
|
|||||||
|
|
||||||
cleanup->routine = routine;
|
cleanup->routine = routine;
|
||||||
cleanup->arg = arg;
|
cleanup->arg = arg;
|
||||||
cleanup->next = uthread->cleanup_stack;
|
cleanup->next = uthread->cleanup_funcs;
|
||||||
|
|
||||||
uthread->cleanup_stack = cleanup;
|
uthread->cleanup_funcs = cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
static pthread_key_t s_pthread_key_current = 1;
|
static pthread_key_t s_pthread_key_current = 1;
|
||||||
@@ -197,9 +202,9 @@ void* pthread_getspecific(pthread_key_t key)
|
|||||||
if (uthread->specific_keys[i] != key)
|
if (uthread->specific_keys[i] != key)
|
||||||
{
|
{
|
||||||
uthread->specific_keys[i] = key;
|
uthread->specific_keys[i] = key;
|
||||||
uthread->specific_values[i] = nullptr;
|
uthread->specific_vals[i] = nullptr;
|
||||||
}
|
}
|
||||||
ret = uthread->specific_values[i];
|
ret = uthread->specific_vals[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pthread_spin_unlock(&s_pthread_key_lock);
|
pthread_spin_unlock(&s_pthread_key_lock);
|
||||||
@@ -220,7 +225,7 @@ int pthread_setspecific(pthread_key_t key, const void* value)
|
|||||||
continue;
|
continue;
|
||||||
if (uthread->specific_keys[i] != key)
|
if (uthread->specific_keys[i] != key)
|
||||||
uthread->specific_keys[i] = key;
|
uthread->specific_keys[i] = key;
|
||||||
uthread->specific_values[i] = const_cast<void*>(value);
|
uthread->specific_vals[i] = const_cast<void*>(value);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -375,11 +380,16 @@ int pthread_attr_getstacksize(const pthread_attr_t* __restrict attr, size_t* __r
|
|||||||
|
|
||||||
int pthread_attr_setstacksize(pthread_attr_t* attr, size_t stacksize)
|
int pthread_attr_setstacksize(pthread_attr_t* attr, size_t stacksize)
|
||||||
{
|
{
|
||||||
|
if (stacksize < PTHREAD_STACK_MIN)
|
||||||
|
return EINVAL;
|
||||||
|
if (auto rem = stacksize % getpagesize())
|
||||||
|
stacksize += getpagesize() - rem;
|
||||||
|
attr->stackaddr = nullptr;
|
||||||
attr->stacksize = stacksize;
|
attr->stacksize = stacksize;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_create(pthread_t* __restrict thread_id, const pthread_attr_t* __restrict attr, void* (*start_routine)(void*), void* __restrict arg)
|
int pthread_create(pthread_t* __restrict thread, const pthread_attr_t* __restrict attr, void* (*start_routine)(void*), void* __restrict arg)
|
||||||
{
|
{
|
||||||
auto* info = static_cast<pthread_trampoline_info_t*>(malloc(sizeof(pthread_trampoline_info_t)));
|
auto* info = static_cast<pthread_trampoline_info_t*>(malloc(sizeof(pthread_trampoline_info_t)));
|
||||||
if (info == nullptr)
|
if (info == nullptr)
|
||||||
@@ -387,12 +397,11 @@ int pthread_create(pthread_t* __restrict thread_id, const pthread_attr_t* __rest
|
|||||||
|
|
||||||
*info = {
|
*info = {
|
||||||
.uthread = nullptr,
|
.uthread = nullptr,
|
||||||
.detached = attr ? (attr->detachstate == PTHREAD_CREATE_DETACHED) : false,
|
|
||||||
.start_routine = start_routine,
|
.start_routine = start_routine,
|
||||||
.arg = arg,
|
.arg = arg,
|
||||||
};
|
};
|
||||||
|
|
||||||
long syscall_ret = 0;
|
uthread* result = nullptr;
|
||||||
|
|
||||||
{
|
{
|
||||||
uthread* self = _get_uthread();
|
uthread* self = _get_uthread();
|
||||||
@@ -413,14 +422,15 @@ int pthread_create(pthread_t* __restrict thread_id, const pthread_attr_t* __rest
|
|||||||
.master_tls_size = self->master_tls_size,
|
.master_tls_size = self->master_tls_size,
|
||||||
.master_tls_module_count = self->master_tls_module_count,
|
.master_tls_module_count = self->master_tls_module_count,
|
||||||
.dynamic_tls = self->dynamic_tls,
|
.dynamic_tls = self->dynamic_tls,
|
||||||
.cleanup_stack = nullptr,
|
|
||||||
.id = -1,
|
.id = -1,
|
||||||
|
.attr = attr ? *attr : s_default_pthread_attr,
|
||||||
.errno_ = 0,
|
.errno_ = 0,
|
||||||
.cancel_type = PTHREAD_CANCEL_DEFERRED,
|
.cancel_type = PTHREAD_CANCEL_DEFERRED,
|
||||||
.cancel_state = PTHREAD_CANCEL_ENABLE,
|
.cancel_state = PTHREAD_CANCEL_ENABLE,
|
||||||
.canceled = 0,
|
.canceled = 0,
|
||||||
|
.cleanup_funcs = nullptr,
|
||||||
.specific_keys = {},
|
.specific_keys = {},
|
||||||
.specific_values = {},
|
.specific_vals = {},
|
||||||
.dtv = { self->dtv[0] }
|
.dtv = { self->dtv[0] }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -430,14 +440,14 @@ int pthread_create(pthread_t* __restrict thread_id, const pthread_attr_t* __rest
|
|||||||
uthread->dtv[i] = self->dtv[i] - self_addr + uthread_addr;
|
uthread->dtv[i] = self->dtv[i] - self_addr + uthread_addr;
|
||||||
|
|
||||||
info->uthread = uthread;
|
info->uthread = uthread;
|
||||||
|
result = uthread;
|
||||||
}
|
}
|
||||||
|
|
||||||
syscall_ret = syscall(SYS_THREAD_CREATE, _pthread_trampoline, info);
|
if (syscall(SYS_THREAD_CREATE, _pthread_trampoline, info) == -1)
|
||||||
if (syscall_ret == -1)
|
|
||||||
goto pthread_create_error;
|
goto pthread_create_error;
|
||||||
|
|
||||||
if (thread_id)
|
if (thread)
|
||||||
*thread_id = syscall_ret;
|
*thread = result;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
pthread_create_error:
|
pthread_create_error:
|
||||||
@@ -450,13 +460,17 @@ pthread_create_error:
|
|||||||
|
|
||||||
int pthread_detach(pthread_t thread)
|
int pthread_detach(pthread_t thread)
|
||||||
{
|
{
|
||||||
return syscall(SYS_THREAD_DETACH, thread);
|
// FIXME: race if detached thread exits before assigning detachstate
|
||||||
|
if (syscall(SYS_THREAD_DETACH, thread->id) == -1)
|
||||||
|
return errno;
|
||||||
|
thread->attr.detachstate = PTHREAD_CREATE_DETACHED;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pthread_exit(void* value_ptr)
|
void pthread_exit(void* value_ptr)
|
||||||
{
|
{
|
||||||
uthread* uthread = _get_uthread();
|
uthread* uthread = _get_uthread();
|
||||||
while (uthread->cleanup_stack)
|
while (uthread->cleanup_funcs)
|
||||||
pthread_cleanup_pop(1);
|
pthread_cleanup_pop(1);
|
||||||
|
|
||||||
for (size_t iteration = 0; iteration < PTHREAD_DESTRUCTOR_ITERATIONS; iteration++)
|
for (size_t iteration = 0; iteration < PTHREAD_DESTRUCTOR_ITERATIONS; iteration++)
|
||||||
@@ -471,8 +485,8 @@ void pthread_exit(void* value_ptr)
|
|||||||
if (s_pthread_key_map[i] && uthread->specific_keys[i] == s_pthread_key_map[i])
|
if (s_pthread_key_map[i] && uthread->specific_keys[i] == s_pthread_key_map[i])
|
||||||
{
|
{
|
||||||
destructor = s_pthread_key_destructors[i];
|
destructor = s_pthread_key_destructors[i];
|
||||||
value = uthread->specific_values[i];
|
value = uthread->specific_vals[i];
|
||||||
uthread->specific_values[i] = nullptr;
|
uthread->specific_vals[i] = nullptr;
|
||||||
}
|
}
|
||||||
pthread_spin_unlock(&s_pthread_key_lock);
|
pthread_spin_unlock(&s_pthread_key_lock);
|
||||||
|
|
||||||
@@ -485,18 +499,26 @@ void pthread_exit(void* value_ptr)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
free_uthread(uthread);
|
if (uthread->attr.detachstate == PTHREAD_CREATE_DETACHED)
|
||||||
|
free_uthread(uthread);
|
||||||
syscall(SYS_THREAD_EXIT, value_ptr);
|
syscall(SYS_THREAD_EXIT, value_ptr);
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_join(pthread_t thread, void** value_ptr)
|
int pthread_join(pthread_t thread, void** value_ptr)
|
||||||
{
|
{
|
||||||
|
if (thread->attr.detachstate != PTHREAD_CREATE_JOINABLE)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
pthread_testcancel();
|
pthread_testcancel();
|
||||||
errno = 0;
|
errno = 0;
|
||||||
} while (syscall(SYS_THREAD_JOIN, thread, value_ptr) == -1 && errno == EINTR);
|
} while (syscall(SYS_THREAD_JOIN, thread->id, value_ptr) == -1 && errno == EINTR);
|
||||||
return errno;
|
|
||||||
|
const int ret = errno;
|
||||||
|
if (ret == 0)
|
||||||
|
free_uthread(thread);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_once(pthread_once_t* once_control, void (*init_routine)(void))
|
int pthread_once(pthread_once_t* once_control, void (*init_routine)(void))
|
||||||
@@ -536,8 +558,8 @@ void _pthread_call_atfork(int state)
|
|||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case _PTHREAD_ATFORK_PREPARE: list = s_atfork_prepare; break;
|
case _PTHREAD_ATFORK_PREPARE: list = s_atfork_prepare; break;
|
||||||
case _PTHREAD_ATFORK_PARENT: list = s_atfork_parent; break;
|
case _PTHREAD_ATFORK_PARENT: list = s_atfork_parent; break;
|
||||||
case _PTHREAD_ATFORK_CHILD: list = s_atfork_child; break;
|
case _PTHREAD_ATFORK_CHILD: list = s_atfork_child; break;
|
||||||
default:
|
default:
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
@@ -802,7 +824,7 @@ int pthread_mutex_lock(pthread_mutex_t* mutex)
|
|||||||
|
|
||||||
int pthread_mutex_trylock(pthread_mutex_t* mutex)
|
int pthread_mutex_trylock(pthread_mutex_t* mutex)
|
||||||
{
|
{
|
||||||
const uint32_t tid = pthread_self();
|
const uint32_t tid = pthread_self()->id;
|
||||||
|
|
||||||
switch (mutex->attr.type)
|
switch (mutex->attr.type)
|
||||||
{
|
{
|
||||||
@@ -831,7 +853,7 @@ int pthread_mutex_timedlock(pthread_mutex_t* __restrict mutex, const struct time
|
|||||||
if (const int ret = pthread_mutex_trylock(mutex); ret != EBUSY)
|
if (const int ret = pthread_mutex_trylock(mutex); ret != EBUSY)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
const uint32_t tid = pthread_self();
|
const uint32_t tid = pthread_self()->id;
|
||||||
|
|
||||||
uint32_t expected = 0;
|
uint32_t expected = 0;
|
||||||
while (!BAN::atomic_compare_exchange(mutex->futex, expected, tid, BAN::memory_order_acquire))
|
while (!BAN::atomic_compare_exchange(mutex->futex, expected, tid, BAN::memory_order_acquire))
|
||||||
@@ -854,7 +876,7 @@ int pthread_mutex_timedlock(pthread_mutex_t* __restrict mutex, const struct time
|
|||||||
|
|
||||||
int pthread_mutex_unlock(pthread_mutex_t* mutex)
|
int pthread_mutex_unlock(pthread_mutex_t* mutex)
|
||||||
{
|
{
|
||||||
ASSERT(mutex->futex == static_cast<uint32_t>(pthread_self()));
|
ASSERT(mutex->futex == static_cast<uint32_t>(pthread_self()->id));
|
||||||
|
|
||||||
mutex->lock_depth--;
|
mutex->lock_depth--;
|
||||||
if (mutex->lock_depth == 0)
|
if (mutex->lock_depth == 0)
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ void psignal(int signum, const char* message)
|
|||||||
|
|
||||||
int pthread_kill(pthread_t thread, int sig)
|
int pthread_kill(pthread_t thread, int sig)
|
||||||
{
|
{
|
||||||
if (syscall(SYS_THREAD_KILL, thread, sig) == -1)
|
if (syscall(SYS_THREAD_KILL, thread->id, sig) == -1)
|
||||||
return errno;
|
return errno;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,12 +65,12 @@ extern "C" void _init_libc(char** environ, init_funcs_t init_funcs, init_funcs_t
|
|||||||
#error
|
#error
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
self->cleanup_stack = nullptr;
|
|
||||||
self->id = syscall(SYS_THREAD_GETID);
|
self->id = syscall(SYS_THREAD_GETID);
|
||||||
self->errno_ = 0;
|
self->errno_ = 0;
|
||||||
self->cancel_type = PTHREAD_CANCEL_DEFERRED;
|
self->cancel_type = PTHREAD_CANCEL_DEFERRED;
|
||||||
self->cancel_state = PTHREAD_CANCEL_ENABLE;
|
self->cancel_state = PTHREAD_CANCEL_ENABLE;
|
||||||
self->canceled = false;
|
self->canceled = false;
|
||||||
|
self->cleanup_funs = nullptr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -83,14 +83,14 @@ extern "C" void _init_libc(char** environ, init_funcs_t init_funcs, init_funcs_t
|
|||||||
.master_tls_size = 0,
|
.master_tls_size = 0,
|
||||||
.master_tls_module_count = 1,
|
.master_tls_module_count = 1,
|
||||||
.dynamic_tls = nullptr,
|
.dynamic_tls = nullptr,
|
||||||
.cleanup_stack = nullptr,
|
|
||||||
.id = static_cast<pthread_t>(syscall(SYS_THREAD_GETID)),
|
.id = static_cast<pthread_t>(syscall(SYS_THREAD_GETID)),
|
||||||
.errno_ = 0,
|
.errno_ = 0,
|
||||||
.cancel_type = PTHREAD_CANCEL_DEFERRED,
|
.cancel_type = PTHREAD_CANCEL_DEFERRED,
|
||||||
.cancel_state = PTHREAD_CANCEL_ENABLE,
|
.cancel_state = PTHREAD_CANCEL_ENABLE,
|
||||||
.canceled = false,
|
.canceled = false,
|
||||||
|
.cleanup_funs = nullptr,
|
||||||
.specific_keys = {},
|
.specific_keys = {},
|
||||||
.specific_values = {},
|
.specific_vals = {},
|
||||||
.dtv = { 0 },
|
.dtv = { 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -216,16 +216,16 @@ static _dynamic_tls_t* s_dynamic_tls = nullptr;
|
|||||||
|
|
||||||
static const char* s_ld_library_path = nullptr;
|
static const char* s_ld_library_path = nullptr;
|
||||||
|
|
||||||
static BAN::Atomic<pthread_t> s_global_locker = 0;
|
static BAN::Atomic<pid_t> s_global_locker = 0;
|
||||||
static uint32_t s_global_lock_depth = 0;
|
static uint32_t s_global_lock_depth = 0;
|
||||||
|
|
||||||
constexpr uintptr_t SYM_NOT_FOUND = -1;
|
constexpr uintptr_t SYM_NOT_FOUND = -1;
|
||||||
|
|
||||||
static void lock_global_lock()
|
static void lock_global_lock()
|
||||||
{
|
{
|
||||||
const pthread_t tid = syscall(SYS_THREAD_GETID);
|
const pid_t tid = syscall(SYS_THREAD_GETID);
|
||||||
|
|
||||||
pthread_t expected = 0;
|
pid_t expected = 0;
|
||||||
while (!s_global_locker.compare_exchange(expected, tid))
|
while (!s_global_locker.compare_exchange(expected, tid))
|
||||||
{
|
{
|
||||||
if (expected == tid)
|
if (expected == tid)
|
||||||
@@ -1349,25 +1349,21 @@ static void initialize_tls(MasterTLS master_tls)
|
|||||||
memcpy(tls_addr, master_tls.addr, master_tls.size);
|
memcpy(tls_addr, master_tls.addr, master_tls.size);
|
||||||
|
|
||||||
uthread& uthread = *reinterpret_cast<struct uthread*>(tls_addr + master_tls.size);
|
uthread& uthread = *reinterpret_cast<struct uthread*>(tls_addr + master_tls.size);
|
||||||
|
memset(&uthread, 0, sizeof(uthread));
|
||||||
|
|
||||||
// uthread is prepared in libc init, but some other stuff may be calling pthread functions
|
uthread.self = &uthread;
|
||||||
// for example __cxa_guard_release calls pthread_cond_broadcast
|
uthread.master_tls_addr = master_tls.addr,
|
||||||
uthread = {
|
uthread.master_tls_size = master_tls.size,
|
||||||
.self = &uthread,
|
uthread.master_tls_module_count = master_tls.module_count,
|
||||||
.master_tls_addr = master_tls.addr,
|
uthread.dynamic_tls = s_dynamic_tls,
|
||||||
.master_tls_size = master_tls.size,
|
|
||||||
.master_tls_module_count = master_tls.module_count,
|
// these are prepared in libc init, but some other stuff may be calling pthread functions
|
||||||
.dynamic_tls = s_dynamic_tls,
|
// for example __cxa_guard_release calls pthread_cond_broadcast
|
||||||
.cleanup_stack = nullptr,
|
uthread.id = syscall(SYS_THREAD_GETID);
|
||||||
.id = static_cast<pthread_t>(syscall(SYS_THREAD_GETID)),
|
uthread.errno_ = 0;
|
||||||
.errno_ = 0,
|
uthread.cancel_type = PTHREAD_CANCEL_DEFERRED;
|
||||||
.cancel_type = PTHREAD_CANCEL_DEFERRED,
|
uthread.cancel_state = PTHREAD_CANCEL_ENABLE;
|
||||||
.cancel_state = PTHREAD_CANCEL_ENABLE,
|
uthread.canceled = false;
|
||||||
.canceled = false,
|
|
||||||
.specific_keys = {},
|
|
||||||
.specific_values = {},
|
|
||||||
.dtv = {},
|
|
||||||
};
|
|
||||||
|
|
||||||
uthread.dtv[0] = master_tls.module_count;
|
uthread.dtv[0] = master_tls.module_count;
|
||||||
for (size_t i = 0; i < s_loaded_file_count; i++)
|
for (size_t i = 0; i < s_loaded_file_count; i++)
|
||||||
|
|||||||
Reference in New Issue
Block a user