aboutsummaryrefslogtreecommitdiffstats
path: root/erts/preloaded/src
diff options
context:
space:
mode:
authorRickard Green <[email protected]>2018-03-21 11:54:28 +0100
committerGitHub <[email protected]>2018-03-21 11:54:28 +0100
commitcf3cbf0871832cb0808293842e5ae726edfc12e1 (patch)
treecd67d38d40c3414275ec257a6685b86c949c621a /erts/preloaded/src
parent2c5711efcdd48ab8a9b7cd9ae27c97b9c1f8c37e (diff)
parent4bc282d812cc2c49aa3e2d073e96c720f16aa270 (diff)
downloadotp-cf3cbf0871832cb0808293842e5ae726edfc12e1.tar.gz
otp-cf3cbf0871832cb0808293842e5ae726edfc12e1.tar.bz2
otp-cf3cbf0871832cb0808293842e5ae726edfc12e1.zip
Merge pull request #1740 from rickard-green/rickard/signals/OTP-14589
Implementation of true asynchronous signaling between processes
Diffstat (limited to 'erts/preloaded/src')
-rw-r--r--erts/preloaded/src/Makefile4
-rw-r--r--erts/preloaded/src/erlang.erl36
-rw-r--r--erts/preloaded/src/erts_dirty_process_code_checker.erl81
-rw-r--r--erts/preloaded/src/erts_dirty_process_signal_handler.erl97
-rw-r--r--erts/preloaded/src/erts_internal.erl28
5 files changed, 150 insertions, 96 deletions
diff --git a/erts/preloaded/src/Makefile b/erts/preloaded/src/Makefile
index a2872082f2..4333f6643a 100644
--- a/erts/preloaded/src/Makefile
+++ b/erts/preloaded/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2016. All Rights Reserved.
+# Copyright Ericsson AB 2008-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -47,7 +47,7 @@ PRE_LOADED_ERL_MODULES = \
erts_internal \
erl_tracer \
erts_literal_area_collector \
- erts_dirty_process_code_checker
+ erts_dirty_process_signal_handler
PRE_LOADED_BEAM_MODULES = \
prim_eval
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index 370ecdc3f6..6cfca68a56 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@
-export([localtime_to_universaltime/1]).
-export([suspend_process/1]).
-export([min/2, max/2]).
--export([dmonitor_node/3, dmonitor_p/2]).
+-export([dmonitor_node/3]).
-export([delay_trap/2]).
-export([set_cookie/2, get_cookie/0]).
-export([nodes/0]).
@@ -122,7 +122,7 @@
-export([delete_element/2]).
-export([delete_module/1, demonitor/1, demonitor/2, display/1]).
-export([display_nl/0, display_string/1, erase/0, erase/1]).
--export([error/1, error/2, exit/1, exit/2, external_size/1]).
+-export([error/1, error/2, exit/1, exit/2, exit_signal/2, external_size/1]).
-export([external_size/2, finish_after_on_load/2, finish_loading/1, float/1]).
-export([float_to_binary/1, float_to_binary/2,
float_to_list/1, float_to_list/2, floor/1]).
@@ -786,6 +786,13 @@ exit(_Reason) ->
exit(_Pid, _Reason) ->
erlang:nif_error(undefined).
+%% exit_signal/2
+-spec erlang:exit_signal(Pid, Reason) -> true when
+ Pid :: pid() | port(),
+ Reason :: term().
+exit_signal(_Pid, _Reason) ->
+ erlang:nif_error(undefined).
+
%% external_size/1
-spec erlang:external_size(Term) -> non_neg_integer() when
Term :: term().
@@ -1012,8 +1019,20 @@ group_leader() ->
-spec group_leader(GroupLeader, Pid) -> true when
GroupLeader :: pid(),
Pid :: pid().
-group_leader(_GroupLeader, _Pid) ->
- erlang:nif_error(undefined).
+group_leader(GroupLeader, Pid) ->
+ case case erts_internal:group_leader(GroupLeader, Pid) of
+ false ->
+ Ref = erlang:make_ref(),
+ erts_internal:group_leader(GroupLeader,
+ Pid,
+ Ref),
+ receive {Ref, MsgRes} -> MsgRes end;
+ Res ->
+ Res
+ end of
+ true -> true;
+ Error -> erlang:error(Error, [GroupLeader, Pid])
+ end.
%% halt/0
%% Shadowed by erl_bif_types: erlang:halt/0
@@ -3279,13 +3298,6 @@ dmonitor_node(Node, Flag, Opts) ->
dmonitor_node(Node,Flag,[])
end.
--spec erlang:dmonitor_p('process', pid() | {atom(),atom()}) -> reference().
-dmonitor_p(process, ProcSpec) ->
- %% Only called when auto-connect attempt failed early in VM
- Ref = erlang:make_ref(),
- erlang:self() ! {'DOWN', Ref, process, ProcSpec, noconnection},
- Ref.
-
%%
%% Trap function used when modified timing has been enabled.
%%
diff --git a/erts/preloaded/src/erts_dirty_process_code_checker.erl b/erts/preloaded/src/erts_dirty_process_code_checker.erl
deleted file mode 100644
index 7d3fa264be..0000000000
--- a/erts/preloaded/src/erts_dirty_process_code_checker.erl
+++ /dev/null
@@ -1,81 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
--module(erts_dirty_process_code_checker).
-
--export([start/0]).
-
-%%
-%% The erts_dirty_process_code_checker is started at
-%% VM boot by the VM. It is a spawned as a system
-%% process, i.e, the whole VM will terminate if
-%% this process terminates.
-%%
-start() ->
- process_flag(trap_exit, true),
- msg_loop().
-
-msg_loop() ->
- _ = receive
- Request ->
- handle_request(Request)
- end,
- msg_loop().
-
-check_process(Requester, Target, ReqId, Module) ->
- Result = erts_internal:check_dirty_process_code(Target, Module),
- Requester ! {check_process_code, ReqId, Result}.
-
-handle_request({Requester,
- Target,
- Prio,
- {check_process_code,
- ReqId,
- Module} = Op}) ->
- %%
- %% Target may have stopped executing dirty since the
- %% initial request was made. Check its current state
- %% and try to send the request if possible; otherwise,
- %% check the dirty executing process and send the result...
- %%
- try
- case erts_internal:is_process_executing_dirty(Target) of
- true ->
- check_process(Requester, Target, ReqId, Module);
- false ->
- case erts_internal:request_system_task(Requester,
- Target,
- Prio,
- Op) of
- ok ->
- ok;
- dirty_execution ->
- check_process(Requester, Target, ReqId, Module)
- end
- end
- catch
- _ : _ ->
- ok %% Ignore all failures; someone passed us garbage...
- end;
-handle_request(_Garbage) ->
- ignore.
-
-
-
diff --git a/erts/preloaded/src/erts_dirty_process_signal_handler.erl b/erts/preloaded/src/erts_dirty_process_signal_handler.erl
new file mode 100644
index 0000000000..ab71790b9d
--- /dev/null
+++ b/erts/preloaded/src/erts_dirty_process_signal_handler.erl
@@ -0,0 +1,97 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(erts_dirty_process_signal_handler).
+
+-export([start/0]).
+
+%%
+%% The erts_dirty_process_signal_handler is started at
+%% VM boot by the VM. It is a spawned as a system
+%% process, i.e, the whole VM will terminate if
+%% this process terminates.
+%%
+start() ->
+ process_flag(trap_exit, true),
+ msg_loop().
+
+msg_loop() ->
+ _ = receive
+ Request ->
+ try
+ handle_request(Request)
+ catch
+ _ : _ ->
+ %% Ignore all failures;
+ %% someone passed us garbage...
+ ok
+ end
+ end,
+ msg_loop().
+
+handle_request(Pid) when is_pid(Pid) ->
+ handle_incoming_signals(Pid, 0);
+handle_request({Requester, Target, Prio,
+ {SysTaskOp, ReqId, Arg} = Op} = Request) ->
+ case handle_sys_task(Requester, Target, SysTaskOp, ReqId, Arg) of
+ true ->
+ ok;
+ false ->
+ %% Target has stopped executing dirty since the
+ %% initial request was made. Dispatch the
+ %% request to target and let it handle it itself...
+ case erts_internal:request_system_task(Requester,
+ Target,
+ Prio,
+ Op) of
+ ok ->
+ ok;
+ dirty_execution ->
+ %% Ahh... It began executing dirty again...
+ handle_request(Request)
+ end
+ end;
+handle_request(_Garbage) ->
+ ignore.
+
+%%
+%% ----------------------------------------------------------------------------
+%%
+
+handle_incoming_signals(Pid, 5) ->
+ self() ! Pid; %% Work with other requests for a while...
+handle_incoming_signals(Pid, N) ->
+ case erts_internal:dirty_process_handle_signals(Pid) of
+ more -> handle_incoming_signals(Pid, N+1);
+ _Res -> ok
+ end.
+
+handle_sys_task(Requester, Target, check_process_code, ReqId, Module) ->
+ case erts_internal:is_process_executing_dirty(Target) of
+ false ->
+ false;
+ true ->
+ _ = check_process(Requester, Target, ReqId, Module),
+ true
+ end.
+
+check_process(Requester, Target, ReqId, Module) ->
+ Result = erts_internal:check_dirty_process_code(Target, Module),
+ Requester ! {check_process_code, ReqId, Result}.
diff --git a/erts/preloaded/src/erts_internal.erl b/erts/preloaded/src/erts_internal.erl
index a51c0c4c0e..21f228395e 100644
--- a/erts/preloaded/src/erts_internal.erl
+++ b/erts/preloaded/src/erts_internal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -45,6 +45,8 @@
-export([check_process_code/3]).
-export([check_dirty_process_code/2]).
-export([is_process_executing_dirty/1]).
+-export([dirty_process_handle_signals/1]).
+
-export([release_literal_area_switch/0]).
-export([purge_module/2]).
@@ -71,6 +73,8 @@
gather_sched_wall_time_result/1,
await_sched_wall_time_modifications/2]).
+-export([group_leader/2, group_leader/3]).
+
%% Auto import name clash
-export([check_process_code/1]).
@@ -306,6 +310,13 @@ check_dirty_process_code(_Pid,_Module) ->
is_process_executing_dirty(_Pid) ->
erlang:nif_error(undefined).
+-spec dirty_process_handle_signals(Pid) -> Res when
+ Pid :: pid(),
+ Res :: 'false' | 'true' | 'noproc' | 'normal' | 'more' | 'ok'.
+
+dirty_process_handle_signals(_Pid) ->
+ erlang:nif_error(undefined).
+
-spec release_literal_area_switch() -> 'true' | 'false'.
release_literal_area_switch() ->
@@ -574,3 +585,18 @@ sched_wall_time(Ref, N, Acc) ->
{Ref, SWTL} when erlang:is_list(SWTL) -> sched_wall_time(Ref, N-1, Acc ++ SWTL);
{Ref, SWT} -> sched_wall_time(Ref, N-1, [SWT|Acc])
end.
+
+-spec erts_internal:group_leader(GL, Pid) -> true | false | badarg when
+ GL :: pid(),
+ Pid :: pid().
+
+group_leader(_GL, _Pid) ->
+ erlang:nif_error(undefined).
+
+-spec erts_internal:group_leader(GL, Pid, Ref) -> ok when
+ GL :: pid(),
+ Pid :: pid(),
+ Ref :: reference().
+
+group_leader(_GL, _Pid, _Ref) ->
+ erlang:nif_error(undefined).