aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator
diff options
context:
space:
mode:
authorRickard Green <[email protected]>2017-01-23 17:16:28 +0100
committerRickard Green <[email protected]>2017-02-06 19:54:48 +0100
commit7fee9c57d89be05c980d1684329b26ac991bb26a (patch)
tree09b0d4f3478a1f79ccb308839e08c70d3746ad32 /erts/emulator
parentb079018e38272604ffacfece9b97924a9e39df5c (diff)
downloadotp-7fee9c57d89be05c980d1684329b26ac991bb26a.tar.gz
otp-7fee9c57d89be05c980d1684329b26ac991bb26a.tar.bz2
otp-7fee9c57d89be05c980d1684329b26ac991bb26a.zip
Use magic refs for NIF resources
Diffstat (limited to 'erts/emulator')
-rw-r--r--erts/emulator/beam/erl_nif.c32
-rw-r--r--erts/emulator/test/nif_SUITE.erl9
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_SUITE.c56
3 files changed, 61 insertions, 36 deletions
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index 20b00bd4ba..1de56ce0a1 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -2209,34 +2209,40 @@ ERL_NIF_TERM enif_make_resource(ErlNifEnv* env, void* obj)
{
ErlNifResource* resource = DATA_TO_RESOURCE(obj);
ErtsBinary* bin = ERTS_MAGIC_BIN_FROM_UNALIGNED_DATA(resource);
- Eterm* hp = alloc_heap(env,PROC_BIN_SIZE);
- return erts_mk_magic_binary_term(&hp, &MSO(env->proc), &bin->binary);
+ Eterm* hp = alloc_heap(env, ERTS_MAGIC_REF_THING_SIZE);
+ return erts_mk_magic_ref(&hp, &MSO(env->proc), &bin->binary);
}
ERL_NIF_TERM enif_make_resource_binary(ErlNifEnv* env, void* obj,
const void* data, size_t size)
{
- Eterm bin = enif_make_resource(env, obj);
- ProcBin* pb = (ProcBin*) binary_val(bin);
+ ErlNifResource* resource = DATA_TO_RESOURCE(obj);
+ ErtsBinary* bin = ERTS_MAGIC_BIN_FROM_UNALIGNED_DATA(resource);
+ Eterm* hp = alloc_heap(env,PROC_BIN_SIZE);
+ Eterm ebin = erts_mk_magic_binary_term(&hp, &MSO(env->proc), &bin->binary);
+ ProcBin* pb = (ProcBin*) binary_val(ebin);
pb->bytes = (byte*) data;
pb->size = size;
- return bin;
+ return ebin;
}
int enif_get_resource(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifResourceType* type,
void** objp)
{
- ProcBin* pb;
Binary* mbin;
ErlNifResource* resource;
- if (!ERTS_TERM_IS_MAGIC_BINARY(term)) {
- return 0;
+ if (is_internal_magic_ref(term))
+ mbin = erts_magic_ref2bin(term);
+ else {
+ ProcBin* pb;
+ if (!ERTS_TERM_IS_MAGIC_BINARY(term))
+ return 0;
+ pb = (ProcBin*) binary_val(term);
+ /*if (pb->size != 0) {
+ return 0; / * Or should we allow "resource binaries" as handles? * /
+ }*/
+ mbin = pb->val;
}
- pb = (ProcBin*) binary_val(term);
- /*if (pb->size != 0) {
- return 0; / * Or should we allow "resource binaries" as handles? * /
- }*/
- mbin = pb->val;
resource = (ErlNifResource*) ERTS_MAGIC_BIN_UNALIGNED_DATA(mbin);
if (ERTS_MAGIC_BIN_DESTRUCTOR(mbin) != &nif_resource_dtor
|| resource->type != type) {
diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl
index 36d512e388..8959be8690 100644
--- a/erts/emulator/test/nif_SUITE.erl
+++ b/erts/emulator/test/nif_SUITE.erl
@@ -748,7 +748,7 @@ resource_hugo_do(Type) ->
HugoBin = <<"Hugo Hacker">>,
HugoPtr = alloc_resource(Type, HugoBin),
Hugo = make_resource(HugoPtr),
- <<>> = Hugo,
+ true = is_reference(Hugo),
release_resource(HugoPtr),
erlang:garbage_collect(),
{HugoPtr,HugoBin} = get_resource(Type,Hugo),
@@ -782,7 +782,7 @@ resource_otto_do(Type) ->
OttoBin = <<"Otto Ordonnans">>,
OttoPtr = alloc_resource(Type, OttoBin),
Otto = make_resource(OttoPtr),
- <<>> = Otto,
+ true = is_reference(Otto),
%% forget resource term but keep referenced by NIF
{OttoPtr, OttoBin}.
@@ -805,8 +805,9 @@ resource_new_do2(Type) ->
BinB = <<"NewB">>,
ResA = make_new_resource(Type, BinA),
ResB = make_new_resource(Type, BinB),
- <<>> = ResA,
- <<>> = ResB,
+ true = is_reference(ResA),
+ true = is_reference(ResB),
+ ResA /= ResB,
{PtrA,BinA} = get_resource(Type, ResA),
{PtrB,BinB} = get_resource(Type, ResB),
true = (PtrA =/= PtrB),
diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
index 4decb7f418..7331c5b2cd 100644
--- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
+++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
@@ -1027,6 +1027,7 @@ struct make_term_info
unsigned reuse_push;
unsigned reuse_pull;
ErlNifResourceType* resource_type;
+ void *resource;
ERL_NIF_TERM other_term;
ERL_NIF_TERM blob;
ErlNifPid to_pid;
@@ -1139,12 +1140,7 @@ static ERL_NIF_TERM make_term_list0(struct make_term_info* mti, int n)
}
static ERL_NIF_TERM make_term_resource(struct make_term_info* mti, int n)
{
- void* resource = enif_alloc_resource(mti->resource_type, 10);
- ERL_NIF_TERM term;
- fill(resource, 10, n);
- term = enif_make_resource(mti->dst_env, resource);
- enif_release_resource(resource);
- return term;
+ return enif_make_resource(mti->dst_env, mti->resource);
}
static ERL_NIF_TERM make_term_new_binary(struct make_term_info* mti, int n)
{
@@ -1249,23 +1245,39 @@ static int make_term_n(struct make_term_info* mti, int n, ERL_NIF_TERM* res)
return 0;
}
-static ERL_NIF_TERM make_blob(ErlNifEnv* caller_env, ErlNifEnv* dst_env,
- ERL_NIF_TERM other_term)
+
+static void
+init_make_blob(struct make_term_info *mti,
+ ErlNifEnv* caller_env,
+ ERL_NIF_TERM other_term)
{
PrivData* priv = (PrivData*) enif_priv_data(caller_env);
+ mti->caller_env = caller_env;
+ mti->resource_type = priv->rt_arr[0].t;
+ mti->resource = enif_alloc_resource(mti->resource_type, 10);
+ fill(mti->resource, 10, 17);
+ mti->other_term = other_term;
+}
+
+static void
+fini_make_blob(struct make_term_info *mti)
+{
+ enif_release_resource(mti->resource);
+}
+
+static ERL_NIF_TERM make_blob(struct make_term_info *mti,
+ ErlNifEnv* dst_env)
+{
ERL_NIF_TERM term, list;
int n = 0;
- struct make_term_info mti;
- mti.caller_env = caller_env;
- mti.dst_env = dst_env;
- mti.dst_env_valid = 1;
- mti.reuse_push = 0;
- mti.reuse_pull = 0;
- mti.resource_type = priv->rt_arr[0].t;
- mti.other_term = other_term;
+
+ mti->reuse_push = 0;
+ mti->reuse_pull = 0;
+ mti->dst_env = dst_env;
+ mti->dst_env_valid = 1;
list = enif_make_list(dst_env, 0);
- while (make_term_n(&mti, n++, &term)) {
+ while (make_term_n(mti, n++, &term)) {
list = enif_make_list_cell(dst_env, term, list);
}
return list;
@@ -1277,13 +1289,16 @@ static ERL_NIF_TERM send_new_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
ERL_NIF_TERM msg, copy;
ErlNifEnv* msg_env;
int res;
+ struct make_term_info mti;
if (!enif_get_local_pid(env, argv[0], &to)) {
return enif_make_badarg(env);
}
msg_env = enif_alloc_env();
- msg = make_blob(env,msg_env, argv[1]);
- copy = make_blob(env,env, argv[1]);
+ init_make_blob(&mti, env, argv[1]);
+ msg = make_blob(&mti,msg_env);
+ copy = make_blob(&mti,env);
+ fini_make_blob(&mti);
res = enif_send(env, &to, msg_env, msg);
enif_free_env(msg_env);
return enif_make_tuple3(env, atom_ok, enif_make_int(env,res), copy);
@@ -1303,6 +1318,8 @@ static ERL_NIF_TERM alloc_msgenv(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
mti->reuse_push = 0;
mti->reuse_pull = 0;
mti->resource_type = priv->rt_arr[0].t;
+ mti->resource = enif_alloc_resource(mti->resource_type, 10);
+ fill(mti->resource, 10, 17);
mti->other_term = enif_make_list(mti->dst_env, 0);
mti->blob = enif_make_list(mti->dst_env, 0);
mti->mtx = enif_mutex_create("nif_SUITE:mtx");
@@ -1320,6 +1337,7 @@ static void msgenv_dtor(ErlNifEnv* env, void* obj)
if (mti->dst_env != NULL) {
enif_free_env(mti->dst_env);
}
+ enif_release_resource(mti->resource);
enif_mutex_destroy(mti->mtx);
enif_cond_destroy(mti->cond);
}