mirror of
https://github.com/scylladb/scylladb.git
synced 2026-05-01 21:55:50 +00:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user