You've already forked qlg.tsgz.moe
Init Repo
This commit is contained in:
182
vendor/swoole/src/coroutine/base.cc
vendored
Executable file
182
vendor/swoole/src/coroutine/base.cc
vendored
Executable file
@@ -0,0 +1,182 @@
|
||||
#include "coroutine.h"
|
||||
#include "context.h"
|
||||
#include <string>
|
||||
|
||||
/* allocate cid for coroutine */
|
||||
typedef struct cidmap
|
||||
{
|
||||
uint32_t nr_free;
|
||||
char page[65536];
|
||||
} cidmap_t;
|
||||
|
||||
using namespace swoole;
|
||||
|
||||
struct coroutine_s
|
||||
{
|
||||
public:
|
||||
Context ctx;
|
||||
int cid;
|
||||
coroutine_s(int _cid, size_t stack_size, coroutine_func_t fn, void* private_data) :
|
||||
ctx(stack_size, fn, private_data)
|
||||
{
|
||||
cid = _cid;
|
||||
}
|
||||
};
|
||||
|
||||
static struct
|
||||
{
|
||||
int stack_size;
|
||||
int current_cid;
|
||||
int previous_cid;
|
||||
struct coroutine_s *coroutines[MAX_CORO_NUM_LIMIT + 1];
|
||||
coroutine_close_t onClose;
|
||||
} swCoroG =
|
||||
{ SW_DEFAULT_C_STACK_SIZE, -1, -1,
|
||||
{ NULL, }, NULL };
|
||||
|
||||
/* 1 <= cid <= 524288 */
|
||||
static cidmap_t cidmap =
|
||||
{ MAX_CORO_NUM_LIMIT,
|
||||
{ 0 } };
|
||||
|
||||
static int last_cid = -1;
|
||||
|
||||
static inline int test_and_set_bit(int cid, void *addr)
|
||||
{
|
||||
uint32_t mask = 1U << (cid & 0x1f);
|
||||
uint32_t *p = ((uint32_t*) addr) + (cid >> 5);
|
||||
uint32_t old = *p;
|
||||
|
||||
*p = old | mask;
|
||||
|
||||
return (old & mask) == 0;
|
||||
}
|
||||
|
||||
static inline void clear_bit(int cid, void *addr)
|
||||
{
|
||||
uint32_t mask = 1U << (cid & 0x1f);
|
||||
uint32_t *p = ((uint32_t*) addr) + (cid >> 5);
|
||||
uint32_t old = *p;
|
||||
|
||||
*p = old & ~mask;
|
||||
}
|
||||
|
||||
/* find next free cid */
|
||||
static inline int find_next_zero_bit(void *addr, int cid)
|
||||
{
|
||||
uint32_t *p;
|
||||
uint32_t mask;
|
||||
int mark = cid;
|
||||
|
||||
cid++;
|
||||
cid &= 0x7ffff;
|
||||
while (cid != mark)
|
||||
{
|
||||
mask = 1U << (cid & 0x1f);
|
||||
p = ((uint32_t*) addr) + (cid >> 5);
|
||||
|
||||
if ((~(*p) & mask))
|
||||
{
|
||||
break;
|
||||
}
|
||||
++cid;
|
||||
cid &= 0x7fff;
|
||||
}
|
||||
|
||||
return cid;
|
||||
}
|
||||
|
||||
static inline int alloc_cidmap()
|
||||
{
|
||||
int cid;
|
||||
|
||||
if (cidmap.nr_free == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
cid = find_next_zero_bit(&cidmap.page, last_cid);
|
||||
if (test_and_set_bit(cid, &cidmap.page))
|
||||
{
|
||||
--cidmap.nr_free;
|
||||
last_cid = cid;
|
||||
return cid + 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline void free_cidmap(int cid)
|
||||
{
|
||||
cid--;
|
||||
cidmap.nr_free++;
|
||||
clear_bit(cid, &cidmap.page);
|
||||
}
|
||||
|
||||
int coroutine_create(coroutine_func_t fn, void* args)
|
||||
{
|
||||
int cid = alloc_cidmap();
|
||||
if (unlikely(cid == -1))
|
||||
{
|
||||
swWarn("alloc_cidmap failed");
|
||||
return CORO_LIMIT;
|
||||
}
|
||||
|
||||
coroutine_t *co = new coroutine_t(cid, swCoroG.stack_size, fn, args);
|
||||
swCoroG.coroutines[cid] = co;
|
||||
swCoroG.previous_cid = swCoroG.current_cid;
|
||||
swCoroG.current_cid = cid;
|
||||
co->ctx.SwapIn();
|
||||
if (co->ctx.end)
|
||||
{
|
||||
if (swCoroG.onClose)
|
||||
{
|
||||
swCoroG.onClose();
|
||||
}
|
||||
coroutine_release(co);
|
||||
}
|
||||
return cid;
|
||||
}
|
||||
|
||||
void coroutine_yield(coroutine_t *co)
|
||||
{
|
||||
swCoroG.current_cid = swCoroG.previous_cid;
|
||||
co->ctx.SwapOut();
|
||||
}
|
||||
|
||||
void coroutine_resume(coroutine_t *co)
|
||||
{
|
||||
swCoroG.previous_cid = swCoroG.current_cid;
|
||||
swCoroG.current_cid = co->cid;
|
||||
co->ctx.SwapIn();
|
||||
if (co->ctx.end)
|
||||
{
|
||||
if (swCoroG.onClose)
|
||||
{
|
||||
swCoroG.onClose();
|
||||
}
|
||||
coroutine_release(co);
|
||||
}
|
||||
}
|
||||
|
||||
void coroutine_release(coroutine_t *co)
|
||||
{
|
||||
free_cidmap(co->cid);
|
||||
swCoroG.coroutines[co->cid] = NULL;
|
||||
delete co;
|
||||
}
|
||||
|
||||
void coroutine_set_close(coroutine_close_t func)
|
||||
{
|
||||
swCoroG.onClose = func;
|
||||
}
|
||||
|
||||
coroutine_t* coroutine_get_by_id(int cid)
|
||||
{
|
||||
return swCoroG.coroutines[cid];
|
||||
}
|
||||
|
||||
int coroutine_get_cid()
|
||||
{
|
||||
return swCoroG.current_cid;
|
||||
}
|
||||
76
vendor/swoole/src/coroutine/boost.cc
vendored
Executable file
76
vendor/swoole/src/coroutine/boost.cc
vendored
Executable file
@@ -0,0 +1,76 @@
|
||||
#include "swoole.h"
|
||||
#include "context.h"
|
||||
|
||||
#if USE_BOOST_CONTEXT
|
||||
|
||||
using namespace swoole;
|
||||
|
||||
Context::Context(size_t stack_size, coroutine_func_t fn, void* private_data) :
|
||||
fn_(fn), stack_size_(stack_size), private_data_(private_data)
|
||||
{
|
||||
BOOST_ASSERT(boost::context::stack_traits::minimum_size() <= stack_size_);
|
||||
BOOST_ASSERT(
|
||||
boost::context::stack_traits::is_unbounded()
|
||||
|| (boost::context::stack_traits::maximum_size() >= stack_size_));
|
||||
|
||||
protect_page_ = 0;
|
||||
end = false;
|
||||
swap_ctx_ = NULL;
|
||||
|
||||
stack_ = (char*) sw_malloc(stack_size_);
|
||||
swDebug("alloc stack: size=%u, ptr=%p.", stack_size_, stack_);
|
||||
|
||||
void* sp = (void*) ((char*) stack_ + stack_size_);
|
||||
#ifdef USE_VALGRIND
|
||||
valgrind_stack_id = VALGRIND_STACK_REGISTER(sp, stack_);
|
||||
#endif
|
||||
ctx_ = boost::context::make_fcontext(sp, stack_size_, (void (*)(intptr_t))&context_func);
|
||||
|
||||
uint32_t protect_page = get_protect_stack_page();
|
||||
if (protect_page)
|
||||
{
|
||||
if (protect_stack(stack_, stack_size_, protect_page))
|
||||
{
|
||||
protect_page_ = protect_page;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Context::~Context()
|
||||
{
|
||||
if (stack_)
|
||||
{
|
||||
swDebug("free stack: ptr=%p", stack_);
|
||||
if (protect_page_)
|
||||
{
|
||||
unprotect_stack(stack_, protect_page_);
|
||||
}
|
||||
#if defined(USE_VALGRIND)
|
||||
VALGRIND_STACK_DEREGISTER(valgrind_stack_id);
|
||||
#endif
|
||||
sw_free(stack_);
|
||||
stack_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool Context::SwapIn()
|
||||
{
|
||||
boost::context::jump_fcontext(&swap_ctx_, ctx_, (intptr_t) this, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Context::SwapOut()
|
||||
{
|
||||
boost::context::jump_fcontext(&ctx_, swap_ctx_, (intptr_t) this, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Context::context_func(void *arg)
|
||||
{
|
||||
Context* _this = (Context*) arg;
|
||||
_this->fn_(_this->private_data_);
|
||||
_this->end = true;
|
||||
_this->SwapOut();
|
||||
}
|
||||
|
||||
#endif
|
||||
71
vendor/swoole/src/coroutine/context.cc
vendored
Executable file
71
vendor/swoole/src/coroutine/context.cc
vendored
Executable file
@@ -0,0 +1,71 @@
|
||||
#include "swoole.h"
|
||||
#include "context.h"
|
||||
|
||||
#ifndef SW_NO_USE_ASM_CONTEXT
|
||||
|
||||
using namespace swoole;
|
||||
|
||||
Context::Context(size_t stack_size, coroutine_func_t fn, void* private_data) :
|
||||
fn_(fn), stack_size_(stack_size), private_data_(private_data)
|
||||
{
|
||||
protect_page_ = 0;
|
||||
end = false;
|
||||
swap_ctx_ = NULL;
|
||||
|
||||
stack_ = (char*) sw_malloc(stack_size_);
|
||||
swDebug("alloc stack: size=%u, ptr=%p.", stack_size_, stack_);
|
||||
|
||||
void* sp = (void*) ((char*) stack_ + stack_size_);
|
||||
#ifdef USE_VALGRIND
|
||||
valgrind_stack_id = VALGRIND_STACK_REGISTER(sp, stack_);
|
||||
#endif
|
||||
ctx_ = make_fcontext(sp, stack_size_, (void (*)(intptr_t))&context_func);
|
||||
|
||||
uint32_t protect_page = get_protect_stack_page();
|
||||
if (protect_page)
|
||||
{
|
||||
if (protect_stack(stack_, stack_size_, protect_page))
|
||||
{
|
||||
protect_page_ = protect_page;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Context::~Context()
|
||||
{
|
||||
if (stack_)
|
||||
{
|
||||
swDebug("free stack: ptr=%p", stack_);
|
||||
if (protect_page_)
|
||||
{
|
||||
unprotect_stack(stack_, protect_page_);
|
||||
}
|
||||
#if defined(USE_VALGRIND)
|
||||
VALGRIND_STACK_DEREGISTER(valgrind_stack_id);
|
||||
#endif
|
||||
sw_free(stack_);
|
||||
stack_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool Context::SwapIn()
|
||||
{
|
||||
jump_fcontext(&swap_ctx_, ctx_, (intptr_t) this, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Context::SwapOut()
|
||||
{
|
||||
jump_fcontext(&ctx_, swap_ctx_, (intptr_t) this, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Context::context_func(void *arg)
|
||||
{
|
||||
Context *_this = (Context *) arg;
|
||||
_this->fn_(_this->private_data_);
|
||||
_this->end = true;
|
||||
_this->SwapOut();
|
||||
}
|
||||
|
||||
#endif
|
||||
79
vendor/swoole/src/coroutine/ucontext.cc
vendored
Executable file
79
vendor/swoole/src/coroutine/ucontext.cc
vendored
Executable file
@@ -0,0 +1,79 @@
|
||||
#include "swoole.h"
|
||||
#include "context.h"
|
||||
|
||||
#if USE_UCONTEXT
|
||||
|
||||
using namespace swoole;
|
||||
|
||||
Context::Context(size_t stack_size, coroutine_func_t fn, void* private_data) :
|
||||
fn_(fn), stack_size_(stack_size), private_data_(private_data)
|
||||
{
|
||||
if (-1 == getcontext(&ctx_))
|
||||
{
|
||||
swoole_throw_error(SW_ERROR_CO_GETCONTEXT_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
protect_page_ = 0;
|
||||
end = false;
|
||||
|
||||
stack_ = (char*) sw_malloc(stack_size);
|
||||
swDebug("alloc stack: size=%lu, ptr=%p", stack_size, stack_);
|
||||
|
||||
ctx_.uc_stack.ss_sp = stack_;
|
||||
ctx_.uc_stack.ss_size = stack_size;
|
||||
ctx_.uc_link = NULL;
|
||||
|
||||
#if defined(USE_VALGRIND)
|
||||
valgrind_stack_id = VALGRIND_STACK_REGISTER(static_cast<char *>(stack_) + stack_size, stack_);
|
||||
#endif
|
||||
|
||||
makecontext(&ctx_, (void (*)(void))&context_func, 1, this);
|
||||
|
||||
uint32_t protect_page = get_protect_stack_page();
|
||||
if (protect_page)
|
||||
{
|
||||
if (protect_stack(stack_, stack_size, protect_page))
|
||||
{
|
||||
protect_page_ = protect_page;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Context::~Context()
|
||||
{
|
||||
if (stack_)
|
||||
{
|
||||
swDebug("free stack: ptr=%p", stack_);
|
||||
if (protect_page_)
|
||||
{
|
||||
unprotect_stack(stack_, protect_page_);
|
||||
}
|
||||
|
||||
#if defined(USE_VALGRIND)
|
||||
VALGRIND_STACK_DEREGISTER(valgrind_stack_id);
|
||||
#endif
|
||||
sw_free(stack_);
|
||||
stack_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool Context::SwapIn()
|
||||
{
|
||||
return 0 == swapcontext(&swap_ctx_, &ctx_);
|
||||
}
|
||||
|
||||
bool Context::SwapOut()
|
||||
{
|
||||
return 0 == swapcontext(&ctx_, &swap_ctx_);
|
||||
}
|
||||
|
||||
void Context::context_func(void *arg)
|
||||
{
|
||||
Context *_this = (Context *) arg;
|
||||
_this->fn_(_this->private_data_);
|
||||
_this->end = true;
|
||||
_this->SwapOut();
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user