Skip to content

Commit

Permalink
options/posix: implement stack searching in pthread_getattr_np()
Browse files Browse the repository at this point in the history
  • Loading branch information
Geertiebear committed Dec 21, 2021
1 parent caab1c2 commit 5022a50
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 2 deletions.
1 change: 1 addition & 0 deletions options/ansi/include/inttypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
#define SCNx32 "x"
#define SCNx64 "lx"
#define SCNxMAX "lx"
#define SCNxPTR "lx"

#define SCNd64 "ld"

Expand Down
2 changes: 2 additions & 0 deletions options/internal/include/mlibc/thread.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#pragma once

#include <mlibc/tcb.hpp>
#include <stdint.h>

namespace mlibc {

Tcb *get_current_tcb();
uintptr_t get_sp();

} // namespace mlibc
6 changes: 6 additions & 0 deletions options/internal/x86_64/thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,10 @@ Tcb *get_current_tcb() {
return reinterpret_cast<Tcb *>(ptr);
}

uintptr_t get_sp() {
uintptr_t rsp;
asm ("mov %%rsp, %0" : "=r"(rsp));
return rsp;
}

} // namespace mlibc
40 changes: 38 additions & 2 deletions options/posix/generic/pthread-stubs.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@

#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <inttypes.h>

#include <bits/ensure.h>
#include <frg/allocation.hpp>
Expand Down Expand Up @@ -188,11 +190,45 @@ int pthread_attr_setschedpolicy(pthread_attr_t *__restrict attr, int policy) {
return 0;
}

namespace {
void get_own_stackinfo(void **stack_addr, size_t *stack_size) {
auto fp = fopen("/proc/self/maps", "r");
if (!fp) {
mlibc::infoLogger() << "mlibc pthreads: /proc/self/maps does not exist! Producing incorrect"
" stack results!" << frg::endlog;
return;
}

char line[256];
auto sp = mlibc::get_sp();
while (fgets(line, 128, fp)) {
uintptr_t from, to;
if(sscanf(line, "%lx-%lx", &from, &to) != 2)
continue;
if (sp < to && sp > from) {
// We need to return the lowest byte of the stack.
*stack_addr = reinterpret_cast<void*>(from);
*stack_size = to - from;
fclose(fp);
return;
}
}

fclose(fp);
}
}

int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr) {
auto tcb = reinterpret_cast<Tcb*>(thread);
*attr = pthread_attr_t{};
attr->__mlibc_stacksize = tcb->stackSize;
attr->__mlibc_stackaddr = tcb->stackAddr;

if (!tcb->stackAddr || !tcb->stackSize) {
get_own_stackinfo(&attr->__mlibc_stackaddr, &attr->__mlibc_stacksize);
} else {
attr->__mlibc_stacksize = tcb->stackSize;
attr->__mlibc_stackaddr = tcb->stackAddr;
}

attr->__mlibc_guardsize = tcb->guardSize;
attr->__mlibc_detachstate = tcb->isJoinable ? PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED;
mlibc::infoLogger() << "pthread_getattr_np(): Implementation is incomplete!" << frg::endlog;
Expand Down
31 changes: 31 additions & 0 deletions tests/posix/pthread_attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,36 @@ static void test_stack() {
assert(new_size == stacksize);
}

static void *getattr_worker(void *arg) {
return NULL;
}

static void test_getattrnp() {
pthread_attr_t attr;
size_t stacksize = PTHREAD_STACK_MIN;
assert(!pthread_attr_init(&attr));
assert(!pthread_attr_setstacksize(&attr, stacksize));

pthread_t thread;
assert(!pthread_create(&thread, &attr, getattr_worker, NULL));
assert(!pthread_getattr_np(thread, &attr));
size_t other_stacksize;
assert(!pthread_attr_getstacksize(&attr, &other_stacksize));
assert(other_stacksize == stacksize);
assert(!pthread_join(thread, NULL));

pthread_t own_thread = pthread_self();
void *stack;
assert(!pthread_getattr_np(own_thread, &attr));
assert(!pthread_attr_getstack(&attr, &stack, &other_stacksize));
assert(stack);
assert(other_stacksize);
// Check that we can read from the highest byte returned.
// pthread_getattr_np() should return the lowest byte
// of the stack.
assert(!*(char*)(stack + other_stacksize - 1));
}

int main() {
test_detachstate();
test_stacksize();
Expand All @@ -140,4 +170,5 @@ int main() {
test_schedpolicy();
test_stackaddr();
test_stack();
test_getattrnp();
}

0 comments on commit 5022a50

Please sign in to comment.