aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/test/nif_SUITE_data
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/test/nif_SUITE_data')
-rw-r--r--erts/emulator/test/nif_SUITE_data/Makefile.src14
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_SUITE.1.c2
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_SUITE.c149
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_mod.1.c2
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_mod.2.c2
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_mod.3.c2
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_mod.c103
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_mod.erl64
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_mod.h17
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;
+