Skip to content

Commit 1f31aa3

Browse files
committed
port luaCoco to xtensa architecture
1 parent 216b820 commit 1f31aa3

7 files changed

Lines changed: 336 additions & 24 deletions

File tree

app/lua/lapi.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -107,25 +107,20 @@ LUA_API int lua_checkstack (lua_State *L, int size) {
107107

108108

109109
LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
110-
int i;
110+
StkId f, t;
111111
if (from == to) return;
112112
lua_lock(to);
113113
api_checknelems(from, n);
114114
api_check(from, G(from) == G(to));
115115
api_check(from, to->ci->top - to->top >= n);
116-
from->top -= n;
117-
for (i = 0; i < n; i++) {
118-
setobj2s(to, to->top++, from->top + i);
119-
}
116+
f = from->top;
117+
t = to->top = to->top + n;
118+
while (--n >= 0) setobj2s(to, --t, --f);
119+
from->top = f;
120120
lua_unlock(to);
121121
}
122122

123123

124-
LUA_API void lua_setlevel (lua_State *from, lua_State *to) {
125-
to->nCcalls = from->nCcalls;
126-
}
127-
128-
129124
LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {
130125
lua_CFunction old;
131126
lua_lock(L);

app/lua/lbaselib.c

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
#include C_HEADER_STDLIB
1717
#include "lauxlib.h"
1818
#include "lualib.h"
19+
#ifndef COCO_DISABLE
20+
#include "lcoco.h"
21+
#endif
1922
#include "lrotable.h"
2023

2124

@@ -582,7 +585,6 @@ static int auxresume (lua_State *L, lua_State *co, int narg) {
582585
return -1; /* error flag */
583586
}
584587
lua_xmove(L, co, narg);
585-
lua_setlevel(L, co);
586588
status = lua_resume(co, narg);
587589
if (status == 0 || status == LUA_YIELD) {
588590
int nres = lua_gettop(co);
@@ -631,10 +633,27 @@ static int luaB_auxwrap (lua_State *L) {
631633
}
632634

633635

636+
#ifndef COCO_DISABLE
637+
static int luaB_cstacksize (lua_State *L)
638+
{
639+
lua_pushinteger(L, luaCOCO_cstacksize(luaL_optint(L, 1, -1)));
640+
return 1;
641+
}
642+
#endif
643+
644+
634645
static int luaB_cocreate (lua_State *L) {
646+
#ifdef COCO_DISABLE
635647
lua_State *NL = lua_newthread(L);
636648
luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
637649
"Lua function expected");
650+
#else
651+
int cstacksize = luaL_optint(L, 2, 0);
652+
lua_State *NL = lua_newcthread(L, cstacksize);
653+
luaL_argcheck(L, lua_isfunction(L, 1) &&
654+
(cstacksize >= 0 ? 1 : !lua_iscfunction(L, 1)),
655+
1, "Lua function expected");
656+
#endif
638657
lua_pushvalue(L, 1); /* move function to top */
639658
lua_xmove(L, NL, 1); /* move function from L to NL */
640659
return 1;
@@ -669,6 +688,9 @@ const LUA_REG_TYPE co_funcs[] = {
669688
{LSTRKEY("status"), LFUNCVAL(luaB_costatus)},
670689
{LSTRKEY("wrap"), LFUNCVAL(luaB_cowrap)},
671690
{LSTRKEY("yield"), LFUNCVAL(luaB_yield)},
691+
#ifndef COCO_DISABLE
692+
{LSTRKEY("cstacksize"), LFUNCVAL(luaB_cstacksize)},
693+
#endif
672694
{LNILKEY, LNILVAL}
673695
};
674696

@@ -714,6 +736,10 @@ LUALIB_API int luaopen_base (lua_State *L) {
714736
base_open(L);
715737
#if LUA_OPTIMIZE_MEMORY == 0
716738
luaL_register(L, LUA_COLIBNAME, co_funcs);
739+
#ifndef COCO_DISABLE
740+
lua_pushboolean(L, 1);
741+
lua_setfield(L, -2, "coco");
742+
#endif
717743
return 2;
718744
#else
719745
return 1;

app/lua/lcoco.h

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
** Lua/Coco glue.
3+
** Copyright (C) 2004-2009 Mike Pall. See copyright notice in lcoco.c
4+
*/
5+
6+
#ifndef lcoco_h
7+
#define lcoco_h
8+
9+
#define LUACOCO_VERSION "Coco 1.1.6"
10+
#define LUACOCO_VERSION_NUM 10106
11+
12+
/* Exported C API to add a C stack to a coroutine. */
13+
LUA_API lua_State *lua_newcthread(lua_State *L, int cstacksize);
14+
15+
/* Internal support routines. */
16+
LUAI_FUNC void luaCOCO_free(lua_State *L);
17+
LUAI_FUNC int luaCOCO_resume(lua_State *L, int nargs);
18+
LUAI_FUNC int luaCOCO_yield(lua_State *L);
19+
LUAI_FUNC int luaCOCO_cstacksize(int cstacksize);
20+
21+
/* Forward declaration. */
22+
typedef struct coco_State coco_State;
23+
24+
/* These are redefined below. */
25+
#undef LUAI_EXTRASPACE
26+
#undef luai_userstateopen
27+
/* luai_userstateclose unused */
28+
#undef luai_userstatethread
29+
#undef luai_userstatefree
30+
#undef luai_userstateresume
31+
#undef luai_userstateyield
32+
33+
/* Use Windows Fibers (Win98+). */
34+
#if defined(_WIN32)
35+
36+
/* Fibers allocate their own stack. The whole Coco state is in front of L. */
37+
struct coco_State {
38+
void *fib; /* Own fiber (if any). */
39+
void *back; /* Fiber to switch back to. */
40+
int nargs; /* Number of arguments to pass. */
41+
int dummy_align;
42+
};
43+
44+
#define L2COCO(L) (&((coco_State *)(L))[-1])
45+
#define LHASCOCO(L) (L2COCO(L)->fib)
46+
#define LUAI_EXTRASPACE sizeof(coco_State)
47+
#define luai_userstateopen(L) L2COCO(L)->fib = NULL
48+
#define luai_userstatethread(L,L1) L2COCO(L1)->fib = NULL
49+
#define COCO_USE_FIBERS
50+
51+
#else /* !defined(_WIN32) */
52+
53+
/* The Coco state depends on the context switch method used. See lcoco.c. */
54+
/* It's stored at the end of the stack. Only need a pointer in front of L. */
55+
#define L2COCO(L) (((coco_State **)(L))[-1])
56+
#define LHASCOCO(L) (L2COCO(L))
57+
/* This wastes some space on 32 bit systems, but gets better alignment. */
58+
#define LUAI_EXTRASPACE sizeof(LUAI_USER_ALIGNMENT_T)
59+
#define luai_userstateopen(L) L2COCO(L) = NULL
60+
#define luai_userstatethread(L,L1) L2COCO(L1) = NULL
61+
62+
#endif /* !defined(_WIN32) */
63+
64+
#define luai_userstatefree(L) if (LHASCOCO(L)) luaCOCO_free(L)
65+
#define luai_userstateresume(L, nargs) \
66+
if (LHASCOCO(L)) return luaCOCO_resume(L, nargs)
67+
#define luai_userstateyield(L, nresults) \
68+
do { if (LHASCOCO(L)) { \
69+
L->base = L->top - (nresults); /* Protect stack slots below. */ \
70+
return luaCOCO_yield(L); } } while (0)
71+
72+
#endif

app/lua/lcoco_xtensa.c

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
/*
2+
** Copyright (C) 2004-2009 Mike Pall. All rights reserved.
3+
**
4+
** Permission is hereby granted, free of charge, to any person obtaining
5+
** a copy of this software and associated documentation files (the
6+
** "Software"), to deal in the Software without restriction, including
7+
** without limitation the rights to use, copy, modify, merge, publish,
8+
** distribute, sublicense, and/or sell copies of the Software, and to
9+
** permit persons to whom the Software is furnished to do so, subject to
10+
** the following conditions:
11+
**
12+
** The above copyright notice and this permission notice shall be
13+
** included in all copies or substantial portions of the Software.
14+
**
15+
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16+
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17+
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18+
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19+
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20+
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21+
** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22+
**
23+
** [ MIT license: http://www.opensource.org/licenses/mit-license.php ]
24+
*/
25+
26+
/* Coco -- True C coroutines for Lua. http://luajit.org/coco.html */
27+
#ifndef COCO_DISABLE
28+
29+
#define lcoco_c
30+
#define LUA_CORE
31+
32+
#include "lua.h"
33+
34+
#include "lobject.h"
35+
#include "lstate.h"
36+
#include "ldo.h"
37+
#include "lvm.h"
38+
#include "lgc.h"
39+
40+
#define STACK_REG(coco, p, sz)
41+
#define STACK_DEREG(id)
42+
#define STACK_VGID
43+
44+
/* Try _setjmp/_longjmp with a patched jump buffer. */
45+
#include <setjmp.h>
46+
47+
// buf[0] is regsiter a0(return addr), buf[1] is regsiter a1(stack ptr)
48+
// see newlib-2.0.0/newlib/libc/machine/xtensa/setjmp.S
49+
#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
50+
buf[0] = (int)(func); \
51+
buf[1] = (int)(stack); \
52+
stack[0] = (size_t)(a0);
53+
54+
#ifdef COCO_PATCHCTX
55+
#define COCO_CTX jmp_buf
56+
#define COCO_MAKECTX(coco, buf, func, stack, a0) \
57+
setjmp(buf); COCO_PATCHCTX(coco, buf, func, stack, a0)
58+
#define COCO_SWITCH(from, to) if (!setjmp(from)) longjmp(to, 1);
59+
#endif
60+
61+
#ifndef COCO_STACKADJUST
62+
#define COCO_STACKADJUST 1
63+
#endif
64+
65+
#define COCO_FILL(coco, NL, mainfunc) \
66+
{ /* Include the return address to get proper stack alignment. */ \
67+
size_t *stackptr = &((size_t *)coco)[-COCO_STACKADJUST]; \
68+
COCO_MAKECTX(coco, coco->ctx, mainfunc, stackptr, NL) \
69+
}
70+
71+
/* Common code for inline asm/setjmp/ucontext to allocate/free the stack. */
72+
73+
struct coco_State {
74+
#ifdef COCO_STATE_HEAD
75+
COCO_STATE_HEAD
76+
#endif
77+
COCO_CTX ctx; /* Own context. */
78+
COCO_CTX back; /* Context to switch back to. */
79+
void *allocptr; /* Pointer to allocated memory. */
80+
int allocsize; /* Size of allocated memory. */
81+
int nargs; /* Number of arguments to pass. */
82+
STACK_VGID /* Optional valgrind stack id. See above. */
83+
};
84+
85+
typedef void (*coco_MainFunc)(void);
86+
87+
/* Put the Coco state at the end and align it downwards. */
88+
#define ALIGNED_END(p, s, t) \
89+
((t *)(((char *)0) + ((((char *)(p)-(char *)0)+(s)-sizeof(t)) & -16)))
90+
91+
#define COCO_NEW(OL, NL, cstacksize, mainfunc) \
92+
{ \
93+
void *ptr = luaM_malloc(OL, cstacksize); \
94+
coco_State *coco = ALIGNED_END(ptr, cstacksize, coco_State); \
95+
STACK_REG(coco, ptr, cstacksize) \
96+
coco->allocptr = ptr; \
97+
coco->allocsize = cstacksize; \
98+
COCO_FILL(coco, NL, mainfunc) \
99+
L2COCO(NL) = coco; \
100+
}
101+
102+
#define COCO_FREE(L) \
103+
STACK_DEREG(L2COCO(L)) \
104+
luaM_freemem(L, L2COCO(L)->allocptr, L2COCO(L)->allocsize); \
105+
L2COCO(L) = NULL;
106+
107+
#define COCO_JUMPIN(coco) COCO_SWITCH(coco->back, coco->ctx)
108+
#define COCO_JUMPOUT(coco) COCO_SWITCH(coco->ctx, coco->back)
109+
110+
/* ------------------------------------------------------------------------ */
111+
112+
#ifndef COCO_MIN_CSTACKSIZE
113+
#define COCO_MIN_CSTACKSIZE (2048)
114+
#endif
115+
116+
/* Don't use multiples of 64K to avoid D-cache aliasing conflicts. */
117+
#ifndef COCO_DEFAULT_CSTACKSIZE
118+
#define COCO_DEFAULT_CSTACKSIZE (8192)
119+
#endif
120+
121+
static int defaultcstacksize = COCO_DEFAULT_CSTACKSIZE;
122+
123+
/* Start the Lua or C function. */
124+
static void coco_start(lua_State *L, void *ud)
125+
{
126+
if (luaD_precall(L, (StkId)ud, LUA_MULTRET) == PCRLUA)
127+
luaV_execute(L, L->ci - L->base_ci);
128+
}
129+
130+
// _a to _f for register file a2 to a7, thus L is where a1(stack ptr) point to
131+
#define COCO_MAIN_PARAM int _a, int _b, int _c, int _d, int _e, int _f, lua_State *L
132+
133+
#ifndef COCO_MAIN_DECL
134+
#define COCO_MAIN_DECL
135+
#endif
136+
137+
/* Toplevel function for the new coroutine stack. Never exits. */
138+
static void COCO_MAIN_DECL coco_main(COCO_MAIN_PARAM)
139+
{
140+
#ifdef COCO_MAIN_GETL
141+
COCO_MAIN_GETL
142+
#endif
143+
coco_State *coco = L2COCO(L);
144+
for (;;) {
145+
L->status = luaD_rawrunprotected(L, coco_start, L->top - (coco->nargs+1));
146+
if (L->status != 0) luaD_seterrorobj(L, L->status, L->top);
147+
COCO_JUMPOUT(coco)
148+
}
149+
}
150+
151+
/* Add a C stack to a coroutine. */
152+
lua_State *lua_newcthread(lua_State *OL, int cstacksize)
153+
{
154+
lua_State *NL = lua_newthread(OL);
155+
156+
if (cstacksize < 0)
157+
return NL;
158+
if (cstacksize == 0)
159+
cstacksize = defaultcstacksize;
160+
else if (cstacksize < COCO_MIN_CSTACKSIZE)
161+
cstacksize = COCO_MIN_CSTACKSIZE;
162+
cstacksize &= -16;
163+
164+
COCO_NEW(OL, NL, cstacksize, ((coco_MainFunc)(coco_main)))
165+
166+
return NL;
167+
}
168+
169+
/* Free the C stack of a coroutine. Called from lstate.c. */
170+
void luaCOCO_free(lua_State *L)
171+
{
172+
COCO_FREE(L)
173+
}
174+
175+
/* Resume a coroutine with a C stack. Called from ldo.c. */
176+
int luaCOCO_resume(lua_State *L, int nargs)
177+
{
178+
coco_State *coco = L2COCO(L);
179+
coco->nargs = nargs;
180+
COCO_JUMPIN(coco)
181+
#ifndef COCO_DISABLE_EARLY_FREE
182+
if (L->status != LUA_YIELD) {
183+
COCO_FREE(L)
184+
}
185+
#endif
186+
return L->status;
187+
}
188+
189+
/* Yield from a coroutine with a C stack. Called from ldo.c. */
190+
int luaCOCO_yield(lua_State *L)
191+
{
192+
coco_State *coco = L2COCO(L);
193+
L->status = LUA_YIELD;
194+
COCO_JUMPOUT(coco)
195+
L->status = 0;
196+
{
197+
StkId base = L->top - coco->nargs;
198+
StkId rbase = L->base;
199+
if (rbase < base) { /* Need to move args down? */
200+
while (base < L->top)
201+
setobjs2s(L, rbase++, base++);
202+
L->top = rbase;
203+
}
204+
}
205+
L->base = L->ci->base; /* Restore invariant. */
206+
return coco->nargs;
207+
}
208+
209+
/* Get/set the default C stack size. */
210+
int luaCOCO_cstacksize(int cstacksize)
211+
{
212+
int oldsz = defaultcstacksize;
213+
if (cstacksize >= 0) {
214+
if (cstacksize == 0)
215+
cstacksize = COCO_DEFAULT_CSTACKSIZE;
216+
else if (cstacksize < COCO_MIN_CSTACKSIZE)
217+
cstacksize = COCO_MIN_CSTACKSIZE;
218+
defaultcstacksize = cstacksize;
219+
}
220+
return oldsz;
221+
}
222+
223+
#endif

0 commit comments

Comments
 (0)