Skip to content

Commit af32e12

Browse files
committed
Fix driver usage of ports
- Fix i2c and spi esp32 native code to use ports - Fix `whereis/1` and `register/2` to work with ports - Fix specifications related to ports - Fix documentation of `register/2` Signed-off-by: Paul Guyot <pguyot@kallisys.net>
1 parent 095e61a commit af32e12

File tree

21 files changed

+135
-114
lines changed

21 files changed

+135
-114
lines changed

UPDATING.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
by using `term_port_from_local_process_id` instead of `term_from_local_process_id`. Sockets, from
1212
port socket driver, are also represented by a port and some matching code may need to be updated from
1313
`is_pid/1` to `is_port/1`.
14+
- Ports and pids can be registered. Function `globalcontext_get_registered_process` result now is
15+
a term that can be a `port()` or a `pid()`.
1416

1517
## v0.6.4 -> v0.6.5
1618

libs/eavmlib/src/console.erl

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
%%-----------------------------------------------------------------------------
4141
-spec puts(iodata()) -> ok | {error, term()}.
4242
puts(Text) ->
43-
puts(get_pid(), Text).
43+
puts(get_port(), Text).
4444

4545
%% @hidden
4646
-spec puts(pid(), iodata()) -> ok.
@@ -55,7 +55,7 @@ puts(Console, Text) ->
5555
%%-----------------------------------------------------------------------------
5656
-spec flush() -> ok | {error, term()}.
5757
flush() ->
58-
flush(get_pid()).
58+
flush(get_port()).
5959

6060
%% @hidden
6161
-spec flush(pid()) -> ok.
@@ -77,18 +77,18 @@ print(_Text) ->
7777
%% Internal operations
7878

7979
%% @private
80-
-spec get_pid() -> pid().
81-
get_pid() ->
80+
-spec get_port() -> port().
81+
get_port() ->
8282
case whereis(console) of
8383
undefined ->
8484
start();
85-
Pid when is_pid(Pid) ->
86-
Pid
85+
Port when is_port(Port) ->
86+
Port
8787
end.
8888

8989
%% @private
90-
-spec start() -> pid().
90+
-spec start() -> port().
9191
start() ->
92-
Pid = erlang:open_port({spawn, "console"}, []),
93-
erlang:register(console, Pid),
94-
Pid.
92+
Port = erlang:open_port({spawn, "console"}, []),
93+
erlang:register(console, Port),
94+
Port.

libs/eavmlib/src/gpio.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
detach_interrupt/1
5858
]).
5959

