From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id 3248F376361; Wed, 15 Mar 2023 19:17:21 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 3248F376361 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1678897041; bh=yUJQmjUJYPNXBr+eQs8viJEkrVs1oXwzp65nOkNiHAY=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=T6zhMDfeF+P3BP/Tqlpaz797P3jxfjgfoCqbCIB7t1lOtwx6r1g/BxV/88XSa2N0X kLw/URxWq80PBIsjkB8xD6smuWt4OI3rvsazyLwOOKJozE+LYUkCEIH06oHJfKMaiO vX94LyNOF3KP9YiniA3qrIW9qSRxsEAI3ouNivWQ= Received: from smtpng1.i.mail.ru (smtpng1.i.mail.ru [94.100.181.251]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id B9977376363 for ; Wed, 15 Mar 2023 19:14:54 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org B9977376363 Received: by smtpng1.m.smailru.net with esmtpa (envelope-from ) id 1pcTm9-0003ZV-PP; Wed, 15 Mar 2023 19:14:54 +0300 To: Igor Munkin , Maxim Kokryashkin Date: Wed, 15 Mar 2023 19:11:05 +0300 Message-Id: <251e7cacc074df4ebae5efcddc12665a2f8ffaa4.1678895861.git.skaplun@tarantool.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Mailru-Src: smtp X-4EC0790: 10 X-7564579A: EEAE043A70213CC8 X-77F55803: 4F1203BC0FB41BD91FB0073BE751D55461ABC3E74F83D87504755FF90D1007B7182A05F5380850404C228DA9ACA6FE27F9E4AE93DBAB64882A11B641D18C90036CF8B347E0291DB932F6870C367299B6 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE70043D879A87EF1BCEA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F7900637680B37D8C6EC627A8638F802B75D45FF36EB9D2243A4F8B5A6FCA7DBDB1FC311F39EFFDF887939037866D6147AF826D8295E1428BA4ADCA4B41E911575C1B3EF117882F4460429724CE54428C33FAD305F5C1EE8F4F765FCD6672DD12D5A8206A471835C12D1D9774AD6D5ED66289B52BA9C0B312567BB23117882F44604297287769387670735204B6963042765DA4BF04B652EEC242312D2E47CDBA5A96583BA9C0B312567BB231DD303D21008E29813377AFFFEAFD269A417C69337E82CC2E827F84554CEF50127C277FBC8AE2E8BA83251EDC214901ED5E8D9A59859A8B6B1CFA6D474D4A6A4089D37D7C0E48F6C5571747095F342E88FB05168BE4CE3AF X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D34B3611847B8BC2D0B133D9C05BDC68ACA816D39A97EDF9907907F1D03E9781B6CEB4B85D8767926D01D7E09C32AA3244CD303B517D392134CB33AA81DA2A9891851E887DA02A9F7BF927AC6DF5659F194 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojOXwBDQf4j7P/DHI7MWxpfw== X-DA7885C5: 89629C50D0CB74CA992EB771DD7126D07F76E7F565249470F40874DFACA0A2A9262E2D401490A4A0DB037EFA58388B346E8BC1A9835FDE71 X-Mailru-Sender: 689FA8AB762F73933AF1F914F131DBF5F66C1C6A52BB23F7853B0B257498B3FA0FBE9A32752B8C9C2AA642CC12EC09F1FB559BB5D741EB962F61BD320559CF1EFD657A8799238ED55FEEDEB644C299C0ED14614B50AE0675 X-Mras: Ok Subject: [Tarantool-patches] [PATCH v1 luajit 5/5] test: rewrite misclib-sysprof-capi test in C X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Sergey Kaplun via Tarantool-patches Reply-To: Sergey Kaplun Cc: tarantool-patches@dev.tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" This patch rewrites the aforementioned test with usage libtest recently introduced. The approach is similar to the previous patch. `c_payload()` function to profile now is set up globally on script loading. The payload for enabled and disabled JIT is the same. As far as for sysprof testing is necessary to replace backtrace with libunwind first, the payload tests are marked with `todo()`. Nevertheless, glibc `assert()` still necessary to check correctness of profile writer, so it is still used there. Relates to tarantool/tarantool#781 Part of tarantool/tarantool#7900 --- .../misclib-sysprof-capi-script.lua | 35 ++ .../misclib-sysprof-capi.test.c | 317 ++++++++++++++++++ test/tarantool-tests/CMakeLists.txt | 1 - .../misclib-sysprof-capi.test.lua | 54 --- .../misclib-sysprof-capi/CMakeLists.txt | 1 - .../misclib-sysprof-capi/testsysprof.c | 260 -------------- 6 files changed, 352 insertions(+), 316 deletions(-) create mode 100644 test/tarantool-c-tests/misclib-sysprof-capi-script.lua create mode 100644 test/tarantool-c-tests/misclib-sysprof-capi.test.c delete mode 100644 test/tarantool-tests/misclib-sysprof-capi.test.lua delete mode 100644 test/tarantool-tests/misclib-sysprof-capi/CMakeLists.txt delete mode 100644 test/tarantool-tests/misclib-sysprof-capi/testsysprof.c diff --git a/test/tarantool-c-tests/misclib-sysprof-capi-script.lua b/test/tarantool-c-tests/misclib-sysprof-capi-script.lua new file mode 100644 index 00000000..dd8387db --- /dev/null +++ b/test/tarantool-c-tests/misclib-sysprof-capi-script.lua @@ -0,0 +1,35 @@ +local M = {} + +-- luacheck: no global +assert(c_payload, 'c_payload global function should be set via script loader') + +local function lua_payload(n) + if n <= 1 then + return n + end + return lua_payload(n - 1) + lua_payload(n - 2) +end + +local function payload() + local n_iterations = 500000 + + local co = coroutine.create(function() + for i = 1, n_iterations do + if i % 2 == 0 then + c_payload(10) + else + lua_payload(10) + end + coroutine.yield() + end + end) + + for _ = 1, n_iterations do + coroutine.resume(co) + end +end + +M.profile_func_jiton = payload +M.profile_func_jitoff = payload + +return M diff --git a/test/tarantool-c-tests/misclib-sysprof-capi.test.c b/test/tarantool-c-tests/misclib-sysprof-capi.test.c new file mode 100644 index 00000000..4c54877e --- /dev/null +++ b/test/tarantool-c-tests/misclib-sysprof-capi.test.c @@ -0,0 +1,317 @@ +#include "lauxlib.h" +#include "lmisclib.h" +#include "lua.h" +#include "luajit.h" + +#include "test.h" +#include "utils.h" + +#include +#include +#include +#include + +/* XXX: Still need normal assert inside writer functions. */ +#undef NDEBUG +#include + +/* Need for skipcond for OS and ARCH. */ +#include "lj_arch.h" + +#define UNUSED(x) ((void)(x)) + +/* --- utils -------------------------------------------------- */ + +#define SYSPROF_INTERVAL_DEFAULT 100 + +/* + * Yep, 8Mb. Tuned in order not to bother the platform with too + * often flushes. + */ +#define STREAM_BUFFER_SIZE (8 * 1024 * 1024) + +/* + * Structure given as ctx to sysprof writer and on_stop callback. + */ +struct sysprof_ctx { + /* Output file descriptor for data. */ + int fd; + /* Buffer for data. */ + uint8_t buf[STREAM_BUFFER_SIZE]; +}; + +/* + * Default buffer writer function. + * Just call fwrite to the corresponding FILE. + */ +static size_t buffer_writer_default(const void **buf_addr, size_t len, + void *opt) +{ + struct sysprof_ctx *ctx = opt; + int fd = ctx->fd; + const void * const buf_start = *buf_addr; + const void *data = *buf_addr; + size_t write_total = 0; + + assert(len <= STREAM_BUFFER_SIZE); + + for (;;) { + const size_t written = write(fd, data, len - write_total); + + if (written == 0) { + /* Re-tries write in case of EINTR. */ + if (errno != EINTR) { + /* + * Will be freed as whole chunk + * later. + */ + *buf_addr = NULL; + return write_total; + } + errno = 0; + continue; + } + + write_total += written; + assert(write_total <= len); + + if (write_total == len) + break; + + data = (uint8_t *)data + (ptrdiff_t)written; + } + + *buf_addr = buf_start; + return write_total; +} + +/* + * Default on stop callback. Just close the corresponding stream. + */ +static int on_stop_cb_default(void *opt, uint8_t *buf) +{ + UNUSED(buf); + struct sysprof_ctx *ctx = opt; + int fd = ctx->fd; + free(ctx); + return close(fd); +} + +static int stream_init(struct luam_Sysprof_Options *opt) +{ + struct sysprof_ctx *ctx = calloc(1, sizeof(struct sysprof_ctx)); + if (NULL == ctx) + return PROFILE_ERRIO; + + ctx->fd = open("/dev/null", O_WRONLY | O_CREAT, 0644); + if (-1 == ctx->fd) { + free(ctx); + return PROFILE_ERRIO; + } + + opt->ctx = ctx; + opt->buf = ctx->buf; + opt->len = STREAM_BUFFER_SIZE; + + return PROFILE_SUCCESS; +} + +/* --- C Payload ---------------------------------------------- */ + +static double fib(double n) +{ + if (n <= 1) + return n; + return fib(n - 1) + fib(n - 2); +} + +static int c_payload(lua_State *L) +{ + fib(luaL_checknumber(L, 1)); + lua_pushboolean(L, 1); + return 1; +} + +/* --- sysprof C API tests ------------------------------------ */ + +static int base(void *test_state) +{ + UNUSED(test_state); + struct luam_Sysprof_Options opt = {}; + struct luam_Sysprof_Counters cnt = {}; + + (void)opt.interval; + (void)opt.mode; + (void)opt.ctx; + (void)opt.buf; + (void)opt.len; + + luaM_sysprof_report(&cnt); + + (void)cnt.samples; + (void)cnt.vmst_interp; + (void)cnt.vmst_lfunc; + (void)cnt.vmst_ffunc; + (void)cnt.vmst_cfunc; + (void)cnt.vmst_gc; + (void)cnt.vmst_exit; + (void)cnt.vmst_record; + (void)cnt.vmst_opt; + (void)cnt.vmst_asm; + (void)cnt.vmst_trace; + + return TEST_EXIT_SUCCESS; +} + +static int validation(void *test_state) +{ + lua_State *L = test_state; + struct luam_Sysprof_Options opt = {}; + int status = PROFILE_SUCCESS; + + /* Unknown mode. */ + opt.mode = 0x40; + status = luaM_sysprof_start(L, &opt); + assert_true(status == PROFILE_ERRUSE); + + /* Buffer not configured. */ + opt.mode = LUAM_SYSPROF_CALLGRAPH; + opt.buf = NULL; + status = luaM_sysprof_start(L, &opt); + assert_true(status == PROFILE_ERRUSE); + + /* Bad interval. */ + opt.mode = LUAM_SYSPROF_DEFAULT; + opt.interval = 0; + status = luaM_sysprof_start(L, &opt); + assert_true(status == PROFILE_ERRUSE); + + /* Check if profiling started. */ + opt.mode = LUAM_SYSPROF_DEFAULT; + opt.interval = SYSPROF_INTERVAL_DEFAULT; + status = luaM_sysprof_start(L, &opt); + assert_true(status == PROFILE_SUCCESS); + + /* Already running. */ + status = luaM_sysprof_start(L, &opt); + assert_true(status == PROFILE_ERRRUN); + + /* Profiler stopping. */ + status = luaM_sysprof_stop(L); + assert_true(status == PROFILE_SUCCESS); + + /* Stopping profiler which is not running. */ + status = luaM_sysprof_stop(L); + assert_true(status == PROFILE_ERRRUN); + + return TEST_EXIT_SUCCESS; +} + +/* Get function to profile on top, call it. */ +static int check_profile_func(lua_State *L) +{ + struct luam_Sysprof_Options opt = {}; + struct luam_Sysprof_Counters cnt = {}; + int status = PROFILE_ERRUSE; + /* + * Since all the other modes functionality is the + * subset of CALLGRAPH mode, run this mode to test + * the profiler's behavior. + */ + opt.mode = LUAM_SYSPROF_CALLGRAPH; + opt.interval = SYSPROF_INTERVAL_DEFAULT; + stream_init(&opt); + + /* + * XXX: Payload function on top will not be removed if any + * of those assertions fail. So, the next call to the + * `utils_get_aux_lfunc()` will fail. It's OK, since + * we are already in trouble, just keep it in mind. + */ + assert_true(luaM_sysprof_set_writer(buffer_writer_default) + == PROFILE_SUCCESS); + assert_true(luaM_sysprof_set_on_stop(on_stop_cb_default) + == PROFILE_SUCCESS); + assert_true(luaM_sysprof_set_backtracer(NULL) == PROFILE_SUCCESS); + + status = luaM_sysprof_start(L, &opt); + assert_true(status == PROFILE_SUCCESS); + + /* Run payload. */ + if (lua_pcall(L, 0, 0, 0) != LUA_OK) { + test_comment("error running payload: %s", lua_tostring(L, -1)); + bail_out("error running sysprof test payload"); + } + + status = luaM_sysprof_stop(L); + assert_true(status == PROFILE_SUCCESS); + + status = luaM_sysprof_report(&cnt); + assert_true(status == PROFILE_SUCCESS); + + assert_true(cnt.samples > 1); + assert_true(cnt.samples == cnt.vmst_asm + + cnt.vmst_cfunc + + cnt.vmst_exit + + cnt.vmst_ffunc + + cnt.vmst_gc + + cnt.vmst_interp + + cnt.vmst_lfunc + + cnt.vmst_opt + + cnt.vmst_record + + cnt.vmst_trace); + + return TEST_EXIT_SUCCESS; +} + +/* + * FIXME: The following two tests are disabled because sometimes + * `backtrace` dynamically loads a platform-specific unwinder, + * which is not signal-safe. + */ + +static int profile_func_jitoff(void *test_state) +{ + todo("Need to replace backtrace with libunwind first"); + lua_State *L = test_state; + utils_get_aux_lfunc(L); + (void)luaJIT_setmode(L, 0, LUAJIT_MODE_ENGINE | LUAJIT_MODE_OFF); + (void)luaJIT_setmode(L, 0, LUAJIT_MODE_ENGINE | LUAJIT_MODE_FLUSH); + check_profile_func(L); + (void)luaJIT_setmode(L, 0, LUAJIT_MODE_ENGINE | LUAJIT_MODE_ON); + return TEST_EXIT_SUCCESS; +} + +static int profile_func_jiton(void *test_state) +{ + todo("Need to replace backtrace with libunwind first"); + lua_State *L = test_state; + utils_get_aux_lfunc(L); + check_profile_func(L); + return TEST_EXIT_SUCCESS; +} + +int main(void) +{ + if (LUAJIT_OS != LUAJIT_OS_LINUX) + skip_all("Sysprof is implemented for Linux only"); + if (LUAJIT_TARGET != LUAJIT_ARCH_X86 + && LUAJIT_TARGET != LUAJIT_ARCH_X64) + skip_all("Sysprof is implemented for x86_64 only"); + + lua_State *L = utils_lua_init(); + + lua_pushcfunction(L, c_payload); + lua_setfield(L, LUA_GLOBALSINDEX, "c_payload"); + utils_load_aux_script(L); + + const struct test_unit tgroup[] = { + test_unit_new(base), + test_unit_new(validation), + test_unit_new(profile_func_jitoff), + test_unit_new(profile_func_jiton) + }; + const int test_result = test_run_group(tgroup, L); + utils_lua_close(L); + return test_result; +} diff --git a/test/tarantool-tests/CMakeLists.txt b/test/tarantool-tests/CMakeLists.txt index b4ce39d3..b1c7207f 100644 --- a/test/tarantool-tests/CMakeLists.txt +++ b/test/tarantool-tests/CMakeLists.txt @@ -66,7 +66,6 @@ add_subdirectory(lj-416-xor-before-jcc) add_subdirectory(lj-601-fix-gc-finderrfunc) add_subdirectory(lj-727-lightuserdata-itern) add_subdirectory(lj-flush-on-trace) -add_subdirectory(misclib-sysprof-capi) # The part of the memory profiler toolchain is located in tools # directory, jit, profiler, and bytecode toolchains are located diff --git a/test/tarantool-tests/misclib-sysprof-capi.test.lua b/test/tarantool-tests/misclib-sysprof-capi.test.lua deleted file mode 100644 index 4395bce3..00000000 --- a/test/tarantool-tests/misclib-sysprof-capi.test.lua +++ /dev/null @@ -1,54 +0,0 @@ -local tap = require("tap") -local test = tap.test("clib-misc-sysprof"):skipcond({ - ["Sysprof is implemented for x86_64 only"] = jit.arch ~= "x86" and - jit.arch ~= "x64", - ["Sysprof is implemented for Linux only"] = jit.os ~= "Linux", -}) - -test:plan(2) - -local testsysprof = require("testsysprof") - -jit.off() - -test:ok(testsysprof.base()) -test:ok(testsysprof.validation()) - --- FIXME: The following two tests are disabled because sometimes --- `backtrace` dynamically loads a platform-specific unwinder, which is --- not signal-safe. ---[[ -local function lua_payload(n) - if n <= 1 then - return n - end - return lua_payload(n - 1) + lua_payload(n - 2) -end - -local function payload() - local n_iterations = 500000 - - local co = coroutine.create(function () - for i = 1, n_iterations do - if i % 2 == 0 then - testsysprof.c_payload(10) - else - lua_payload(10) - end - coroutine.yield() - end - end) - - for _ = 1, n_iterations do - coroutine.resume(co) - end -end - -test:ok(testsysprof.profile_func(payload)) - -jit.on() -jit.flush() - -test:ok(testsysprof.profile_func(payload)) ---]] -os.exit(test:check() and 0 or 1) diff --git a/test/tarantool-tests/misclib-sysprof-capi/CMakeLists.txt b/test/tarantool-tests/misclib-sysprof-capi/CMakeLists.txt deleted file mode 100644 index d9fb1a1a..00000000 --- a/test/tarantool-tests/misclib-sysprof-capi/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -BuildTestCLib(testsysprof testsysprof.c) diff --git a/test/tarantool-tests/misclib-sysprof-capi/testsysprof.c b/test/tarantool-tests/misclib-sysprof-capi/testsysprof.c deleted file mode 100644 index d7a3e355..00000000 --- a/test/tarantool-tests/misclib-sysprof-capi/testsysprof.c +++ /dev/null @@ -1,260 +0,0 @@ -#include -#include -#include - -#include - -#include -#include -#include -#include - -#undef NDEBUG -#include - -#define UNUSED(x) ((void)(x)) - -/* --- utils -------------------------------------------------------------- */ - -#define SYSPROF_INTERVAL_DEFAULT 100 - -/* - ** Yep, 8Mb. Tuned in order not to bother the platform with too often flushes. - */ -#define STREAM_BUFFER_SIZE (8 * 1024 * 1024) - -/* Structure given as ctx to sysprof writer and on_stop callback. */ -struct sysprof_ctx { - /* Output file descriptor for data. */ - int fd; - /* Buffer for data. */ - uint8_t buf[STREAM_BUFFER_SIZE]; -}; - -/* - ** Default buffer writer function. - ** Just call fwrite to the corresponding FILE. - */ -static size_t buffer_writer_default(const void **buf_addr, size_t len, - void *opt) -{ - struct sysprof_ctx *ctx = opt; - int fd = ctx->fd; - const void * const buf_start = *buf_addr; - const void *data = *buf_addr; - size_t write_total = 0; - - assert(len <= STREAM_BUFFER_SIZE); - - for (;;) { - const size_t written = write(fd, data, len - write_total); - - if (written == 0) { - /* Re-tries write in case of EINTR. */ - if (errno != EINTR) { - /* Will be freed as whole chunk later. */ - *buf_addr = NULL; - return write_total; - } - errno = 0; - continue; - } - - write_total += written; - assert(write_total <= len); - - if (write_total == len) - break; - - data = (uint8_t *)data + (ptrdiff_t)written; - } - - *buf_addr = buf_start; - return write_total; -} - -/* Default on stop callback. Just close the corresponding stream. */ -static int on_stop_cb_default(void *opt, uint8_t *buf) -{ - UNUSED(buf); - struct sysprof_ctx *ctx = opt; - int fd = ctx->fd; - free(ctx); - return close(fd); -} - -static int stream_init(struct luam_Sysprof_Options *opt) -{ - struct sysprof_ctx *ctx = calloc(1, sizeof(struct sysprof_ctx)); - if (NULL == ctx) - return PROFILE_ERRIO; - - ctx->fd = open("/dev/null", O_WRONLY | O_CREAT, 0644); - if (-1 == ctx->fd) { - free(ctx); - return PROFILE_ERRIO; - } - - opt->ctx = ctx; - opt->buf = ctx->buf; - opt->len = STREAM_BUFFER_SIZE; - - return PROFILE_SUCCESS; -} - -/* --- Payload ------------------------------------------------------------ */ - -static double fib(double n) -{ - if (n <= 1) - return n; - return fib(n - 1) + fib(n - 2); -} - -static int c_payload(lua_State *L) -{ - fib(luaL_checknumber(L, 1)); - lua_pushboolean(L, 1); - return 1; -} - -/* --- sysprof C API tests ------------------------------------------------ */ - -static int base(lua_State *L) -{ - struct luam_Sysprof_Options opt = {}; - struct luam_Sysprof_Counters cnt = {}; - - (void)opt.interval; - (void)opt.mode; - (void)opt.ctx; - (void)opt.buf; - (void)opt.len; - - luaM_sysprof_report(&cnt); - - (void)cnt.samples; - (void)cnt.vmst_interp; - (void)cnt.vmst_lfunc; - (void)cnt.vmst_ffunc; - (void)cnt.vmst_cfunc; - (void)cnt.vmst_gc; - (void)cnt.vmst_exit; - (void)cnt.vmst_record; - (void)cnt.vmst_opt; - (void)cnt.vmst_asm; - (void)cnt.vmst_trace; - - lua_pushboolean(L, 1); - return 1; -} - -static int validation(lua_State *L) -{ - struct luam_Sysprof_Options opt = {}; - int status = PROFILE_SUCCESS; - - /* Unknown mode. */ - opt.mode = 0x40; - status = luaM_sysprof_start(L, &opt); - assert(PROFILE_ERRUSE == status); - - /* Buffer not configured. */ - opt.mode = LUAM_SYSPROF_CALLGRAPH; - opt.buf = NULL; - status = luaM_sysprof_start(L, &opt); - assert(PROFILE_ERRUSE == status); - - /* Bad interval. */ - opt.mode = LUAM_SYSPROF_DEFAULT; - opt.interval = 0; - status = luaM_sysprof_start(L, &opt); - assert(PROFILE_ERRUSE == status); - - /* Check if profiling started. */ - opt.mode = LUAM_SYSPROF_DEFAULT; - opt.interval = SYSPROF_INTERVAL_DEFAULT; - status = luaM_sysprof_start(L, &opt); - assert(PROFILE_SUCCESS == status); - - /* Already running. */ - status = luaM_sysprof_start(L, &opt); - assert(PROFILE_ERRRUN == status); - - /* Profiler stopping. */ - status = luaM_sysprof_stop(L); - assert(PROFILE_SUCCESS == status); - - /* Stopping profiler which is not running. */ - status = luaM_sysprof_stop(L); - assert(PROFILE_ERRRUN == status); - - lua_pushboolean(L, 1); - return 1; -} - -static int profile_func(lua_State *L) -{ - struct luam_Sysprof_Options opt = {}; - struct luam_Sysprof_Counters cnt = {}; - int status = PROFILE_ERRUSE; - - int n = lua_gettop(L); - if (n != 1 || !lua_isfunction(L, 1)) - luaL_error(L, "incorrect argument: 1 function is required"); - - /* - ** Since all the other modes functionality is the - ** subset of CALLGRAPH mode, run this mode to test - ** the profiler's behavior. - */ - opt.mode = LUAM_SYSPROF_CALLGRAPH; - opt.interval = SYSPROF_INTERVAL_DEFAULT; - stream_init(&opt); - - assert(luaM_sysprof_set_writer(buffer_writer_default) == PROFILE_SUCCESS); - assert(luaM_sysprof_set_on_stop(on_stop_cb_default) == PROFILE_SUCCESS); - assert(luaM_sysprof_set_backtracer(NULL) == PROFILE_SUCCESS); - - status = luaM_sysprof_start(L, &opt); - assert(PROFILE_SUCCESS == status); - - /* Run payload. */ - if (lua_pcall(L, 0, 0, 0) != LUA_OK) - luaL_error(L, "error running payload: %s", lua_tostring(L, -1)); - - status = luaM_sysprof_stop(L); - assert(PROFILE_SUCCESS == status); - - status = luaM_sysprof_report(&cnt); - assert(PROFILE_SUCCESS == status); - - assert(cnt.samples > 1); - assert(cnt.samples == cnt.vmst_asm + - cnt.vmst_cfunc + - cnt.vmst_exit + - cnt.vmst_ffunc + - cnt.vmst_gc + - cnt.vmst_interp + - cnt.vmst_lfunc + - cnt.vmst_opt + - cnt.vmst_record + - cnt.vmst_trace); - - lua_pushboolean(L, 1); - return 1; -} - -static const struct luaL_Reg testsysprof[] = { - {"base", base}, - {"c_payload", c_payload}, - {"profile_func", profile_func}, - {"validation", validation}, - {NULL, NULL} -}; - -LUA_API int luaopen_testsysprof(lua_State *L) -{ - luaL_register(L, "testsysprof", testsysprof); - return 1; -} -- 2.34.1