Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for pthread_getattr_np #470

Merged
merged 1 commit into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ LIBC_TOP_HALF_MUSL_SOURCES += \
thread/pthread_create.c \
thread/pthread_detach.c \
thread/pthread_equal.c \
thread/pthread_getattr_np.c \
thread/pthread_getspecific.c \
thread/pthread_join.c \
thread/pthread_key_create.c \
Expand Down
1 change: 1 addition & 0 deletions expected/wasm32-wasip1-threads/defined-symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1010,6 +1010,7 @@ pthread_condattr_setpshared
pthread_create
pthread_detach
pthread_equal
pthread_getattr_np
pthread_getspecific
pthread_join
pthread_key_create
Expand Down
36 changes: 26 additions & 10 deletions libc-top-half/musl/src/env/__init_tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,35 @@ extern unsigned char __global_base;
extern weak unsigned char __stack_high;
extern weak unsigned char __stack_low;

static inline void setup_default_stack_size()
struct stack_bounds {
void *base;
size_t size;
};

static inline struct stack_bounds get_stack_bounds()
{
ptrdiff_t stack_size;
struct stack_bounds bounds;

if (&__stack_high)
stack_size = &__stack_high - &__stack_low;
else {
if (&__stack_high) {
bounds.base = &__stack_high;
bounds.size = &__stack_high - &__stack_low;
} else {
unsigned char *sp;
__asm__(
".globaltype __stack_pointer, i32\n"
"global.get __stack_pointer\n"
"local.set %0\n"
: "=r"(sp));
stack_size = sp > &__global_base ? &__heap_base - &__data_end : (ptrdiff_t)&__global_base;
if (sp > &__global_base) {
bounds.base = &__heap_base;
bounds.size = &__heap_base - &__data_end;
} else {
bounds.base = &__global_base;
bounds.size = (size_t)&__global_base;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code only calculates the stack found of the main thread (i.e. the singular stack that the linker produces). Is that intended?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fills data for main thread, spawned threads have these fields filled in pthread_create.

}

__default_stacksize =
stack_size < DEFAULT_STACK_MAX ?
stack_size : DEFAULT_STACK_MAX;
return bounds;
}

void __wasi_init_tp() {
Expand All @@ -68,8 +78,14 @@ int __init_tp(void *p)
td->detach_state = DT_JOINABLE;
td->tid = __syscall(SYS_set_tid_address, &__thread_list_lock);
#else
setup_default_stack_size();
struct stack_bounds bounds = get_stack_bounds();
__default_stacksize =
bounds.size < DEFAULT_STACK_MAX ?
bounds.size : DEFAULT_STACK_MAX;
td->detach_state = DT_JOINABLE;
td->stack = bounds.base;
td->stack_size = bounds.size;
td->guard_size = 0;
/*
* Initialize the TID to a value which doesn't conflict with
* host-allocated TIDs, so that TID-based locks can work.
Expand Down
6 changes: 6 additions & 0 deletions libc-top-half/musl/src/thread/pthread_getattr_np.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#define _GNU_SOURCE
#include "pthread_impl.h"
#include "libc.h"
#ifdef __wasilibc_unmodified_upstream
#include <sys/mman.h>
#endif

int pthread_getattr_np(pthread_t t, pthread_attr_t *a)
{
Expand All @@ -12,13 +14,17 @@ int pthread_getattr_np(pthread_t t, pthread_attr_t *a)
a->_a_stackaddr = (uintptr_t)t->stack;
a->_a_stacksize = t->stack_size;
} else {
#ifdef __wasilibc_unmodified_upstream
char *p = (void *)libc.auxv;
size_t l = PAGE_SIZE;
p += -(uintptr_t)p & PAGE_SIZE-1;
a->_a_stackaddr = (uintptr_t)p;
while (mremap(p-l-PAGE_SIZE, PAGE_SIZE, 2*PAGE_SIZE, 0)==MAP_FAILED && errno==ENOMEM)
l += PAGE_SIZE;
a->_a_stacksize = l;
#else
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we can leave the if / else above and just replace the else block.

It looks like that if block covers secondary threads and the else block covers the main thread? We could use the __stack_high / __stack_low globals for the else case I think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea was to fill these fields in main thread struct and handle everything the same way. Otherwise this would need to duplicate the logic for getting stack bounds, fallback to __heap_base, etc...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced only else block.

return ENOSYS;
#endif
}
return 0;
}