From: Cyrill Gorcunov <gorcunov@gmail.com> To: tml <tarantool-patches@dev.tarantool.org> Cc: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>, Alexander Turenko <alexander.turenko@tarantool.org> Subject: [Tarantool-patches] [PATCH v4 1/6] box/func: factor out c function entry structure Date: Thu, 1 Oct 2020 16:51:08 +0300 [thread overview] Message-ID: <20201001135113.329664-2-gorcunov@gmail.com> (raw) In-Reply-To: <20201001135113.329664-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 | 156 +++++++++++++++++++++++-------------------------- src/box/func.h | 43 ++++++++++++++ 2 files changed, 116 insertions(+), 83 deletions(-) diff --git a/src/box/func.c b/src/box/func.c index 8087c953f..75d2abb5f 100644 --- a/src/box/func.c +++ b/src/box/func.c @@ -59,19 +59,9 @@ 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 +361,53 @@ 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); + + struct module *module = module_cache_find(name.package, + name.package_end); + if (module == NULL) { + /* Try to find loaded module in the cache */ + module = module_load(name.package, name.package_end); + if (module == NULL) + return -1; + if (module_cache_put(module)) { + module_delete(module); + return -1; + } + } + + mod_sym->addr = module_sym(module, name.sym); + if (mod_sym->addr == NULL) + 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 +422,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 +445,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 +455,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,79 +522,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 *module = module_cache_find(name.package, - name.package_end); - if (module == NULL) { - /* Try to find loaded module in the cache */ - module = module_load(name.package, name.package_end); - if (module == NULL) - return -1; - if (module_cache_put(module)) { - module_delete(module); - return -1; - } - } - - func->func = module_sym(module, name.sym); - if (func->func == NULL) - 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; } @@ -571,10 +561,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..acf2df9a9 100644 --- a/src/box/func.h +++ b/src/box/func.h @@ -58,6 +58,29 @@ 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; + /** + * Each stored function keeps a handle to the + * dynamic library for the C callback. + */ + struct module *module; + /** + * Function name definition. + */ + char *name; +}; + /** Virtual method table for func object. */ struct func_vtab { /** Call function with given arguments. */ @@ -108,6 +131,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.26.2
next prev parent reply other threads:[~2020-10-01 13:51 UTC|newest] Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-10-01 13:51 [Tarantool-patches] [PATCH v4 0/6] box/func: implement cfunc Lua module Cyrill Gorcunov 2020-10-01 13:51 ` Cyrill Gorcunov [this message] 2020-10-01 13:51 ` [Tarantool-patches] [PATCH v4 2/6] box/func: provide module_sym_call Cyrill Gorcunov 2020-10-01 13:51 ` [Tarantool-patches] [PATCH v4 3/6] box/func: more detailed error in module reloading Cyrill Gorcunov 2020-10-01 13:51 ` [Tarantool-patches] [PATCH v4 4/6] box/func: export func_split_name helper Cyrill Gorcunov 2020-10-01 13:51 ` [Tarantool-patches] [PATCH v4 5/6] box/func: implement cfunc Lua module Cyrill Gorcunov 2020-10-03 13:55 ` Vladislav Shpilevoy 2020-10-05 10:31 ` Cyrill Gorcunov 2020-10-05 21:59 ` Vladislav Shpilevoy 2020-10-06 12:55 ` Cyrill Gorcunov 2020-10-01 13:51 ` [Tarantool-patches] [PATCH v4 6/6] test: box/cfunc -- add simple module test Cyrill Gorcunov 2020-10-03 13:55 ` Vladislav Shpilevoy 2020-10-03 13:55 ` [Tarantool-patches] [PATCH v4 0/6] box/func: implement cfunc Lua module Vladislav Shpilevoy 2020-10-05 11:51 ` Cyrill Gorcunov 2020-10-05 21:59 ` Vladislav Shpilevoy
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=20201001135113.329664-2-gorcunov@gmail.com \ --to=gorcunov@gmail.com \ --cc=alexander.turenko@tarantool.org \ --cc=tarantool-patches@dev.tarantool.org \ --cc=v.shpilevoy@tarantool.org \ --subject='Re: [Tarantool-patches] [PATCH v4 1/6] 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