From: Cyrill Gorcunov via Tarantool-patches <tarantool-patches@dev.tarantool.org> To: tml <tarantool-patches@dev.tarantool.org> Cc: Vladislav Shpilevoy <v.shpilevoy@tarantool.org> Subject: [Tarantool-patches] [PATCH v14 01/12] box/func: factor out c function entry structure Date: Wed, 3 Feb 2021 01:11:56 +0300 [thread overview] Message-ID: <20210202221207.383101-2-gorcunov@gmail.com> (raw) In-Reply-To: <20210202221207.383101-1-gorcunov@gmail.com> Currently func_c structure is a wrapper over struct func which in turn handles function definition, credentials and etc, mostly to handle internal "_func" space. Such tight bound doesn't allow to reuse func_c in any other context. But we're going to support C function execution in read-only instances and for this we better reuse already existing structures as much as possible instead of breeding new ones. Thus lets extract module symbols into module_sym structure, this allows us to reuse module path cache in other code. While extracting the structure rename "func" member to "addr" since this exactly what the member represents: an address of symbol in memory. Same time to be completely independent of "_func" specific lets carry symbolic name inplace (ie member "name" is kind of redundant when module_sym is used for "_func" handling where we can retrieve the name via function definition but such definition won't be available for non-persistent C functions which we will support in next patches). The new structure allows us to load/unload general symbols via module_sym_load() and module_sym_unload() helpers. Part-of #4642 Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com> --- src/box/func.c | 190 ++++++++++++++++++++++++------------------------- src/box/func.h | 42 +++++++++++ 2 files changed, 134 insertions(+), 98 deletions(-) diff --git a/src/box/func.c b/src/box/func.c index 9909cee45..8030aa07c 100644 --- a/src/box/func.c +++ b/src/box/func.c @@ -59,19 +59,8 @@ struct func_name { struct func_c { /** Function object base class. */ struct func base; - /** - * Anchor for module membership. - */ - struct rlist item; - /** - * For C functions, the body of the function. - */ - box_function_f func; - /** - * Each stored function keeps a handle to the - * dynamic library for the C callback. - */ - struct module *module; + /** C function module symbol. */ + struct module_sym mod_sym; }; /*** @@ -371,6 +360,73 @@ module_sym(struct module *module, const char *name) return f; } +int +module_sym_load(struct module_sym *mod_sym) +{ + assert(mod_sym->addr == NULL); + + struct func_name name; + func_split_name(mod_sym->name, &name); + + /* + * In case if module has been loaded already by + * some previous call we can eliminate redundant + * loading and take it from the cache. + */ + struct module *cached, *module; + cached = module_cache_find(name.package, name.package_end); + if (cached == NULL) { + module = module_load(name.package, name.package_end); + if (module == NULL) + return -1; + if (module_cache_put(module) != 0) { + module_delete(module); + return -1; + } + } else { + module = cached; + } + + mod_sym->addr = module_sym(module, name.sym); + if (mod_sym->addr == NULL) { + if (cached == NULL) { + /* + * In case if it was a first load we should + * clean the cache immediately otherwise + * the module continue being referenced even + * if there will be no use of it. + * + * Note the module_sym set an error thus be + * careful to not wipe it. + */ + module_cache_del(name.package, name.package_end); + module_delete(module); + } + return -1; + } + mod_sym->module = module; + rlist_add(&module->funcs, &mod_sym->item); + return 0; +} + +void +module_sym_unload(struct module_sym *mod_sym) +{ + if (mod_sym->module == NULL) + return; + + rlist_del(&mod_sym->item); + if (rlist_empty(&mod_sym->module->funcs)) { + struct func_name name; + func_split_name(mod_sym->name, &name); + module_cache_del(name.package, name.package_end); + } + module_gc(mod_sym->module); + + mod_sym->module = NULL; + mod_sym->addr = NULL; +} + int module_reload(const char *package, const char *package_end, struct module **module) { @@ -385,15 +441,15 @@ module_reload(const char *package, const char *package_end, struct module **modu if (new_module == NULL) return -1; - struct func_c *func, *tmp_func; - rlist_foreach_entry_safe(func, &old_module->funcs, item, tmp_func) { + struct module_sym *mod_sym, *tmp; + rlist_foreach_entry_safe(mod_sym, &old_module->funcs, item, tmp) { struct func_name name; - func_split_name(func->base.def->name, &name); - func->func = module_sym(new_module, name.sym); - if (func->func == NULL) + func_split_name(mod_sym->name, &name); + mod_sym->addr = module_sym(new_module, name.sym); + if (mod_sym->addr == NULL) goto restore; - func->module = new_module; - rlist_move(&new_module->funcs, &func->item); + mod_sym->module = new_module; + rlist_move(&new_module->funcs, &mod_sym->item); } module_cache_del(package, package_end); if (module_cache_put(new_module) != 0) @@ -408,9 +464,9 @@ module_reload(const char *package, const char *package_end, struct module **modu */ do { struct func_name name; - func_split_name(func->base.def->name, &name); - func->func = module_sym(old_module, name.sym); - if (func->func == NULL) { + func_split_name(mod_sym->name, &name); + mod_sym->addr = module_sym(old_module, name.sym); + if (mod_sym->addr == NULL) { /* * Something strange was happen, an early loaden * function was not found in an old dso. @@ -418,10 +474,11 @@ module_reload(const char *package, const char *package_end, struct module **modu panic("Can't restore module function, " "server state is inconsistent"); } - func->module = old_module; - rlist_move(&old_module->funcs, &func->item); - } while (func != rlist_first_entry(&old_module->funcs, - struct func_c, item)); + mod_sym->module = old_module; + rlist_move(&old_module->funcs, &mod_sym->item); + } while (mod_sym != rlist_first_entry(&old_module->funcs, + struct module_sym, + item)); assert(rlist_empty(&new_module->funcs)); module_delete(new_module); return -1; @@ -484,94 +541,31 @@ func_c_new(MAYBE_UNUSED struct func_def *def) return NULL; } func->base.vtab = &func_c_vtab; - func->func = NULL; - func->module = NULL; + func->mod_sym.addr = NULL; + func->mod_sym.module = NULL; + func->mod_sym.name = def->name; return &func->base; } -static void -func_c_unload(struct func_c *func) -{ - if (func->module) { - rlist_del(&func->item); - if (rlist_empty(&func->module->funcs)) { - struct func_name name; - func_split_name(func->base.def->name, &name); - module_cache_del(name.package, name.package_end); - } - module_gc(func->module); - } - func->module = NULL; - func->func = NULL; -} - static void func_c_destroy(struct func *base) { assert(base->vtab == &func_c_vtab); assert(base != NULL && base->def->language == FUNC_LANGUAGE_C); struct func_c *func = (struct func_c *) base; - func_c_unload(func); + module_sym_unload(&func->mod_sym); TRASH(base); free(func); } -/** - * Resolve func->func (find the respective DLL and fetch the - * symbol from it). - */ -static int -func_c_load(struct func_c *func) -{ - assert(func->func == NULL); - - struct func_name name; - func_split_name(func->base.def->name, &name); - - struct module *cached, *module; - cached = module_cache_find(name.package, name.package_end); - if (cached == NULL) { - module = module_load(name.package, name.package_end); - if (module == NULL) - return -1; - if (module_cache_put(module)) { - module_delete(module); - return -1; - } - } else { - module = cached; - } - - func->func = module_sym(module, name.sym); - if (func->func == NULL) { - if (cached == NULL) { - /* - * In case if it was a first load we should - * clean the cache immediately otherwise - * the module continue being referenced even - * if there will be no use of it. - * - * Note the module_sym set an error thus be - * careful to not wipe it. - */ - module_cache_del(name.package, name.package_end); - module_delete(module); - } - return -1; - } - func->module = module; - rlist_add(&module->funcs, &func->item); - return 0; -} - int func_c_call(struct func *base, struct port *args, struct port *ret) { assert(base->vtab == &func_c_vtab); assert(base != NULL && base->def->language == FUNC_LANGUAGE_C); struct func_c *func = (struct func_c *) base; - if (func->func == NULL) { - if (func_c_load(func) != 0) + if (func->mod_sym.addr == NULL) { + if (module_sym_load(&func->mod_sym) != 0) return -1; } @@ -586,10 +580,10 @@ func_c_call(struct func *base, struct port *args, struct port *ret) box_function_ctx_t ctx = { ret }; /* Module can be changed after function reload. */ - struct module *module = func->module; + struct module *module = func->mod_sym.module; assert(module != NULL); ++module->calls; - int rc = func->func(&ctx, data, data + data_sz); + int rc = func->mod_sym.addr(&ctx, data, data + data_sz); --module->calls; module_gc(module); region_truncate(region, region_svp); diff --git a/src/box/func.h b/src/box/func.h index 581e468cb..9a7f17446 100644 --- a/src/box/func.h +++ b/src/box/func.h @@ -58,6 +58,28 @@ struct module { char package[0]; }; +/** + * Callable symbol bound to a module. + */ +struct module_sym { + /** + * Anchor for module membership. + */ + struct rlist item; + /** + * For C functions, address of the function. + */ + box_function_f addr; + /** + * A module the symbol belongs to. + */ + struct module *module; + /** + * Function name definition. + */ + char *name; +}; + /** Virtual method table for func object. */ struct func_vtab { /** Call function with given arguments. */ @@ -108,6 +130,26 @@ func_delete(struct func *func); int func_call(struct func *func, struct port *args, struct port *ret); +/** + * Resolve C entry (find the respective DLL and fetch the + * symbol from it). + * + * @param mod_sym module symbol pointer. + * @retval -1 on error. + * @retval 0 on success. + */ +int +module_sym_load(struct module_sym *mod_sym); + +/** + * Unload module symbol and drop it from the package + * cache if there is no users left. + * + * @param mod_sym module symbol pointer. + */ +void +module_sym_unload(struct module_sym *mod_sym); + /** * Reload dynamically loadable module. * -- 2.29.2
next prev parent reply other threads:[~2021-02-02 22:12 UTC|newest] Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-02-02 22:11 [Tarantool-patches] [PATCH v14 00/12] box: implement cmod Lua module Cyrill Gorcunov via Tarantool-patches 2021-02-02 22:11 ` Cyrill Gorcunov via Tarantool-patches [this message] 2021-02-02 22:11 ` [Tarantool-patches] [PATCH v14 02/12] module_cache: move module handling into own subsystem Cyrill Gorcunov via Tarantool-patches 2021-02-02 22:11 ` [Tarantool-patches] [PATCH v14 03/12] module_cache: direct update a cache value on reload Cyrill Gorcunov via Tarantool-patches 2021-02-02 22:11 ` [Tarantool-patches] [PATCH v14 04/12] module_cache: rename calls to ref in module structure Cyrill Gorcunov via Tarantool-patches 2021-02-02 22:12 ` [Tarantool-patches] [PATCH v14 05/12] module_cache: add comment about weird resolving Cyrill Gorcunov via Tarantool-patches 2021-02-02 22:12 ` [Tarantool-patches] [PATCH v14 06/12] module_cache: module_reload - drop redundant parameter Cyrill Gorcunov via Tarantool-patches 2021-02-02 22:12 ` [Tarantool-patches] [PATCH v14 07/12] module_cache: use references as a main usage counter Cyrill Gorcunov via Tarantool-patches 2021-02-02 22:12 ` [Tarantool-patches] [PATCH v14 08/12] module_cache: make module to carry hash it belongs to Cyrill Gorcunov via Tarantool-patches 2021-02-02 22:12 ` [Tarantool-patches] [PATCH v14 09/12] module_cache: use own hash for box.schema.func requests Cyrill Gorcunov via Tarantool-patches 2021-02-02 22:12 ` [Tarantool-patches] [PATCH v14 10/12] module_cache: provide module_load/unload calls Cyrill Gorcunov via Tarantool-patches 2021-02-02 22:12 ` [Tarantool-patches] [PATCH v14 11/12] box/cmod: implement cmod Lua module Cyrill Gorcunov via Tarantool-patches 2021-02-02 22:12 ` [Tarantool-patches] [PATCH v14 12/12] test: box/cfunc -- add cmod test Cyrill Gorcunov via Tarantool-patches
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20210202221207.383101-2-gorcunov@gmail.com \ --to=tarantool-patches@dev.tarantool.org \ --cc=gorcunov@gmail.com \ --cc=v.shpilevoy@tarantool.org \ --subject='Re: [Tarantool-patches] [PATCH v14 01/12] box/func: factor out c function entry structure' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox