xref: /freebsd-src/sys/contrib/openzfs/module/lua/lcorolib.c (revision c03c5b1c80914ec656fbee84539355d1fad68bf9)
1*eda14cbcSMatt Macy /*
2*eda14cbcSMatt Macy ** $Id: lcorolib.c,v 1.5.1.1 2013/04/12 18:48:47 roberto Exp $
3*eda14cbcSMatt Macy ** Coroutine Library
4*eda14cbcSMatt Macy ** See Copyright Notice in lua.h
5*eda14cbcSMatt Macy */
6*eda14cbcSMatt Macy 
7*eda14cbcSMatt Macy 
8*eda14cbcSMatt Macy #define lcorolib_c
9*eda14cbcSMatt Macy #define LUA_LIB
10*eda14cbcSMatt Macy 
11*eda14cbcSMatt Macy #include <sys/lua/lua.h>
12*eda14cbcSMatt Macy 
13*eda14cbcSMatt Macy #include <sys/lua/lauxlib.h>
14*eda14cbcSMatt Macy #include <sys/lua/lualib.h>
15*eda14cbcSMatt Macy 
16*eda14cbcSMatt Macy 
auxresume(lua_State * L,lua_State * co,int narg)17*eda14cbcSMatt Macy static int auxresume (lua_State *L, lua_State *co, int narg) {
18*eda14cbcSMatt Macy   int status;
19*eda14cbcSMatt Macy   if (!lua_checkstack(co, narg)) {
20*eda14cbcSMatt Macy     lua_pushliteral(L, "too many arguments to resume");
21*eda14cbcSMatt Macy     return -1;  /* error flag */
22*eda14cbcSMatt Macy   }
23*eda14cbcSMatt Macy   if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) {
24*eda14cbcSMatt Macy     lua_pushliteral(L, "cannot resume dead coroutine");
25*eda14cbcSMatt Macy     return -1;  /* error flag */
26*eda14cbcSMatt Macy   }
27*eda14cbcSMatt Macy   lua_xmove(L, co, narg);
28*eda14cbcSMatt Macy   status = lua_resume(co, L, narg);
29*eda14cbcSMatt Macy   if (status == LUA_OK || status == LUA_YIELD) {
30*eda14cbcSMatt Macy     int nres = lua_gettop(co);
31*eda14cbcSMatt Macy     if (!lua_checkstack(L, nres + 1)) {
32*eda14cbcSMatt Macy       lua_pop(co, nres);  /* remove results anyway */
33*eda14cbcSMatt Macy       lua_pushliteral(L, "too many results to resume");
34*eda14cbcSMatt Macy       return -1;  /* error flag */
35*eda14cbcSMatt Macy     }
36*eda14cbcSMatt Macy     lua_xmove(co, L, nres);  /* move yielded values */
37*eda14cbcSMatt Macy     return nres;
38*eda14cbcSMatt Macy   }
39*eda14cbcSMatt Macy   else {
40*eda14cbcSMatt Macy     lua_xmove(co, L, 1);  /* move error message */
41*eda14cbcSMatt Macy     return -1;  /* error flag */
42*eda14cbcSMatt Macy   }
43*eda14cbcSMatt Macy }
44*eda14cbcSMatt Macy 
45*eda14cbcSMatt Macy 
luaB_coresume(lua_State * L)46*eda14cbcSMatt Macy static int luaB_coresume (lua_State *L) {
47*eda14cbcSMatt Macy   lua_State *co = lua_tothread(L, 1);
48*eda14cbcSMatt Macy   int r;
49*eda14cbcSMatt Macy   luaL_argcheck(L, co, 1, "coroutine expected");
50*eda14cbcSMatt Macy   r = auxresume(L, co, lua_gettop(L) - 1);
51*eda14cbcSMatt Macy   if (r < 0) {
52*eda14cbcSMatt Macy     lua_pushboolean(L, 0);
53*eda14cbcSMatt Macy     lua_insert(L, -2);
54*eda14cbcSMatt Macy     return 2;  /* return false + error message */
55*eda14cbcSMatt Macy   }
56*eda14cbcSMatt Macy   else {
57*eda14cbcSMatt Macy     lua_pushboolean(L, 1);
58*eda14cbcSMatt Macy     lua_insert(L, -(r + 1));
59*eda14cbcSMatt Macy     return r + 1;  /* return true + 'resume' returns */
60*eda14cbcSMatt Macy   }
61*eda14cbcSMatt Macy }
62*eda14cbcSMatt Macy 
63*eda14cbcSMatt Macy 
luaB_auxwrap(lua_State * L)64*eda14cbcSMatt Macy static int luaB_auxwrap (lua_State *L) {
65*eda14cbcSMatt Macy   lua_State *co = lua_tothread(L, lua_upvalueindex(1));
66*eda14cbcSMatt Macy   int r = auxresume(L, co, lua_gettop(L));
67*eda14cbcSMatt Macy   if (r < 0) {
68*eda14cbcSMatt Macy     if (lua_isstring(L, -1)) {  /* error object is a string? */
69*eda14cbcSMatt Macy       luaL_where(L, 1);  /* add extra info */
70*eda14cbcSMatt Macy       lua_insert(L, -2);
71*eda14cbcSMatt Macy       lua_concat(L, 2);
72*eda14cbcSMatt Macy     }
73*eda14cbcSMatt Macy     return lua_error(L);  /* propagate error */
74*eda14cbcSMatt Macy   }
75*eda14cbcSMatt Macy   return r;
76*eda14cbcSMatt Macy }
77*eda14cbcSMatt Macy 
78*eda14cbcSMatt Macy 
luaB_cocreate(lua_State * L)79*eda14cbcSMatt Macy static int luaB_cocreate (lua_State *L) {
80*eda14cbcSMatt Macy   lua_State *NL;
81*eda14cbcSMatt Macy   luaL_checktype(L, 1, LUA_TFUNCTION);
82*eda14cbcSMatt Macy   NL = lua_newthread(L);
83*eda14cbcSMatt Macy   lua_pushvalue(L, 1);  /* move function to top */
84*eda14cbcSMatt Macy   lua_xmove(L, NL, 1);  /* move function from L to NL */
85*eda14cbcSMatt Macy   return 1;
86*eda14cbcSMatt Macy }
87*eda14cbcSMatt Macy 
88*eda14cbcSMatt Macy 
luaB_cowrap(lua_State * L)89*eda14cbcSMatt Macy static int luaB_cowrap (lua_State *L) {
90*eda14cbcSMatt Macy   luaB_cocreate(L);
91*eda14cbcSMatt Macy   lua_pushcclosure(L, luaB_auxwrap, 1);
92*eda14cbcSMatt Macy   return 1;
93*eda14cbcSMatt Macy }
94*eda14cbcSMatt Macy 
95*eda14cbcSMatt Macy 
luaB_yield(lua_State * L)96*eda14cbcSMatt Macy static int luaB_yield (lua_State *L) {
97*eda14cbcSMatt Macy   return lua_yield(L, lua_gettop(L));
98*eda14cbcSMatt Macy }
99*eda14cbcSMatt Macy 
100*eda14cbcSMatt Macy 
luaB_costatus(lua_State * L)101*eda14cbcSMatt Macy static int luaB_costatus (lua_State *L) {
102*eda14cbcSMatt Macy   lua_State *co = lua_tothread(L, 1);
103*eda14cbcSMatt Macy   luaL_argcheck(L, co, 1, "coroutine expected");
104*eda14cbcSMatt Macy   if (L == co) lua_pushliteral(L, "running");
105*eda14cbcSMatt Macy   else {
106*eda14cbcSMatt Macy     switch (lua_status(co)) {
107*eda14cbcSMatt Macy       case LUA_YIELD:
108*eda14cbcSMatt Macy         lua_pushliteral(L, "suspended");
109*eda14cbcSMatt Macy         break;
110*eda14cbcSMatt Macy       case LUA_OK: {
111*eda14cbcSMatt Macy         lua_Debug ar;
112*eda14cbcSMatt Macy         if (lua_getstack(co, 0, &ar) > 0)  /* does it have frames? */
113*eda14cbcSMatt Macy           lua_pushliteral(L, "normal");  /* it is running */
114*eda14cbcSMatt Macy         else if (lua_gettop(co) == 0)
115*eda14cbcSMatt Macy             lua_pushliteral(L, "dead");
116*eda14cbcSMatt Macy         else
117*eda14cbcSMatt Macy           lua_pushliteral(L, "suspended");  /* initial state */
118*eda14cbcSMatt Macy         break;
119*eda14cbcSMatt Macy       }
120*eda14cbcSMatt Macy       default:  /* some error occurred */
121*eda14cbcSMatt Macy         lua_pushliteral(L, "dead");
122*eda14cbcSMatt Macy         break;
123*eda14cbcSMatt Macy     }
124*eda14cbcSMatt Macy   }
125*eda14cbcSMatt Macy   return 1;
126*eda14cbcSMatt Macy }
127*eda14cbcSMatt Macy 
128*eda14cbcSMatt Macy 
luaB_corunning(lua_State * L)129*eda14cbcSMatt Macy static int luaB_corunning (lua_State *L) {
130*eda14cbcSMatt Macy   int ismain = lua_pushthread(L);
131*eda14cbcSMatt Macy   lua_pushboolean(L, ismain);
132*eda14cbcSMatt Macy   return 2;
133*eda14cbcSMatt Macy }
134*eda14cbcSMatt Macy 
135*eda14cbcSMatt Macy 
136*eda14cbcSMatt Macy static const luaL_Reg co_funcs[] = {
137*eda14cbcSMatt Macy   {"create", luaB_cocreate},
138*eda14cbcSMatt Macy   {"resume", luaB_coresume},
139*eda14cbcSMatt Macy   {"running", luaB_corunning},
140*eda14cbcSMatt Macy   {"status", luaB_costatus},
141*eda14cbcSMatt Macy   {"wrap", luaB_cowrap},
142*eda14cbcSMatt Macy   {"yield", luaB_yield},
143*eda14cbcSMatt Macy   {NULL, NULL}
144*eda14cbcSMatt Macy };
145*eda14cbcSMatt Macy 
146*eda14cbcSMatt Macy 
147*eda14cbcSMatt Macy 
luaopen_coroutine(lua_State * L)148*eda14cbcSMatt Macy LUAMOD_API int luaopen_coroutine (lua_State *L) {
149*eda14cbcSMatt Macy   luaL_newlib(L, co_funcs);
150*eda14cbcSMatt Macy   return 1;
151*eda14cbcSMatt Macy }
152*eda14cbcSMatt Macy 
153*eda14cbcSMatt Macy #if defined(_KERNEL)
154*eda14cbcSMatt Macy 
155*eda14cbcSMatt Macy EXPORT_SYMBOL(luaopen_coroutine);
156*eda14cbcSMatt Macy 
157*eda14cbcSMatt Macy #endif
158