posix: posix_thread: allocate stack manually

Otherwise, the stack is allocated on the creating thread and destroyed
on the created thread, which we don't support.
This commit is contained in:
Avi Kivity
2014-10-05 18:05:38 +03:00
parent 08706fcc6d
commit 50c4dcbd5f
2 changed files with 56 additions and 3 deletions

View File

@@ -3,6 +3,7 @@
*/
#include "posix.hh"
#include "align.hh"
#include <sys/mman.h>
void mmap_deleter::operator()(void* ptr) const {
@@ -21,8 +22,34 @@ void* posix_thread::start_routine(void* arg) {
return nullptr;
}
posix_thread::posix_thread(std::function<void ()> func) : _func(std::make_unique<std::function<void ()>>(std::move(func))) {
auto r = pthread_create(&_pthread, nullptr,
posix_thread::posix_thread(std::function<void ()> func)
: posix_thread(attr{}, std::move(func)) {
}
posix_thread::posix_thread(attr a, std::function<void ()> func)
: _func(std::make_unique<std::function<void ()>>(std::move(func))) {
pthread_attr_t pa;
auto r = pthread_attr_init(&pa);
if (r) {
throw std::system_error(r, std::system_category());
}
auto stack_size = a._stack_size.size;
if (!stack_size) {
stack_size = 2 << 20;
}
// allocate guard area as well
_stack = mmap_anonymous(nullptr, stack_size + (4 << 20),
PROT_NONE, MAP_PRIVATE | MAP_NORESERVE);
auto stack_start = align_up(_stack.get() + 1, 2 << 20);
mmap_area real_stack = mmap_anonymous(stack_start, stack_size,
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_STACK);
real_stack.release(); // protected by @_stack
::madvise(stack_start, stack_size, MADV_HUGEPAGE);
r = pthread_attr_setstack(&pa, stack_start, stack_size);
if (r) {
throw std::system_error(r, std::system_category());
}
r = pthread_create(&_pthread, &pa,
&posix_thread::start_routine, _func.get());
if (r) {
throw std::system_error(r, std::system_category());
@@ -30,7 +57,8 @@ posix_thread::posix_thread(std::function<void ()> func) : _func(std::make_unique
}
posix_thread::posix_thread(posix_thread&& x)
: _func(std::move(x._func)), _pthread(x._pthread), _valid(x._valid) {
: _func(std::move(x._func)), _pthread(x._pthread), _valid(x._valid)
, _stack(std::move(x._stack)) {
x._valid = false;
}

View File

@@ -195,17 +195,42 @@ using mmap_area = std::unique_ptr<char[], mmap_deleter>;
mmap_area mmap_anonymous(void* addr, size_t length, int prot, int flags);
class posix_thread {
public:
class attr;
private:
// must allocate, since this class is moveable
std::unique_ptr<std::function<void ()>> _func;
pthread_t _pthread;
bool _valid = true;
mmap_area _stack;
private:
static void* start_routine(void* arg);
public:
posix_thread(std::function<void ()> func);
posix_thread(attr a, std::function<void ()> func);
posix_thread(posix_thread&& x);
~posix_thread();
void join();
public:
class attr {
public:
struct stack_size { size_t size = 0; };
attr() = default;
template <typename... A>
attr(A... a) {
set(std::forward<A>(a)...);
}
void set() {}
template <typename A, typename... Rest>
void set(A a, Rest... rest) {
set(std::forward<A>(a));
set(std::forward<Rest>(rest)...);
}
void set(stack_size ss) { _stack_size = ss; }
private:
stack_size _stack_size;
friend class posix_thread;
};
};