60-
-type gpio() :: pid().
60+
-type gpio() :: port().
6161
%% This is the pid returned by `gpio:start/0'.
6262
-type pin() :: non_neg_integer() | pin_tuple().
6363
%% The pin definition for ESP32 and PR2040 is a non-negative integer. A tuple is used on the STM32 platform and for the extra "WL" pins on the Pico-W.

libs/eavmlib/src/i2c.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
| {use_nif, boolean()}
6767
| {send_timeout_ms, non_neg_integer()}.
6868
-type params() :: [param()].
69-
-type i2c() :: pid() | {'$i2c', term(), reference()}.
69+
-type i2c() :: port() | {'$i2c', term(), reference()}.
7070
-type address() :: non_neg_integer().
7171
-type register() :: non_neg_integer().
7272

libs/eavmlib/src/network.erl

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -462,20 +462,22 @@ maybe_callback1({Key, Arg} = Msg, Config) ->
462462
end.
463463

464464
%% @private
465+
-spec get_port() -> port().
465466
get_port() ->
466467
case whereis(network_port) of
467468
undefined ->
468469
open_port();
469-
Pid ->
470-
Pid
470+
Port ->
471+
Port
471472
end.
472473

473474
%% @private
475+
-spec open_port() -> port().
474476
open_port() ->
475-
Pid = erlang:open_port({spawn, "network"}, []),
477+
Port = erlang:open_port({spawn, "network"}, []),
476478
%Pid = spawn(?MODULE, simulation_loop, []),
477-
erlang:register(network_port, Pid),
478-
Pid.
479+
erlang:register(network_port, Port),
480+
Port.
479481

480482
%% @private
481483
wait_for_ip(Timeout) ->

libs/eavmlib/src/port.erl

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
%% The port driver should be initialized with:
2929
%% `open_port({spawn, "Name"}, Param)'
3030
%% Where Name is an atom(), and is the name of the driver. The return from `open_port/2'
31-
%% will be the Pid that will be required for future `port:call/2' or `port:call/3' use.
31+
%% will be the Port that will be required for future `port:call/2' or `port:call/3' use.
3232
%%
3333
%% Examples:
3434
%% ```open_port({spawn, "i2c"}, Param)'''
@@ -41,31 +41,31 @@
4141
-export([call/2, call/3]).
4242

4343
%%-----------------------------------------------------------------------------
44-
%% @param Port Pid to which to send messages
44+
%% @param Port Port to which to send messages
4545
%% @param Message the message to send
4646
%% @returns term() | {error, Reason}.
47-
%% @doc Send a message to a given port driver pid.
47+
%% @doc Send a message to a given port driver.
4848
%%
49-
%% This function is used to send a message to an open port divers pid and will
49+
%% This function is used to send a message to an open port drivers port and will
5050
%% return a term or `{error, Reason}'.
5151
%% @end
5252
%%-----------------------------------------------------------------------------
53-
-spec call(Port :: pid(), Message :: term()) -> term().
53+
-spec call(Port :: port(), Message :: term()) -> term().
5454
call(Port, Message) ->
5555
call(Port, Message, infinity).
5656

5757
%%-----------------------------------------------------------------------------
58-
%% @param Port Pid to which to send messages
58+
%% @param Port Port to which to send messages
5959
%% @param Message the message to send
6060
%% @param Timeout the timeout value in milliseconds
6161
%% @returns term() | {error, Reason}.
62-
%% @doc Send a message to a given port driver pid with a timeout.
62+
%% @doc Send a message to a given port driver with a timeout.
6363
%%
64-
%% This function is used to send a message to an open port divers pid and will return
64+
%% This function is used to send a message to an open port drivers port and will return
6565
%% a term or `{error, Reason}', or`{error, timeout}' if the TimeoutMs is reached first.
6666
%% @end
6767
%%-----------------------------------------------------------------------------
68-
-spec call(Port :: pid(), Message :: term(), Timeout :: timeout()) -> term() | {error, timeout}.
68+
-spec call(Port :: port(), Message :: term(), Timeout :: timeout()) -> term() | {error, timeout}.
6969
call(Port, Message, Timeout) ->
7070
MonitorRef = monitor(port, Port),
7171
Port ! {'$call', {self(), MonitorRef}, Message},

libs/eavmlib/src/spi.erl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
| {device_config, [{device_name(), device_config()}]}
6969
].
7070

71-
-type spi() :: pid().
71+
-type spi() :: port().
7272
-type address() :: non_neg_integer().
7373

7474
-type transaction() :: #{
@@ -244,7 +244,7 @@ write_at(SPI, DeviceName, Address, Len, Data) ->
244244
-spec write(SPI :: spi(), DeviceName :: device_name(), Transaction :: transaction()) ->
245245
ok | {error, Reason :: term()}.
246246
write(SPI, DeviceName, Transaction) when
247-
is_pid(SPI) andalso is_atom(DeviceName) andalso is_map(Transaction)
247+
is_port(SPI) andalso is_atom(DeviceName) andalso is_map(Transaction)
248248
->
249249
port:call(SPI, {write, DeviceName, Transaction}).
250250

