diff options
Diffstat (limited to 'erts/emulator/test/nif_SUITE_data')
-rw-r--r-- | erts/emulator/test/nif_SUITE_data/Makefile.src | 14 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE_data/nif_SUITE.1.c | 2 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 149 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE_data/nif_mod.1.c | 2 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE_data/nif_mod.2.c | 2 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE_data/nif_mod.3.c | 2 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE_data/nif_mod.c | 103 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE_data/nif_mod.erl | 64 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE_data/nif_mod.h | 17 |
9 files changed, 355 insertions, 0 deletions
diff --git a/erts/emulator/test/nif_SUITE_data/Makefile.src b/erts/emulator/test/nif_SUITE_data/Makefile.src new file mode 100644 index 0000000000..6a8b4f1245 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/Makefile.src @@ -0,0 +1,14 @@ + +NIF_LIBS = nif_SUITE.1@dll@ \ + nif_mod.1@dll@ \ + nif_mod.2@dll@ \ + nif_mod.3@dll@ + +all: $(NIF_LIBS) + + +@SHLIB_RULES@ + +$(NIF_LIBS): nif_SUITE.c nif_mod.c nif_mod.h + + diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.1.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.1.c new file mode 100644 index 0000000000..71626043dd --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.1.c @@ -0,0 +1,2 @@ +#define NIF_SUITE_LIB_VER 1 +#include "nif_SUITE.c" diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c new file mode 100644 index 0000000000..852495e234 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -0,0 +1,149 @@ +#include "erl_nif.h" +#include <string.h> +#include <assert.h> + +#include "nif_mod.h" + +static int static_cntA; /* zero by default */ +static int static_cntB = NIF_SUITE_LIB_VER * 100; + +typedef struct +{ + int ref_cnt; + CallInfo* call_history; + NifModPrivData* nif_mod; +}PrivData; + +void add_call(ErlNifEnv* env, PrivData* data, const char* func_name) +{ + CallInfo* call = enif_alloc(env, sizeof(CallInfo)+strlen(func_name)); + strcpy(call->func_name, func_name); + call->lib_ver = NIF_SUITE_LIB_VER; + call->next = data->call_history; + call->static_cntA = ++static_cntA; + call->static_cntB = ++static_cntB; + data->call_history = call; +} + +#define ADD_CALL(FUNC_NAME) add_call(env, enif_get_data(env),FUNC_NAME) + +static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) +{ + PrivData* data = enif_alloc(env, sizeof(PrivData)); + assert(data != NULL); + data->ref_cnt = 1; + data->call_history = NULL; + data->nif_mod = NULL; + + add_call(env, data, "load"); + + *priv_data = data; + return 0; +} + +static int reload(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) +{ + add_call(env, *priv_data, "reload"); + return 0; +} + +static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info) +{ + PrivData* data = *old_priv_data; + add_call(env, data, "upgrade"); + data->ref_cnt++; + *priv_data = *old_priv_data; + return 0; +} + +static void unload(ErlNifEnv* env, void* priv_data) +{ + PrivData* data = priv_data; + add_call(env, data, "unload"); + if (--data->ref_cnt == 0) { + enif_free(env, priv_data); + } +} + +static ERL_NIF_TERM lib_version(ErlNifEnv* env) +{ + ADD_CALL("lib_version"); + return enif_make_int(env, NIF_SUITE_LIB_VER); +} + +static ERL_NIF_TERM make_call_history(ErlNifEnv* env, CallInfo** headp) +{ + ERL_NIF_TERM list = enif_make_list(env, 0); /* NIL */ + + while (*headp != NULL) { + CallInfo* call = *headp; + ERL_NIF_TERM tpl = enif_make_tuple(env, 4, + enif_make_atom(env,call->func_name), + enif_make_int(env,call->lib_ver), + enif_make_int(env,call->static_cntA), + enif_make_int(env,call->static_cntB)); + list = enif_make_list_cell(env, tpl, list); + *headp = call->next; + enif_free(env,call); + } + return list; +} + +static ERL_NIF_TERM call_history(ErlNifEnv* env) +{ + PrivData* data = (PrivData*) enif_get_data(env); + + return make_call_history(env,&data->call_history); +} + +static ERL_NIF_TERM hold_nif_mod_priv_data(ErlNifEnv* env, ERL_NIF_TERM a1) +{ + PrivData* data = (PrivData*) enif_get_data(env); + unsigned long ptr_as_ulong; + + if (!enif_get_ulong(env,a1,&ptr_as_ulong)) { + return enif_make_badarg(env); + } + if (data->nif_mod != NULL && --(data->nif_mod->ref_cnt) == 0) { + enif_free(env,data->nif_mod); + } + data->nif_mod = (NifModPrivData*) ptr_as_ulong; + return enif_make_int(env,++(data->nif_mod->ref_cnt)); +} + +static ERL_NIF_TERM nif_mod_call_history(ErlNifEnv* env) +{ + PrivData* data = (PrivData*) enif_get_data(env); + + if (data->nif_mod == NULL) { + return enif_make_string(env,"nif_mod pointer is NULL"); + } + return make_call_history(env,&data->nif_mod->call_history); +} + +static ERL_NIF_TERM list_seq(ErlNifEnv* env, ERL_NIF_TERM a1) +{ + ERL_NIF_TERM list; + int n; + if (!enif_get_int(env, a1, &n)) { + return enif_make_badarg(env); + } + list = enif_make_list(env, 0); /* NIL */ + while (n > 0) { + list = enif_make_list_cell(env, enif_make_int(env,n), list); + n--; + } + return list; +} + +static ErlNifFunc nif_funcs[] = +{ + {"lib_version", 0, lib_version}, + {"call_history", 0, call_history}, + {"hold_nif_mod_priv_data", 1, hold_nif_mod_priv_data}, + {"nif_mod_call_history", 0, nif_mod_call_history}, + {"list_seq", 1, list_seq} +}; + +ERL_NIF_INIT(nif_SUITE,nif_funcs,load,reload,upgrade,unload) + diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.1.c b/erts/emulator/test/nif_SUITE_data/nif_mod.1.c new file mode 100644 index 0000000000..5e508570bd --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.1.c @@ -0,0 +1,2 @@ +#define NIF_LIB_VER 1 +#include "nif_mod.c" diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.2.c b/erts/emulator/test/nif_SUITE_data/nif_mod.2.c new file mode 100644 index 0000000000..5dd5d88766 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.2.c @@ -0,0 +1,2 @@ +#define NIF_LIB_VER 2 +#include "nif_mod.c" diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.3.c b/erts/emulator/test/nif_SUITE_data/nif_mod.3.c new file mode 100644 index 0000000000..8cbcb748a3 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.3.c @@ -0,0 +1,2 @@ +#define NIF_LIB_VER 3 +#include "nif_mod.c" diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.c b/erts/emulator/test/nif_SUITE_data/nif_mod.c new file mode 100644 index 0000000000..18f676335a --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.c @@ -0,0 +1,103 @@ +#include "erl_nif.h" +#include <string.h> +#include <assert.h> + +#include "nif_mod.h" + + +static int static_cntA; /* zero by default */ +static int static_cntB = NIF_LIB_VER * 100; + +static void add_call(ErlNifEnv* env, NifModPrivData* data, const char* func_name) +{ + CallInfo* call = enif_alloc(env, sizeof(CallInfo)+strlen(func_name)); + strcpy(call->func_name, func_name); + call->lib_ver = NIF_LIB_VER; + call->static_cntA = ++static_cntA; + call->static_cntB = ++static_cntB; + call->next = data->call_history; + data->call_history = call; +} + +#define ADD_CALL(FUNC_NAME) add_call(env, enif_get_data(env),FUNC_NAME) + +static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) +{ + NifModPrivData* data = enif_alloc(env, sizeof(NifModPrivData)); + assert(data != NULL); + data->ref_cnt = 1; + data->call_history = NULL; + add_call(env, data, "load"); + + data->calls = 0; + *priv_data = data; + return 0; +} + +static int reload(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) +{ + add_call(env, *priv_data, "reload"); + return 0; +} + +static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info) +{ + NifModPrivData* data = *old_priv_data; + add_call(env, data, "upgrade"); + data->ref_cnt++; + *priv_data = *old_priv_data; + return 0; +} + +static void unload(ErlNifEnv* env, void* priv_data) +{ + NifModPrivData* data = priv_data; + add_call(env, data, "unload"); + if (--data->ref_cnt == 0) { + enif_free(env, data); + } +} + +static ERL_NIF_TERM lib_version(ErlNifEnv* env) +{ + ADD_CALL("lib_version"); + return enif_make_int(env, NIF_LIB_VER); +} + +static ERL_NIF_TERM call_history(ErlNifEnv* env) +{ + NifModPrivData* data = (NifModPrivData*) enif_get_data(env); + ERL_NIF_TERM list = enif_make_list(env, 0); /* NIL */ + + while (data->call_history != NULL) { + CallInfo* call = data->call_history; + ERL_NIF_TERM tpl = enif_make_tuple(env, 2, + enif_make_atom(env,call->func_name), + enif_make_int(env,call->lib_ver)); + list = enif_make_list_cell(env, tpl, list); + data->call_history = call->next; + enif_free(env,call); + } + return list; +} + +static ERL_NIF_TERM get_priv_data_ptr(ErlNifEnv* env) +{ + ADD_CALL("get_priv_data_ptr"); + return enif_make_ulong(env, (unsigned long)enif_get_data(env)); +} + + +static ErlNifFunc nif_funcs[] = +{ + {"lib_version", 0, lib_version}, + {"call_history", 0, call_history}, + {"get_priv_data_ptr", 0, get_priv_data_ptr} +}; + +#if NIF_LIB_VER != 3 +ERL_NIF_INIT(nif_mod,nif_funcs,load,reload,upgrade,unload) +#else +ERL_NIF_INIT_GLOB /* avoid link error on windows */ +#endif + diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.erl b/erts/emulator/test/nif_SUITE_data/nif_mod.erl new file mode 100644 index 0000000000..93da6590a0 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.erl @@ -0,0 +1,64 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(nif_mod). + +-include("test_server.hrl"). + +-export([load_nif_lib/2, start/0, lib_version/0, call_history/0, get_priv_data_ptr/0]). + +-export([loop/0, upgrade/1]). + +-define(nif_stub,nif_stub_error(?LINE)). + +load_nif_lib(Config, Ver) -> + ?line Path = ?config(data_dir, Config), + erlang:load_nif(filename:join(Path,libname(Ver)), 0). + +libname(no_init) -> libname(3); +libname(Ver) when is_integer(Ver) -> + "nif_mod." ++ integer_to_list(Ver). + +start() -> + spawn_opt(?MODULE,loop,[], + [link, monitor]). + +loop() -> + receive + {Pid,lib_version} -> + Pid ! {self(),lib_version()}, + loop(); + {Pid,upgrade} -> + ?MODULE:upgrade(Pid); + die -> + void + end. + +upgrade(Pid) -> + Pid ! {self(),upgraded}, + loop(). + +lib_version() -> % NIF + undefined. + +call_history() -> ?nif_stub. +get_priv_data_ptr() -> ?nif_stub. + +nif_stub_error(Line) -> + exit({nif_not_loaded,module,?MODULE,line,Line}). diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.h b/erts/emulator/test/nif_SUITE_data/nif_mod.h new file mode 100644 index 0000000000..2dfdc75176 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.h @@ -0,0 +1,17 @@ +typedef struct call_info_t +{ + struct call_info_t* next; + unsigned lib_ver; + int static_cntA; + int static_cntB; + char func_name[1]; /* must be last */ +}CallInfo; + + +typedef struct +{ + int calls; + int ref_cnt; + CallInfo* call_history; +}NifModPrivData; + |