aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2015-12-10 10:59:34 +0100
committerLukas Larsson <[email protected]>2016-03-29 14:57:10 +0200
commit348f3f2ee2d2707e30658c3600e05309ad0e72bf (patch)
tree8557d5468c3a3b68bf55ac586b9c7b322e4f3198 /erts/emulator/beam
parent4a736966eba5398a22697db6ca67e1e3dd3cd0f2 (diff)
downloadotp-348f3f2ee2d2707e30658c3600e05309ad0e72bf.tar.gz
otp-348f3f2ee2d2707e30658c3600e05309ad0e72bf.tar.bz2
otp-348f3f2ee2d2707e30658c3600e05309ad0e72bf.zip
erts: Add enif_is_process/port_alive
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/erl_nif.c70
-rw-r--r--erts/emulator/beam/erl_nif.h7
-rw-r--r--erts/emulator/beam/erl_nif_api_funcs.h6
3 files changed, 81 insertions, 2 deletions
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)
{
diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h
index 959fcb5412..6ee22a693c 100644
--- a/erts/emulator/beam/erl_nif.h
+++ b/erts/emulator/beam/erl_nif.h
@@ -150,7 +150,12 @@ typedef enum
typedef struct
{
ERL_NIF_TERM pid; /* internal, may change */
-}ErlNifPid;
+} ErlNifPid;
+
+typedef struct
+{
+ ERL_NIF_TERM port_id; /* internal, may change */
+}ErlNifPort;
typedef ErlDrvSysInfo ErlNifSysInfo;
diff --git a/erts/emulator/beam/erl_nif_api_funcs.h b/erts/emulator/beam/erl_nif_api_funcs.h
index 3fe60e3df8..21864c8b35 100644
--- a/erts/emulator/beam/erl_nif_api_funcs.h
+++ b/erts/emulator/beam/erl_nif_api_funcs.h
@@ -166,6 +166,9 @@ ERL_NIF_API_FUNC_DECL(ErlNifTime, enif_convert_time_unit, (ErlNifTime, ErlNifTim
ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM, enif_now_time, (ErlNifEnv *env));
ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM, enif_cpu_time, (ErlNifEnv *env));
ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM, enif_make_unique_integer, (ErlNifEnv *env, ErlNifUniqueInteger properties));
+ERL_NIF_API_FUNC_DECL(int, enif_is_process_alive, (ErlNifEnv *env, ErlNifPid *pid));
+ERL_NIF_API_FUNC_DECL(int, enif_is_port_alive, (ErlNifEnv *env, ErlNifPort *port_id));
+ERL_NIF_API_FUNC_DECL(int, enif_get_local_port, (ErlNifEnv* env, ERL_NIF_TERM, ErlNifPort* port_id));
/*
** ADD NEW ENTRIES HERE (before this comment) !!!
@@ -324,6 +327,9 @@ ERL_NIF_API_FUNC_DECL(int,enif_is_on_dirty_scheduler,(ErlNifEnv*));
# define enif_now_time ERL_NIF_API_FUNC_MACRO(enif_now_time)
# define enif_cpu_time ERL_NIF_API_FUNC_MACRO(enif_cpu_time)
# define enif_make_unique_integer ERL_NIF_API_FUNC_MACRO(enif_make_unique_integer)
+# define enif_is_process_alive ERL_NIF_API_FUNC_MACRO(enif_is_process_alive)
+# define enif_is_port_alive ERL_NIF_API_FUNC_MACRO(enif_is_port_alive)
+# define enif_get_local_port ERL_NIF_API_FUNC_MACRO(enif_get_local_port)
/*
** ADD NEW ENTRIES HERE (before this comment)