@@ -279,7 +279,7 @@ write(SPI, DeviceName, Transaction) when
279279
-spec write_read(SPI :: spi(), DeviceName :: device_name(), Transaction :: transaction()) ->
280280
{ok, ReadData :: binary()} | {error, Reason :: term()}.
281281
write_read(SPI, DeviceName, Transaction) when
282-
is_pid(SPI) andalso is_atom(DeviceName) andalso is_map(Transaction)
282+
is_port(SPI) andalso is_atom(DeviceName) andalso is_map(Transaction)
283283
->
284284
port:call(SPI, {write_read, DeviceName, Transaction}).
285285

libs/eavmlib/src/uart.erl

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,27 @@
2121
-module(uart).
2222
-export([open/1, open/2, close/1, read/1, write/2]).
2323

24+
-spec open(integer() | list() | binary(), [tuple()]) -> port().
2425
open(Name, Opts) ->
2526
open([{peripheral, Name} | Opts]).
2627

28+
-spec open([tuple()]) -> port().
2729
open(Opts) ->
2830
open_port({spawn, "uart"}, migrate_config(Opts)).
2931

30-
close(Pid) ->
31-
port:call(Pid, close).
32+
-spec close(Port :: port()) -> ok | {error, any()}.
33+
close(Port) ->
34+
port:call(Port, close).
3235

33-
read(Pid) ->
34-
port:call(Pid, read).
36+
-spec read(Port :: port()) -> {ok, binary()} | {error, any()}.
37+
read(Port) ->
38+
port:call(Port, read).
3539

36-
write(Pid, B) ->
40+
-spec write(Port :: port(), B :: iolist()) -> ok | {error, any()}.
41+
write(Port, B) ->
3742
case is_iolist(B) of
3843
true ->
39-
port:call(Pid, {write, B});
44+
port:call(Port, {write, B});
4045
false ->
4146
throw(badarg)
4247
end.

libs/estdlib/src/erlang.erl

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,11 @@
160160
| link
161161
| monitor.
162162

163+
-type send_destination() ::
164+
pid()
165+
| port()
166+
| atom().
167+
163168
%%-----------------------------------------------------------------------------
164169
%% @param Time time in milliseconds after which to send the timeout message.
165170
%% @param Dest Pid or server name to which to send the timeout message.
@@ -859,17 +864,16 @@ ref_to_list(_Ref) ->
859864
erlang:nif_error(undefined).
860865

