110 lines
2.7 KiB
C++
Executable File
110 lines
2.7 KiB
C++
Executable File
#pragma once
|
|
|
|
#ifdef SW_NO_USE_ASM_CONTEXT
|
|
#ifdef HAVE_BOOST_CONTEXT
|
|
#define USE_BOOST_CONTEXT 1
|
|
#include <boost/context/all.hpp>
|
|
#else
|
|
#define USE_UCONTEXT 1
|
|
#include <ucontext.h>
|
|
#endif
|
|
#else
|
|
#include "asm_context.h"
|
|
#endif
|
|
|
|
#ifdef HAVE_VALGRIND
|
|
#define USE_VALGRIND 0
|
|
#endif
|
|
|
|
#include "swoole.h"
|
|
#include "coroutine.h"
|
|
#include "error.h"
|
|
|
|
#if __linux__
|
|
#include <sys/mman.h>
|
|
#endif
|
|
|
|
#ifdef USE_VALGRIND
|
|
#include <valgrind/valgrind.h>
|
|
#endif
|
|
|
|
namespace swoole
|
|
{
|
|
//namespace start
|
|
static uint32_t& get_protect_stack_page()
|
|
{
|
|
static uint32_t protect_stack_page = 0;
|
|
return protect_stack_page;
|
|
}
|
|
|
|
static bool protect_stack(void *top, size_t stack_size, uint32_t page)
|
|
{
|
|
if (stack_size <= SwooleG.pagesize * (page + 1))
|
|
{
|
|
swoole_error_log(SW_LOG_ERROR, SW_ERROR_CO_PROTECT_STACK_FAILED, "getpagesize() failed.");
|
|
return false;
|
|
}
|
|
|
|
void *protect_page_addr = ((size_t) top & 0xfff) ? (void*) (((size_t) top & ~(size_t) 0xfff) + 0x1000) : top;
|
|
if (-1 == mprotect(protect_page_addr, SwooleG.pagesize * page, PROT_NONE))
|
|
{
|
|
swSysError("mprotect() failed: origin_addr:%p, align_addr:%p, page_size:%d, protect_page:%u.", top,
|
|
protect_page_addr, SwooleG.pagesize, page);
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
swDebug("origin_addr:%p, align_addr:%p, page_size:%d, protect_page:%u", top, protect_page_addr, page, SwooleG.pagesize);
|
|
return true;
|
|
}
|
|
}
|
|
static bool unprotect_stack(void *top, uint32_t page)
|
|
{
|
|
void *protect_page_addr = ((size_t) top & 0xfff) ? (void*) (((size_t) top & ~(size_t) 0xfff) + 0x1000) : top;
|
|
if (-1 == mprotect(protect_page_addr, SwooleG.pagesize * page, PROT_READ | PROT_WRITE))
|
|
{
|
|
swSysError("mprotect() failed: origin_addr:%p, align_addr:%p, page_size:%d, protect_page:%u.", top,
|
|
protect_page_addr, SwooleG.pagesize, page);
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
swDebug("origin_addr:%p, align_addr:%p, page_size:%d, protect_page:%u.", top, protect_page_addr, page, SwooleG.pagesize);
|
|
return true;
|
|
}
|
|
}
|
|
class Context
|
|
{
|
|
public:
|
|
Context(size_t stack_size, coroutine_func_t fn, void* private_data);
|
|
~Context();
|
|
bool SwapIn();
|
|
bool SwapOut();
|
|
static void context_func(void* arg);
|
|
public:
|
|
bool end;
|
|
|
|
private:
|
|
#ifdef USE_BOOST_CONTEXT
|
|
boost::context::fcontext_t ctx_;
|
|
boost::context::fcontext_t swap_ctx_;
|
|
#elif USE_UCONTEXT
|
|
ucontext_t swap_ctx_;
|
|
ucontext_t ctx_;
|
|
#else
|
|
fcontext_t ctx_;
|
|
fcontext_t swap_ctx_;
|
|
#endif
|
|
coroutine_func_t fn_;
|
|
char* stack_;
|
|
uint32_t stack_size_;
|
|
uint32_t protect_page_;
|
|
#ifdef USE_VALGRIND
|
|
uint32_t valgrind_stack_id;
|
|
#endif
|
|
void *private_data_;
|
|
};
|
|
//namespace end
|
|
}
|
|
|