Skip to content
Closed
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
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,9 @@ file(GLOB PHOTON_SRC RELATIVE "${PROJECT_SOURCE_DIR}"
if (APPLE)
list(APPEND PHOTON_SRC io/kqueue.cpp)
else ()
file(GLOB CACHE_SRC
file(GLOB CACHE_SRC
fs/cache/*.cpp
fs/cache/full_file_cache/*.cpp
fs/cache/full_file_cache/*.cpp
fs/cache/persistent_cache/*.cpp
)
list(APPEND PHOTON_SRC
Expand Down
2 changes: 2 additions & 0 deletions photon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ static int init_event_engine(uint64_t engine, uint64_t flags, const PhotonOption
int __photon_init(uint64_t event_engine, uint64_t io_engine, const PhotonOptions& options) {
if (options.use_pooled_stack_allocator) {
use_pooled_stack_allocator();
} else {
use_default_stack_allocator();
Copy link
Collaborator

Choose a reason for hiding this comment

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

each vcpu will call photon_init, and use_pooled_stack_allocator is a global config.
This change may leads to user set-up pooled-stack-allocator and then unset. (by initialize another vcpu without setting use_pooled_stack_allocator. That is highly risky.

}
if (options.bypass_threadpool) {
set_bypass_threadpool(true);
Expand Down
20 changes: 18 additions & 2 deletions thread/stack-allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ limitations under the License.
#include <linux/mman.h>
#endif
#include <errno.h>
#include <mutex>
#include <photon/common/alog.h>
#include <photon/common/utility.h>
#include <photon/thread/arch.h>
#include <photon/thread/thread.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
Expand All @@ -29,6 +31,8 @@ limitations under the License.

namespace photon {

static std::once_flag init_once_flag;

template <size_t MIN_ALLOCATION_SIZE = 4UL * 1024,
size_t MAX_ALLOCATION_SIZE = 64UL * 1024 * 1024>
class PooledStackAllocator {
Expand Down Expand Up @@ -169,8 +173,13 @@ size_t pooled_stack_trim_threshold(size_t x) {
return get_pooled_stack_allocator().threshold(x);
}

size_t pooled_stack_trim_current_vcpu(size_t keep_size);
size_t pooled_stack_trim_threshold(size_t x);
void use_pooled_stack_allocator() {
get_pooled_stack_allocator();
std::call_once(init_once_flag, [] {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since it is a one-way setter and always put same value, is it really need to use a std::call_once?

photon::set_thread_stack_allocator({&pooled_stack_alloc, nullptr},
{&pooled_stack_dealloc, nullptr});
});
}

void* default_photon_thread_stack_alloc(void*, size_t stack_size) {
char* ptr = nullptr;
Expand All @@ -193,4 +202,11 @@ void default_photon_thread_stack_dealloc(void*, void* ptr, size_t size) {
free(ptr);
}

void use_default_stack_allocator() {
std::call_once(init_once_flag, [] {
photon::set_thread_stack_allocator({&default_photon_thread_stack_alloc, nullptr},
{&default_photon_thread_stack_dealloc, nullptr});
});
}

} // namespace photon
30 changes: 11 additions & 19 deletions thread/stack-allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,25 @@ limitations under the License.
#include <photon/thread/thread.h>
#include <stddef.h>

// Set photon allocator/deallocator for photon thread stack.
// This is a hook for thread allocation, both alloc and dealloc.
// Helps user to do more works like mark GC while allocating

namespace photon {

// Set photon allocator/deallocator for photon thread stack
// this is a hook for thread allocation, both alloc and dealloc
// helps user to do more works like mark GC while allocating
void* default_photon_thread_stack_alloc(void*, size_t stack_size);
void default_photon_thread_stack_dealloc(void*, void* stack_ptr,
size_t stack_size);
// A memory aligned allocator with stack-overflow protection.
// This is the default option. No need to set explicitly.
void use_default_stack_allocator();

// Threadlocal Pooled stack allocator
// better performance, and keep thread safe
void* pooled_stack_alloc(void*, size_t stack_size);
void pooled_stack_dealloc(void*, void* stack_ptr, size_t stack_size);
// Thread-local Pooled stack allocator.
// Better performance, and keep thread safe.
void use_pooled_stack_allocator();

// Free memory in pooled stack allocator till in-pool memory size less than
// `keep_size` for current vcpu
size_t pooled_stack_trim_current_vcpu(size_t keep_size);

// Pooled stack allocator set keep-in-pool size
size_t pooled_stack_trim_threshold(size_t threshold);

void set_photon_thread_stack_allocator(
Delegate<void*, size_t> photon_thread_alloc = {
&default_photon_thread_stack_alloc, nullptr},
Delegate<void, void*, size_t> photon_thread_dealloc = {
&default_photon_thread_stack_dealloc, nullptr});
inline void use_pooled_stack_allocator() {
set_photon_thread_stack_allocator({&pooled_stack_alloc, nullptr},
{&pooled_stack_dealloc, nullptr});
}
} // namespace photon
18 changes: 9 additions & 9 deletions thread/thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,8 @@ namespace photon
}
};

static Delegate<void*, size_t> photon_thread_alloc(
&default_photon_thread_stack_alloc, nullptr);
static Delegate<void, void*, size_t> photon_thread_dealloc(
&default_photon_thread_stack_dealloc, nullptr);
static Delegate<void*, size_t> photon_thread_alloc;
static Delegate<void, void*, size_t> photon_thread_dealloc;

struct vcpu_t;
struct thread;
Expand Down Expand Up @@ -2095,6 +2093,10 @@ R"(
}

int vcpu_init(uint64_t flags) {
if (unlikely(!photon_thread_alloc || !photon_thread_dealloc)) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

The only problem is here:
once vcpu_init called in a global constructor, it might be called before photon_thread_alloc construct or library load.

that may cause delegate photon_thread_alloc become an empty delegate and unable to be called, result in allocation failure and segment fault.

// For some test cases that don't use photon::init
use_default_stack_allocator();
}
uint64_t FLAGS = VCPU_ENABLE_ACTIVE_WORK_STEALING |
VCPU_ENABLE_PASSIVE_WORK_STEALING;
if (unlikely(flags & ~FLAGS))
Expand Down Expand Up @@ -2148,11 +2150,9 @@ R"(
CURRENT->stackful_free(ptr);
}

void set_photon_thread_stack_allocator(
Delegate<void *, size_t> _photon_thread_alloc,
Delegate<void, void *, size_t> _photon_thread_dealloc) {
photon_thread_alloc = _photon_thread_alloc;
photon_thread_dealloc = _photon_thread_dealloc;
void set_thread_stack_allocator(Delegate<void *, size_t> alloc, Delegate<void, void *, size_t> dealloc) {
photon_thread_alloc = alloc;
photon_thread_dealloc = dealloc;
}

extern "C" {
Expand Down
2 changes: 2 additions & 0 deletions thread/thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,8 @@ namespace photon
// helps allocating when using hybrid C++20 style coroutine
void* stackful_malloc(size_t size);
void stackful_free(void* ptr);

void set_thread_stack_allocator(Delegate<void*, size_t> alloc, Delegate<void, void*, size_t> dealloc);
};

/*
Expand Down
Loading