Path: blob/main/sys/contrib/openzfs/module/lua/lcorolib.c
48383 views
// SPDX-License-Identifier: MIT1/*2** $Id: lcorolib.c,v 1.5.1.1 2013/04/12 18:48:47 roberto Exp $3** Coroutine Library4** See Copyright Notice in lua.h5*/678#define lcorolib_c9#define LUA_LIB1011#include <sys/lua/lua.h>1213#include <sys/lua/lauxlib.h>14#include <sys/lua/lualib.h>151617static int auxresume (lua_State *L, lua_State *co, int narg) {18int status;19if (!lua_checkstack(co, narg)) {20lua_pushliteral(L, "too many arguments to resume");21return -1; /* error flag */22}23if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) {24lua_pushliteral(L, "cannot resume dead coroutine");25return -1; /* error flag */26}27lua_xmove(L, co, narg);28status = lua_resume(co, L, narg);29if (status == LUA_OK || status == LUA_YIELD) {30int nres = lua_gettop(co);31if (!lua_checkstack(L, nres + 1)) {32lua_pop(co, nres); /* remove results anyway */33lua_pushliteral(L, "too many results to resume");34return -1; /* error flag */35}36lua_xmove(co, L, nres); /* move yielded values */37return nres;38}39else {40lua_xmove(co, L, 1); /* move error message */41return -1; /* error flag */42}43}444546static int luaB_coresume (lua_State *L) {47lua_State *co = lua_tothread(L, 1);48int r;49luaL_argcheck(L, co, 1, "coroutine expected");50r = auxresume(L, co, lua_gettop(L) - 1);51if (r < 0) {52lua_pushboolean(L, 0);53lua_insert(L, -2);54return 2; /* return false + error message */55}56else {57lua_pushboolean(L, 1);58lua_insert(L, -(r + 1));59return r + 1; /* return true + 'resume' returns */60}61}626364static int luaB_auxwrap (lua_State *L) {65lua_State *co = lua_tothread(L, lua_upvalueindex(1));66int r = auxresume(L, co, lua_gettop(L));67if (r < 0) {68if (lua_isstring(L, -1)) { /* error object is a string? */69luaL_where(L, 1); /* add extra info */70lua_insert(L, -2);71lua_concat(L, 2);72}73return lua_error(L); /* propagate error */74}75return r;76}777879static int luaB_cocreate (lua_State *L) {80lua_State *NL;81luaL_checktype(L, 1, LUA_TFUNCTION);82NL = lua_newthread(L);83lua_pushvalue(L, 1); /* move function to top */84lua_xmove(L, NL, 1); /* move function from L to NL */85return 1;86}878889static int luaB_cowrap (lua_State *L) {90luaB_cocreate(L);91lua_pushcclosure(L, luaB_auxwrap, 1);92return 1;93}949596static int luaB_yield (lua_State *L) {97return lua_yield(L, lua_gettop(L));98}99100101static int luaB_costatus (lua_State *L) {102lua_State *co = lua_tothread(L, 1);103luaL_argcheck(L, co, 1, "coroutine expected");104if (L == co) lua_pushliteral(L, "running");105else {106switch (lua_status(co)) {107case LUA_YIELD:108lua_pushliteral(L, "suspended");109break;110case LUA_OK: {111lua_Debug ar;112if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */113lua_pushliteral(L, "normal"); /* it is running */114else if (lua_gettop(co) == 0)115lua_pushliteral(L, "dead");116else117lua_pushliteral(L, "suspended"); /* initial state */118break;119}120default: /* some error occurred */121lua_pushliteral(L, "dead");122break;123}124}125return 1;126}127128129static int luaB_corunning (lua_State *L) {130int ismain = lua_pushthread(L);131lua_pushboolean(L, ismain);132return 2;133}134135136static const luaL_Reg co_funcs[] = {137{"create", luaB_cocreate},138{"resume", luaB_coresume},139{"running", luaB_corunning},140{"status", luaB_costatus},141{"wrap", luaB_cowrap},142{"yield", luaB_yield},143{NULL, NULL}144};145146147148LUAMOD_API int luaopen_coroutine (lua_State *L) {149luaL_newlib(L, co_funcs);150return 1;151}152153#if defined(_KERNEL)154155EXPORT_SYMBOL(luaopen_coroutine);156157#endif158159160