861866
%%-----------------------------------------------------------------------------
862-
%% @param Name name of the process to register
863-
%% @param Pid pid of the process to register
867+
%% @param Name name of the process to register
868+
%% @param PidOrPort pid or port of the process to register
864869
%% @returns `true'
865870
%% @doc Register a name for a given process.
866-
%% Processes can be registered with several names.
867-
%% Unlike Erlang/OTP, ports are not distinguished from processes.
868-
%% Errors with `badarg' if the name is already registered.
871+
%% Errors with `badarg' if the name is already registered or if the process
872+
%% is already registered.
869873
%% @end
870874
%%-----------------------------------------------------------------------------
871-
-spec register(Name :: atom(), Pid :: pid()) -> true.
872-
register(_Name, _Pid) ->
875+
-spec register(Name :: atom(), PidOrPort :: pid() | port()) -> true.
876+
register(_Name, _PidOrPort) ->
873877
erlang:nif_error(undefined).
874878

875879
%%-----------------------------------------------------------------------------
@@ -890,7 +894,7 @@ unregister(_Name) ->
890894
%% @doc Lookup a process by name.
891895
%% @end
892896
%%-----------------------------------------------------------------------------
893-
-spec whereis(Name :: atom()) -> pid() | undefined.
897+
-spec whereis(Name :: atom()) -> pid() | port() | undefined.
894898
whereis(_Name) ->
895899
erlang:nif_error(undefined).
896900

@@ -1002,13 +1006,13 @@ make_ref() ->
10021006
%% @doc Send a message to a given process
10031007
%% @end
10041008
%%-----------------------------------------------------------------------------
1005-
-spec send(Pid :: pid(), Message :: Message) -> Message.
1006-
send(_Pid, _Message) ->
1009+
-spec send(Target :: send_destination(), Message :: Message) -> Message.
1010+
send(_Target, _Message) ->
10071011
erlang:nif_error(undefined).
10081012

10091013
%%-----------------------------------------------------------------------------
1010-
%% @param Type type of monitor to create
1011-
%% @param Pid pid of the object to monitor
1014+
%% @param Type type of monitor to create
1015+
%% @param PidOrPort pid or port of the object to monitor
10121016
%% @returns a monitor reference
10131017
%% @doc Create a monitor on a process or on a port.
10141018
%% When the process or the port terminates, the following message is sent to
@@ -1019,8 +1023,10 @@ send(_Pid, _Message) ->
10191023
%% Unlike Erlang/OTP, monitors are only supported for processes and ports.
10201024
%% @end
10211025
%%-----------------------------------------------------------------------------
1022-
-spec monitor(Type :: process | port, Pid :: pid()) -> reference().
1023-
monitor(_Type, _Pid) ->
1026+
-spec monitor
1027+
(Type :: process, Pid :: pid()) -> reference();
1028+
(Type :: port, Port :: port()) -> reference().
1029+
monitor(_Type, _PidOrPort) ->
10241030
erlang:nif_error(undefined).
10251031

10261032
%%-----------------------------------------------------------------------------
@@ -1102,7 +1108,7 @@ exit(_Process, _Reason) ->
11021108
%% Unlike Erlang/OTP, ports are identified by pids.
11031109
%% @end
11041110
%%-----------------------------------------------------------------------------
1105-
-spec open_port(PortName :: {spawn, iodata()}, Options :: [any()] | map()) -> pid().
1111+
-spec open_port(PortName :: {spawn, iodata()}, Options :: [any()] | map()) -> port().
11061112
open_port(_PortName, _Options) ->
11071113
erlang:nif_error(undefined).
11081114

src/libAtomVM/dist_nifs.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -376,10 +376,10 @@ static term nif_erlang_dist_ctrl_put_data(Context *ctx, int argc, term argv[])
376376
RAISE_ERROR(BADARG_ATOM);
377377
}
378378
term to_name = term_get_tuple_element(control, 3);
379-
int target_process_id = globalcontext_get_registered_process(ctx->global, term_to_atom_index(to_name));
380-
if (target_process_id) {
379+
term target_process_pid = globalcontext_get_registered_process(ctx->global, term_to_atom_index(to_name));
380+
if (term_is_local_pid(target_process_pid)) {
381381
term payload = externalterm_to_term_with_roots(data + 1 + bytes_read, binary_len - 1 - bytes_read, ctx, ExternalTermCopy, &bytes_read, 2, argv);
382-
globalcontext_send_message(ctx->global, target_process_id, payload);
382+
globalcontext_send_message(ctx->global, term_to_local_process_id(target_process_pid), payload);
383383
}
384384
break;
385385
}
@@ -390,11 +390,12 @@ static term nif_erlang_dist_ctrl_put_data(Context *ctx, int argc, term argv[])
390390
term from_pid = term_get_tuple_element(control, 1);
391391
term target_proc = term_get_tuple_element(control, 2);
392392
term monitor_ref = term_get_tuple_element(control, 3);
393+
if (term_is_atom(target_proc)) {
394+
target_proc = globalcontext_get_registered_process(ctx->global, term_to_atom_index(target_proc));
395+
}
393396
int target_process_id = 0;
394397
if (term_is_local_pid(target_proc)) {
395398
target_process_id = term_to_local_process_id(target_proc);
396-
} else if (term_is_atom(target_proc)) {
397-
target_process_id = globalcontext_get_registered_process(ctx->global, term_to_atom_index(target_proc));
398399
} else {
399400
RAISE_ERROR(BADARG_ATOM);
400401
}

0 commit comments

Comments
 (0)