From 4a736966eba5398a22697db6ca67e1e3dd3cd0f2 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 10 Dec 2015 10:58:33 +0100 Subject: erts: Add enif_cpu/now_time and enif_make_unique_integer --- erts/emulator/beam/erl_nif.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'erts/emulator/beam/erl_nif.c') diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 8580bc2689..703c96777a 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -1158,6 +1158,51 @@ int enif_make_reverse_list(ErlNifEnv* env, ERL_NIF_TERM term, ERL_NIF_TERM *list return 1; } +ERL_NIF_TERM +enif_now_time(ErlNifEnv *env) +{ + Uint mega, sec, micro; + Eterm *hp; + get_now(&mega, &sec, µ); + hp = alloc_heap(env, 4); + return TUPLE3(hp, make_small(mega), make_small(sec), make_small(micro)); +} + +ERL_NIF_TERM +enif_cpu_time(ErlNifEnv *env) +{ +#ifdef HAVE_ERTS_NOW_CPU + Uint mega, sec, micro; + Eterm *hp; + erts_get_now_cpu(&mega, &sec, µ); + hp = alloc_heap(env, 4); + return TUPLE3(hp, make_small(mega), make_small(sec), make_small(micro)); +#else + return enif_make_badarg(env); +#endif +} + +ERL_NIF_TERM +enif_make_unique_integer(ErlNifEnv *env, ErlNifUniqueInteger properties) +{ + int monotonic = properties & ERL_NIF_UNIQUE_MONOTONIC; + int positive = properties & ERL_NIF_UNIQUE_POSITIVE; + Eterm *hp; + Uint hsz; + + if (monotonic) { + Sint64 raw_unique = erts_raw_get_unique_monotonic_integer(); + hsz = erts_raw_unique_monotonic_integer_heap_size(raw_unique, positive); + hp = alloc_heap(env, hsz); + return erts_raw_make_unique_monotonic_integer_value(&hp, raw_unique, positive); + } else { + Uint64 raw_unique[ERTS_UNIQUE_INT_RAW_VALUES]; + erts_raw_get_unique_integer(raw_unique); + hsz = erts_raw_unique_integer_heap_size(raw_unique, positive); + hp = alloc_heap(env, hsz); + return erts_raw_make_unique_integer(&hp, raw_unique, positive); + } +} ErlNifMutex* enif_mutex_create(char *name) { return erl_drv_mutex_create(name); } void enif_mutex_destroy(ErlNifMutex *mtx) { erl_drv_mutex_destroy(mtx); } -- cgit v1.2.3 From 348f3f2ee2d2707e30658c3600e05309ad0e72bf Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 10 Dec 2015 10:59:34 +0100 Subject: erts: Add enif_is_process/port_alive --- erts/emulator/beam/erl_nif.c | 70 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) (limited to 'erts/emulator/beam/erl_nif.c') diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 703c96777a..8440fd26b5 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -404,12 +404,28 @@ static int is_offheap(const ErlOffHeap* oh) ErlNifPid* enif_self(ErlNifEnv* caller_env, ErlNifPid* pid) { + if (caller_env->proc->common.id == ERTS_INVALID_PID) + return NULL; pid->pid = caller_env->proc->common.id; return pid; } + int enif_get_local_pid(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifPid* pid) { - return is_internal_pid(term) ? (pid->pid=term, 1) : 0; + if (is_internal_pid(term)) { + pid->pid=term; + return 1; + } + return 0; +} + +int enif_get_local_port(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifPort* port) +{ + if (is_internal_port(term)) { + port->port_id=term; + return 1; + } + return 0; } int enif_is_atom(ErlNifEnv* env, ERL_NIF_TERM term) @@ -1158,6 +1174,58 @@ int enif_make_reverse_list(ErlNifEnv* env, ERL_NIF_TERM term, ERL_NIF_TERM *list return 1; } +int enif_is_process_alive(ErlNifEnv* env, ErlNifPid *proc) +{ + ErtsProcLocks rp_locks = 0; /* We don't need any locks, + just to check if it is alive */ + Eterm target = proc->pid; + Process* rp; + Process* c_p; + int scheduler = erts_get_scheduler_id() != 0; + + if (env != NULL) { + c_p = env->proc; + if (target == c_p->common.id) { + /* We are alive! */ + return 1; + } + } + else { +#ifdef ERTS_SMP + c_p = NULL; +#else + erts_exit(ERTS_ABORT_EXIT,"enif_is_process_alive: " + "env==NULL on non-SMP VM"); +#endif + } + + rp = (scheduler + ? erts_proc_lookup(target) + : erts_pid2proc_opt(c_p, ERTS_PROC_LOCK_MAIN, + target, rp_locks, ERTS_P2P_FLG_INC_REFC)); + if (rp == NULL) { + ASSERT(env == NULL || target != c_p->common.id); + return 0; + } else { + if (!scheduler) + erts_proc_dec_refc(rp); + return 1; + } +} + +int enif_is_port_alive(ErlNifEnv *env, ErlNifPort *port) +{ + /* only allowed if called from scheduler */ + if (erts_get_scheduler_id() == 0) + erts_exit(ERTS_ABORT_EXIT,"enif_is_port_alive: called from non-scheduler"); + + return erts_port_lookup( + port->port_id, + (erts_port_synchronous_ops + ? ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP + : ERTS_PORT_SFLGS_INVALID_LOOKUP)) != NULL; +} + ERL_NIF_TERM enif_now_time(ErlNifEnv *env) { -- cgit v1.2.3 From 1bd56e2b5141a3afdca4e854e9b667807bf4e2f3 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 17 Dec 2015 14:14:54 +0100 Subject: erts: Add enif_term_to_binary and enif_binary_to_term --- erts/emulator/beam/erl_nif.c | 70 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) (limited to 'erts/emulator/beam/erl_nif.c') diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 8440fd26b5..21bf752bb6 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -638,6 +638,76 @@ unsigned char* enif_make_new_binary(ErlNifEnv* env, size_t size, return binary_bytes(*termp); } +int enif_term_to_binary(ErlNifEnv *dst_env, ERL_NIF_TERM term, + ErlNifBinary *bin) +{ + Sint size; + byte *bp; + Binary* refbin; + + size = erts_encode_ext_size(term); + if (!enif_alloc_binary(size, bin)) + return 0; + + refbin = bin->ref_bin; + + bp = bin->data; + + erts_encode_ext(term, &bp); + + bin->size = bp - bin->data; + refbin->orig_size = bin->size; + + ASSERT(bin->data + bin->size == bp); + + return 1; +} + +int enif_binary_to_term(ErlNifEnv *dst_env, ErlNifBinary *bin, + ERL_NIF_TERM *term) +{ + Sint size; + ErtsHeapFactory factory; + + if ((size = erts_decode_ext_size(bin->data, bin->size)) < 0) + return 0; + + if (size > 0) { + byte *bp; + + if (is_internal_pid(dst_env->proc->common.id)) { + flush_env(dst_env); + erts_factory_proc_prealloc_init(&factory, dst_env->proc, size); + cache_env(dst_env); + } else { + + /* this is guaranteed to create a heap fragment */ + if (!alloc_heap(dst_env, size)) + return 0; + + erts_factory_heap_frag_init(&factory, dst_env->heap_frag); + } + + bp = bin->data; + *term = erts_decode_ext(&factory, &bp); + + if (is_non_value(*term)) { + return 0; + } + + erts_factory_close(&factory); + } + else { + erts_factory_dummy_init(&factory); + *term = erts_decode_ext(&factory, &bin->data); + if (is_non_value(*term)) { + return 0; + } + ASSERT(is_immed(*term)); + } + return 1; +} + int enif_is_identical(Eterm lhs, Eterm rhs) { return EQ(lhs,rhs); -- cgit v1.2.3 From 209c5cf22b5cdc70eb48e6afdcddfa7132471aab Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 1 Feb 2016 11:01:40 +0100 Subject: erts: Add enif_port_command --- erts/emulator/beam/erl_nif.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'erts/emulator/beam/erl_nif.c') diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 21bf752bb6..6ed89780b4 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -375,6 +375,29 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid, return 1; } +int +enif_port_command(ErlNifEnv *env, const ErlNifPort* to_port, + ErlNifEnv *msg_env, ERL_NIF_TERM msg) +{ + + ErtsSchedulerData *esdp = erts_get_scheduler_data(); + int scheduler = esdp ? esdp->no : 0; + Port *prt; + + if (scheduler == 0 || !env) + return 0; + + prt = erts_port_lookup(to_port->port_id, + (erts_port_synchronous_ops + ? ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP + : ERTS_PORT_SFLGS_INVALID_LOOKUP)); + + if (!prt) + return 0; + + return erts_port_output_async(prt, env->proc->common.id, msg); +} + ERL_NIF_TERM enif_make_copy(ErlNifEnv* dst_env, ERL_NIF_TERM src_term) { Uint sz; -- cgit v1.2.3 From a2a86dadc648dda68b5221a7c1d83b9238be1e25 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 12 Feb 2016 18:52:20 +0100 Subject: erts: Improve enif_binary_to_term * Accept a raw data buffer instead of ErlNifBinary * Accept option ERL_NIF_BIN2TERM_SAFE * Return number of read bytes --- erts/emulator/beam/erl_nif.c | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) (limited to 'erts/emulator/beam/erl_nif.c') diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 6ed89780b4..d8f2272c6d 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -686,17 +686,25 @@ int enif_term_to_binary(ErlNifEnv *dst_env, ERL_NIF_TERM term, return 1; } -int enif_binary_to_term(ErlNifEnv *dst_env, ErlNifBinary *bin, - ERL_NIF_TERM *term) +size_t enif_binary_to_term(ErlNifEnv *dst_env, + const unsigned char* data, + size_t data_sz, + ERL_NIF_TERM *term, + ErlNifBinaryToTerm opts) { Sint size; ErtsHeapFactory factory; + byte *bp = (byte*) data; - if ((size = erts_decode_ext_size(bin->data, bin->size)) < 0) + ERTS_CT_ASSERT(ERL_NIF_BIN2TERM_SAFE == ERTS_DIST_EXT_BTT_SAFE); + + if (opts & ~ERL_NIF_BIN2TERM_SAFE) { + return 0; + } + if ((size = erts_decode_ext_size(bp, data_sz)) < 0) return 0; if (size > 0) { - byte *bp; if (is_internal_pid(dst_env->proc->common.id)) { flush_env(dst_env); @@ -710,25 +718,18 @@ int enif_binary_to_term(ErlNifEnv *dst_env, ErlNifBinary *bin, erts_factory_heap_frag_init(&factory, dst_env->heap_frag); } + } else { + erts_factory_dummy_init(&factory); + } - bp = bin->data; - *term = erts_decode_ext(&factory, &bp); - - if (is_non_value(*term)) { - return 0; - } + *term = erts_decode_ext(&factory, &bp, (Uint32)opts); - erts_factory_close(&factory); - } - else { - erts_factory_dummy_init(&factory); - *term = erts_decode_ext(&factory, &bin->data); - if (is_non_value(*term)) { - return 0; - } - ASSERT(is_immed(*term)); + if (is_non_value(*term)) { + return 0; } - return 1; + erts_factory_close(&factory); + ASSERT(bp > data); + return bp - data; } int enif_is_identical(Eterm lhs, Eterm rhs) -- cgit v1.2.3 From 1c630ab8793425aed1e487d25c71b8bbd9325e8b Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 15 Feb 2016 19:28:52 +0100 Subject: erts: Fix bug in enif_term_to_binary Wait until after dec_term and factory_close to do cache_env(), otherwise we will cache the wrong state. --- erts/emulator/beam/erl_nif.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'erts/emulator/beam/erl_nif.c') diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index d8f2272c6d..c6ece8c1c7 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -705,19 +705,8 @@ size_t enif_binary_to_term(ErlNifEnv *dst_env, return 0; if (size > 0) { - - if (is_internal_pid(dst_env->proc->common.id)) { - flush_env(dst_env); - erts_factory_proc_prealloc_init(&factory, dst_env->proc, size); - cache_env(dst_env); - } else { - - /* this is guaranteed to create a heap fragment */ - if (!alloc_heap(dst_env, size)) - return 0; - - erts_factory_heap_frag_init(&factory, dst_env->heap_frag); - } + flush_env(dst_env); + erts_factory_proc_prealloc_init(&factory, dst_env->proc, size); } else { erts_factory_dummy_init(&factory); } @@ -728,6 +717,8 @@ size_t enif_binary_to_term(ErlNifEnv *dst_env, return 0; } erts_factory_close(&factory); + cache_env(dst_env); + ASSERT(bp > data); return bp - data; } -- cgit v1.2.3 From ed81bb9ed8114d2059783e2c2fdae526d3a36e1e Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 15 Feb 2016 19:26:54 +0100 Subject: erts: Fix bug in enif_send Let cache_env() set env->heap_frag to same as MBUF(p) as it is in any other case. --- erts/emulator/beam/erl_nif.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'erts/emulator/beam/erl_nif.c') diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index c6ece8c1c7..beef6983cd 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -209,6 +209,7 @@ static void flush_env(ErlNifEnv* env) */ static void cache_env(ErlNifEnv* env) { + env->heap_frag = MBUF(env->proc); if (env->heap_frag == NULL) { ASSERT(env->hp_end == HEAP_LIMIT(env->proc)); ASSERT(env->hp <= HEAP_TOP(env->proc)); @@ -216,10 +217,6 @@ static void cache_env(ErlNifEnv* env) env->hp = HEAP_TOP(env->proc); } else { - ASSERT(env->hp_end != HEAP_LIMIT(env->proc)); - ASSERT(env->hp_end - env->hp <= env->heap_frag->alloc_size); - env->heap_frag = MBUF(env->proc); - ASSERT(env->heap_frag != NULL); env->hp = env->heap_frag->mem + env->heap_frag->used_size; env->hp_end = env->heap_frag->mem + env->heap_frag->alloc_size; } -- cgit v1.2.3