Skip to content
Snippets Groups Projects
Commit 9da7e03e authored by Iskander Sagitov's avatar Iskander Sagitov Committed by Nikita Pettik
Browse files

fiber: introduce fiber_o:info() and fiber_o:csw()

If you want to get information or get csw (Context SWitch) of some fiber
you need to call fiber.info(), but it creates table with information about
all the fibers. This patch introduces fiber_object:info() and
fiber_object:csw() - functions to solve this problem.

Closes #5799

@TarantoolBot document
Title: introduce fiber_object:info() and fiber_object:csw()
```
-- fiber_object:info() is the same as fiber.info(), but show information only
about one alive fiber.
-- fiber_object:csw() show csw (Context SWitch) of alive fiber.
```
parent 39370f34
No related branches found
No related tags found
No related merge requests found
## feature/lua/fiber
* Introduce `fiber_object:info()` to get `info` from fiber. Works as `require(fiber).info()` but only for one fiber.
* Introduce `fiber_object:csw()` to get `csw` from fiber (gh-5799).
......@@ -263,13 +263,10 @@ fiber_backtrace_cb(int frameno, void *frameret, const char *func, size_t offset,
#endif
static int
lbox_fiber_statof(struct fiber *f, void *cb_ctx, bool backtrace)
lbox_fiber_statof_map(struct fiber *f, void *cb_ctx, bool backtrace)
{
struct lua_State *L = (struct lua_State *) cb_ctx;
luaL_pushuint64(L, f->fid);
lua_newtable(L);
lua_pushliteral(L, "name");
lua_pushstring(L, fiber_name(f));
lua_settable(L, -3);
......@@ -313,6 +310,16 @@ lbox_fiber_statof(struct fiber *f, void *cb_ctx, bool backtrace)
lua_settable(L, -3);
#endif /* ENABLE_BACKTRACE */
}
return 0;
}
static int
lbox_fiber_statof(struct fiber *f, void *cb_ctx, bool backtrace)
{
struct lua_State *L = cb_ctx;
luaL_pushuint64(L, f->fid);
lua_newtable(L);
lbox_fiber_statof_map(f, cb_ctx, backtrace);
lua_settable(L, -3);
return 0;
}
......@@ -406,14 +413,10 @@ lbox_fiber_top_disable(struct lua_State *L)
}
#endif /* ENABLE_FIBER_TOP */
/**
* Return fiber statistics.
*/
static int
lbox_fiber_info(struct lua_State *L)
{
#ifdef ENABLE_BACKTRACE
bool do_backtrace = true;
bool
lbox_do_backtrace(struct lua_State *L)
{
if (lua_istable(L, 1)) {
lua_pushstring(L, "backtrace");
lua_gettable(L, 1);
......@@ -423,9 +426,21 @@ lbox_fiber_info(struct lua_State *L)
lua_gettable(L, 1);
}
if (!lua_isnil(L, -1))
do_backtrace = lua_toboolean(L, -1);
return lua_toboolean(L, -1);
lua_pop(L, 1);
}
return true;
}
#endif /* ENABLE_BACKTRACE */
/**
* Return fiber statistics.
*/
static int
lbox_fiber_info(struct lua_State *L)
{
#ifdef ENABLE_BACKTRACE
bool do_backtrace = lbox_do_backtrace(L);
if (do_backtrace) {
lua_newtable(L);
fiber_stat(lbox_fiber_statof_bt, L);
......@@ -527,6 +542,17 @@ lbox_fiber_new(struct lua_State *L)
return 1;
}
static struct fiber *
lbox_get_fiber(struct lua_State *L)
{
if (lua_gettop(L) != 0) {
uint64_t *fid = luaL_checkudata(L, 1, fiberlib_name);
return fiber_find(*fid);
} else {
return fiber();
}
}
/**
* Get fiber status.
* This follows the rules of Lua coroutine.status() function:
......@@ -540,16 +566,9 @@ lbox_fiber_new(struct lua_State *L)
static int
lbox_fiber_status(struct lua_State *L)
{
struct fiber *f;
if (lua_gettop(L)) {
uint64_t fid = *(uint64_t *)
luaL_checkudata(L, 1, fiberlib_name);
f = fiber_find(fid);
} else {
f = fiber();
}
struct fiber *f = lbox_get_fiber(L);
const char *status;
if (f == NULL || f->fid == 0) {
if (f == NULL) {
/* This fiber is dead. */
status = "dead";
} else if (f == fiber()) {
......@@ -563,6 +582,42 @@ lbox_fiber_status(struct lua_State *L)
return 1;
}
/**
* Get fiber info: number of context switches, backtrace, id,
* total memory, used memory.
*/
static int
lbox_fiber_object_info(struct lua_State *L)
{
struct fiber *f = lbox_get_fiber(L);
if (f == NULL)
luaL_error(L, "the fiber is dead");
#ifdef ENABLE_BACKTRACE
bool do_backtrace = lbox_do_backtrace(L);
if (do_backtrace) {
lua_newtable(L);
lbox_fiber_statof_map(f, L, true);
} else
#endif /* ENABLE_BACKTRACE */
{
lua_newtable(L);
lbox_fiber_statof_map(f, L, false);
}
return 1;
}
static int
lbox_fiber_csw(struct lua_State *L)
{
struct fiber *f = lbox_get_fiber(L);
if (f == NULL) {
luaL_error(L, "the fiber is dead");
} else {
lua_pushinteger(L, f->csw);
}
return 1;
}
/**
* Get or set fiber name.
* With no arguments, gets or sets the current fiber
......@@ -857,6 +912,8 @@ static const struct luaL_Reg lbox_fiber_meta [] = {
{"name", lbox_fiber_name},
{"cancel", lbox_fiber_cancel},
{"status", lbox_fiber_status},
{"info", lbox_fiber_object_info},
{"csw", lbox_fiber_csw},
{"testcancel", lbox_fiber_testcancel},
{"__serialize", lbox_fiber_serialize},
{"__tostring", lbox_fiber_tostring},
......
-- test-run result file version 2
test_run = require('test_run').new()
| ---
| ...
fiber = require('fiber')
| ---
| ...
json = require('json')
| ---
| ...
function yielder(n) for i=1, n do fiber.yield() end end
| ---
| ...
csw_check_counter = 0
| ---
| ...
fibers = {}
| ---
| ...
test_run:cmd('setopt delimiter ";"')
| ---
| - true
| ...
for i=1,100 do
fibers[i] = fiber.new(function()
local start_csw = fiber.info()[fiber.self():id()].csw
for j=1,10 do
fiber.yield()
if j + start_csw == fiber.self():csw() and
j + start_csw == fiber.self():info().csw then
csw_check_counter = csw_check_counter + 1
end
end
end)
fibers[i]:set_joinable(true)
end;
| ---
| ...
for i=1,100 do
fibers[i]:join()
end;
| ---
| ...
test_run:cmd('setopt delimiter ""');
| ---
| - true
| ...
csw_check_counter
| ---
| - 1000
| ...
cond = fiber.cond()
| ---
| ...
running = fiber.create(function() cond:wait() end)
| ---
| ...
json.encode(running:info()) == json.encode(fiber.info()[running:id()])
| ---
| - true
| ...
cond:signal()
| ---
| ...
dead = fiber.create(function() end)
| ---
| ...
dead:csw()
| ---
| - error: the fiber is dead
| ...
dead:info()
| ---
| - error: the fiber is dead
| ...
test_run = require('test_run').new()
fiber = require('fiber')
json = require('json')
function yielder(n) for i=1, n do fiber.yield() end end
csw_check_counter = 0
fibers = {}
test_run:cmd('setopt delimiter ";"')
for i=1,100 do
fibers[i] = fiber.new(function()
local start_csw = fiber.info()[fiber.self():id()].csw
for j=1,10 do
fiber.yield()
if j + start_csw == fiber.self():csw() and
j + start_csw == fiber.self():info().csw then
csw_check_counter = csw_check_counter + 1
end
end
end)
fibers[i]:set_joinable(true)
end;
for i=1,100 do
fibers[i]:join()
end;
test_run:cmd('setopt delimiter ""');
csw_check_counter
cond = fiber.cond()
running = fiber.create(function() cond:wait() end)
json.encode(running:info()) == json.encode(fiber.info()[running:id()])
cond:signal()
dead = fiber.create(function() end)
dead:csw()
dead:info()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment