diff options
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r-- | erts/emulator/beam/erl_nif.c | 18 | ||||
-rw-r--r-- | erts/emulator/beam/erl_nif.h | 15 | ||||
-rwxr-xr-x | erts/emulator/beam/global.h | 6 | ||||
-rw-r--r-- | erts/emulator/beam/utils.c | 21 |
4 files changed, 51 insertions, 9 deletions
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 48f8be8dd3..673012a9af 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -1213,7 +1213,8 @@ static void close_lib(struct erl_module_nif* lib) lib->entry->unload(&env, lib->priv_data); post_nif_noproc(&env); } - erts_sys_ddll_close(lib->handle); + if (!erts_is_static_nif(lib->handle)) + erts_sys_ddll_close(lib->handle); lib->handle = NULL; } @@ -1564,7 +1565,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) static const char upgrade[] = "upgrade"; char* lib_name = NULL; void* handle = NULL; - void* init_func; + void* init_func = NULL; ErlNifEntry* entry = NULL; ErlNifEnv env; int len, i, err; @@ -1577,6 +1578,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) int veto; struct erl_module_nif* lib = NULL; int reload_warning = 0; + char tmp_buf[255]; len = list_length(BIF_ARG_1); if (len < 0) { @@ -1613,13 +1615,18 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) mod=erts_get_module(mod_atom, erts_active_code_ix()); ASSERT(mod != NULL); + init_func = erts_static_nif_get_nif_init(erts_basename(lib_name,tmp_buf)); + if (init_func != NULL) + handle = init_func; + if (!in_area(caller, mod->curr.code, mod->curr.code_length)) { ASSERT(in_area(caller, mod->old.code, mod->old.code_length)); ret = load_nif_error(BIF_P, "old_code", "Calling load_nif from old " "module '%T' not allowed", mod_atom); } - else if ((err=erts_sys_ddll_open2(lib_name, &handle, &errdesc)) != ERL_DE_NO_ERROR) { + else if (init_func == NULL && + (err=erts_sys_ddll_open2(lib_name, &handle, &errdesc)) != ERL_DE_NO_ERROR) { const char slogan[] = "Failed to load NIF library"; if (strstr(errdesc.str, lib_name) != NULL) { ret = load_nif_error(BIF_P, "load_failed", "%s: '%s'", slogan, errdesc.str); @@ -1628,7 +1635,8 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) ret = load_nif_error(BIF_P, "load_failed", "%s %s: '%s'", slogan, lib_name, errdesc.str); } } - else if (erts_sys_ddll_load_nif_init(handle, &init_func, &errdesc) != ERL_DE_NO_ERROR) { + else if (init_func == NULL && + erts_sys_ddll_load_nif_init(handle, &init_func, &errdesc) != ERL_DE_NO_ERROR) { ret = load_nif_error(BIF_P, bad_lib, "Failed to find library init" " function: '%s'", errdesc.str); @@ -1784,7 +1792,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) if (lib != NULL) { erts_free(ERTS_ALC_T_NIF, lib); } - if (handle != NULL) { + if (handle != NULL && !erts_is_static_nif(handle)) { erts_sys_ddll_close(handle); } erts_sys_ddll_free_error(&errdesc); diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h index 8006741a63..5f4dc21d5c 100644 --- a/erts/emulator/beam/erl_nif.h +++ b/erts/emulator/beam/erl_nif.h @@ -168,7 +168,7 @@ extern TWinDynNifCallbacks WinDynNifCallbacks; # undef ERL_NIF_API_FUNC_DECL #endif -#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) && !defined(STATIC_ERLANG_DRIVER) +#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) && !defined(STATIC_ERLANG_DRIVER) && !defined(STATIC_ERLANG_NIF) # define ERL_NIF_API_FUNC_MACRO(NAME) (WinDynNifCallbacks.NAME) # include "erl_nif_api_funcs.h" /* note that we have to keep ERL_NIF_API_FUNC_MACRO defined */ @@ -180,15 +180,22 @@ extern TWinDynNifCallbacks WinDynNifCallbacks; # undef ERL_NIF_API_FUNC_DECL #endif - #if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) # define ERL_NIF_INIT_GLOB TWinDynNifCallbacks WinDynNifCallbacks; -# define ERL_NIF_INIT_DECL(MODNAME) __declspec(dllexport) ErlNifEntry* nif_init(TWinDynNifCallbacks* callbacks) +# ifdef STATIC_ERLANG_NIF +# define ERL_NIF_INIT_DECL(MODNAME) __declspec(dllexport) ErlNifEntry* MODNAME ## _nif_init(TWinDynNifCallbacks* callbacks) +# else +# define ERL_NIF_INIT_DECL(MODNAME) __declspec(dllexport) ErlNifEntry* nif_init(TWinDynNifCallbacks* callbacks) +# endif # define ERL_NIF_INIT_BODY memcpy(&WinDynNifCallbacks,callbacks,sizeof(TWinDynNifCallbacks)) #else # define ERL_NIF_INIT_GLOB # define ERL_NIF_INIT_BODY -# define ERL_NIF_INIT_DECL(MODNAME) ErlNifEntry* nif_init(void) +# ifdef STATIC_ERLANG_NIF +# define ERL_NIF_INIT_DECL(MODNAME) ErlNifEntry* MODNAME ## _nif_init(void) +# else +# define ERL_NIF_INIT_DECL(MODNAME) ErlNifEntry* nif_init(void) +# endif #endif diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 7f7b6f5d1e..2acc86cf42 100755 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -852,11 +852,17 @@ Port *erts_get_heart_port(void); void erts_lcnt_enable_io_lock_count(int enable); #endif +/* driver_tab.c */ +typedef void *(*ErtsStaticNifInitFPtr)(void); +ErtsStaticNifInitFPtr erts_static_nif_get_nif_init(const char *name); +int erts_is_static_nif(void *handle); + /* erl_drv_thread.c */ void erl_drv_thr_init(void); /* utils.c */ void erts_cleanup_offheap(ErlOffHeap *offheap); +const char *erts_basename(const char* path, char* buff); Uint64 erts_timestamp_millis(void); diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c index c71f8f0712..6293286c75 100644 --- a/erts/emulator/beam/utils.c +++ b/erts/emulator/beam/utils.c @@ -4019,6 +4019,27 @@ erts_smp_ensure_later_interval_acqb(erts_interval_t *icp, Uint64 ic) #endif } +const char *erts_basename(const char* path, char* buff) { + /* This function is not compliant with bash basename. Edge cases like "//" + and "/path//" do not work properly. + */ + int i; + int len = strlen(path); + const char *basename = path; + for (i = 0; path[i] != '\0'; i++) { + if (path[i] == '/') { + if (path[i+1] == '\0') { + memcpy(buff,basename,len - (basename-path)); + buff[len - (basename-path)-1] = '\0'; + basename = buff; + break; + } else { basename = path+i;} + } + } + if (basename == path) + return path; + return basename+1; +} /* * A millisecond timestamp without time correction where there's no hrtime |