📄 lcoco.c
字号:
#define COCO_MAIN_PARAM \ int _a, int _b, int _c, int _d, int _e, int _f, int _g, int _h, lua_State *L#if defined(__MACH__) && defined(_BSD_PPC_SETJMP_H_) /* ppc32-macosx */#define COCO_PATCHCTX(coco, buf, func, stack, a0) \ buf[21] = (int)(func); \ buf[0] = (int)(stack); \ stack[6+8] = (size_t)(a0);#endif#elif (defined(MIPS) || defined(MIPSEL) || defined(__mips)) && \ _MIPS_SIM == _MIPS_SIM_ABI32 && !defined(__mips_eabi)/* Stack layout for o32 ABI. */#define COCO_STACKADJUST 8#define COCO_MAIN_PARAM int _a, int _b, int _c, int _d, lua_State *L#if __GLIBC__ == 2 || defined(__UCLIBC__) /* mips32-linux-glibc2 */#define COCO_PATCHCTX(coco, buf, func, stack, a0) \ buf->__jmpbuf->__pc = (func); /* = t9 in _longjmp. Reqd. for -mabicalls. */ \ buf->__jmpbuf->__sp = (stack); \ buf->__jmpbuf->__fp = (void *)0; \ stack[4] = (size_t)(a0);#endif#elif defined(__arm__) || defined(__ARM__)#if __GLIBC__ == 2 || defined(__UCLIBC__) /* arm-linux-glibc2 */#define COCO_PATCHCTX(coco, buf, func, stack, a0) \ buf->__jmpbuf[__JMP_BUF_SP+1] = (int)(func); /* pc */ \ buf->__jmpbuf[__JMP_BUF_SP] = (int)(stack); /* sp */ \ buf->__jmpbuf[__JMP_BUF_SP-1] = 0; /* fp */ \ stack[0] = (size_t)(a0);#define COCO_STACKADJUST 2#define COCO_MAIN_PARAM int _a, int _b, int _c, int _d, lua_State *L#endif#endif /* arch check */#ifdef COCO_PATCHCTX#define COCO_CTX jmp_buf#define COCO_MAKECTX(coco, buf, func, stack, a0) \ _setjmp(buf); COCO_PATCHCTX(coco, buf, func, stack, a0)#define COCO_SWITCH(from, to) if (!_setjmp(from)) _longjmp(to, 1);#endif#endif /* !defined(COCO_MAKECTX) */#endif /* !defined(COCO_USE_UCONTEXT) *//* ------------------------------------------------------------------------ *//* Use inline asm or _setjmp/_longjmp if available. */#ifdef COCO_MAKECTX#ifndef COCO_STACKADJUST#define COCO_STACKADJUST 1#endif#define COCO_FILL(coco, NL, mainfunc) \{ /* Include the return address to get proper stack alignment. */ \ size_t *stackptr = &((size_t *)coco)[-COCO_STACKADJUST]; \ COCO_MAKECTX(coco, coco->ctx, mainfunc, stackptr, NL) \}/* ------------------------------------------------------------------------ *//* Else fallback to ucontext. Slower, because it saves/restores signals. */#else /* !defined(COCO_MAKECTX) */#include <ucontext.h>#define COCO_CTX ucontext_t/* Ugly workaround for makecontext() deficiencies on 64 bit CPUs. *//* Note that WIN64 (which is LLP64) never comes here. See above. */#if defined(__LP64__) || defined(_LP64) || INT_MAX != LONG_MAX/* 64 bit CPU: split the pointer into two 32 bit ints. */#define COCO_MAIN_PARAM unsigned int lo, unsigned int hi#define COCO_MAIN_GETL \ lua_State *L = (lua_State *)((((unsigned long)hi)<<32)+(unsigned long)lo);#define COCO_MAKECTX(coco, NL, mainfunc) \ makecontext(&coco->ctx, mainfunc, 2, \ (int)(ptrdiff_t)NL, (int)((ptrdiff_t)NL>>32));#else/* 32 bit CPU: a pointer fits into an int. */#define COCO_MAKECTX(coco, NL, mainfunc) \ makecontext(&coco->ctx, mainfunc, 1, (int)NL);#endif#define COCO_FILL(coco, NL, mainfunc) \ getcontext(&coco->ctx); \ coco->ctx.uc_link = NULL; /* We never exit from coco_main. */ \ coco->ctx.uc_stack.ss_sp = coco->allocptr; \ coco->ctx.uc_stack.ss_size = (char *)coco - (char *)(coco->allocptr); \ COCO_MAKECTX(coco, NL, mainfunc)#define COCO_SWITCH(from, to) swapcontext(&(from), &(to));#endif /* !defined(COCO_MAKECTX) *//* Common code for inline asm/setjmp/ucontext to allocate/free the stack. */struct coco_State {#ifdef COCO_STATE_HEAD COCO_STATE_HEAD#endif COCO_CTX ctx; /* Own context. */ COCO_CTX back; /* Context to switch back to. */ void *allocptr; /* Pointer to allocated memory. */ int allocsize; /* Size of allocated memory. */ int nargs; /* Number of arguments to pass. */ STACK_VGID /* Optional valgrind stack id. See above. */};typedef void (*coco_MainFunc)(void);/* Put the Coco state at the end and align it downwards. */#define ALIGNED_END(p, s, t) \ ((t *)(((char *)0) + ((((char *)(p)-(char *)0)+(s)-sizeof(t)) & -16)))/* TODO: use mmap. */#define COCO_NEW(OL, NL, cstacksize, mainfunc) \{ \ void *ptr = luaM_malloc(OL, cstacksize); \ coco_State *coco = ALIGNED_END(ptr, cstacksize, coco_State); \ STACK_REG(coco, ptr, cstacksize) \ coco->allocptr = ptr; \ coco->allocsize = cstacksize; \ COCO_FILL(coco, NL, mainfunc) \ L2COCO(NL) = coco; \}#define COCO_FREE(L) \ STACK_DEREG(L2COCO(L)) \ luaM_freemem(L, L2COCO(L)->allocptr, L2COCO(L)->allocsize); \ L2COCO(L) = NULL;#define COCO_JUMPIN(coco) COCO_SWITCH(coco->back, coco->ctx)#define COCO_JUMPOUT(coco) COCO_SWITCH(coco->ctx, coco->back)#endif /* !COCO_USE_FIBERS *//* ------------------------------------------------------------------------ */#ifndef COCO_MIN_CSTACKSIZE#define COCO_MIN_CSTACKSIZE (32768+4096)#endif/* Don't use multiples of 64K to avoid D-cache aliasing conflicts. */#ifndef COCO_DEFAULT_CSTACKSIZE#define COCO_DEFAULT_CSTACKSIZE (65536-4096)#endifstatic int defaultcstacksize = COCO_DEFAULT_CSTACKSIZE;/* Start the Lua or C function. */static void coco_start(lua_State *L, void *ud){ if (luaD_precall(L, (StkId)ud, LUA_MULTRET) == PCRLUA) luaV_execute(L, L->ci - L->base_ci);}#ifndef COCO_MAIN_PARAM#define COCO_MAIN_PARAM lua_State *L#endif#ifndef COCO_MAIN_DECL#define COCO_MAIN_DECL#endif/* Toplevel function for the new coroutine stack. Never exits. */static void COCO_MAIN_DECL coco_main(COCO_MAIN_PARAM){#ifdef COCO_MAIN_GETL COCO_MAIN_GETL#endif coco_State *coco = L2COCO(L); for (;;) { L->status = luaD_rawrunprotected(L, coco_start, L->top - (coco->nargs+1)); if (L->status != 0) luaD_seterrorobj(L, L->status, L->top); COCO_JUMPOUT(coco) }}/* Add a C stack to a coroutine. */lua_State *lua_newcthread(lua_State *OL, int cstacksize){ lua_State *NL = lua_newthread(OL); if (cstacksize < 0) return NL; if (cstacksize == 0) cstacksize = defaultcstacksize; else if (cstacksize < COCO_MIN_CSTACKSIZE) cstacksize = COCO_MIN_CSTACKSIZE; cstacksize &= -16; COCO_NEW(OL, NL, cstacksize, ((coco_MainFunc)(coco_main))) return NL;}/* Free the C stack of a coroutine. Called from lstate.c. */void luaCOCO_free(lua_State *L){ COCO_FREE(L)}/* Resume a coroutine with a C stack. Called from ldo.c. */int luaCOCO_resume(lua_State *L, int nargs){ coco_State *coco = L2COCO(L); coco->nargs = nargs; COCO_JUMPIN(coco)#ifndef COCO_DISABLE_EARLY_FREE if (L->status != LUA_YIELD) { COCO_FREE(L) }#endif return L->status;}/* Yield from a coroutine with a C stack. Called from ldo.c. */int luaCOCO_yield(lua_State *L){ coco_State *coco = L2COCO(L); L->status = LUA_YIELD; COCO_JUMPOUT(coco) L->status = 0; { StkId base = L->top - coco->nargs; StkId rbase = L->base; if (rbase < base) { /* Need to move args down? */ while (base < L->top) setobjs2s(L, rbase++, base++); L->top = rbase; } } L->base = L->ci->base; /* Restore invariant. */ return coco->nargs;}/* Get/set the default C stack size. */int luaCOCO_cstacksize(int cstacksize){ int oldsz = defaultcstacksize; if (cstacksize >= 0) { if (cstacksize == 0) cstacksize = COCO_DEFAULT_CSTACKSIZE; else if (cstacksize < COCO_MIN_CSTACKSIZE) cstacksize = COCO_MIN_CSTACKSIZE; defaultcstacksize = cstacksize; } return oldsz;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -