Skip to content

Commit

Permalink
Forward port changes from v0.6 release branch
Browse files Browse the repository at this point in the history
Merge a number of fixes from release-0.6 into main.
Some commits will not add any meaningful change since they are backports
from main.
  • Loading branch information
bettio committed Feb 11, 2025
2 parents 7396812 + f30ff07 commit 312f7c6
Show file tree
Hide file tree
Showing 15 changed files with 178 additions and 99 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/build-and-test-on-freebsd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
copyback: false

prepare: |
pkg install -y curl cmake gperf erlang elixir rebar3 mbedtls
pkg install -y curl cmake gperf erlang elixir rebar3 mbedtls3
run: |
set -e
Expand All @@ -80,6 +80,8 @@ jobs:
echo "**hw.ncpu:**"
sysctl -n hw.ncpu
sed -i '' 's/test_http_server/%test_http_server/g' tests/libs/eavmlib/tests.erl
echo "%%"
echo "%% Running CMake ..."
echo "%%"
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/build-and-test-other.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ jobs:

build-and-test-other:
needs: compile_tests
runs-on: ubuntu-24.04
# GCC on qemu segfaults on s390x and arm64v8 when using 24.04
# See also https://github.com/actions/runner-images/issues/11471
runs-on: ubuntu-22.04

strategy:
fail-fast: false
Expand Down Expand Up @@ -128,7 +130,7 @@ jobs:
path: build_tests

- name: Set up QEMU
run: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
uses: docker/setup-qemu-action@v3

- name: "Build and Test: AtomVM on foreign arch"
timeout-minutes: 15
Expand Down
15 changes: 6 additions & 9 deletions .github/workflows/stm32-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ jobs:
id: builddeps-cache
with:
path: |
/home/runner/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi
/home/runner/libopencm3
key: ${{ runner.os }}-build-deps

Expand All @@ -44,24 +43,23 @@ jobs:
https://repo.hex.pm
https://cdn.jsdelivr.net/hex
- name: "apt update"
run: sudo apt update

- name: "Install deps"
run: sudo apt install -y cmake gperf gcc-arm-none-eabi

- name: Checkout and build libopencm3
if: ${{ steps.builddeps-cache.outputs.cache-hit != 'true' }}
working-directory: /home/runner
run: |
set -euo pipefail
cd /home/runner
test -d libopencm3 && rm -fr libopencm3
export PATH=/home/runner/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin:${PATH}
git clone https://github.com/libopencm3/libopencm3.git -b v0.8.0
cd libopencm3
make
- name: "apt update"
run: sudo apt update

- name: "Install deps"
run: sudo apt install -y cmake gperf gcc-arm-none-eabi

- name: Checkout repo
uses: actions/checkout@v4

Expand All @@ -70,7 +68,6 @@ jobs:
working-directory: ./src/platforms/stm32/
run: |
set -euo pipefail
export PATH=/home/runner/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin:${PATH}
mkdir build
cd build
# -DAVM_WARNINGS_ARE_ERRORS=ON
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ certain VM instructions are used.
- Fix `network:stop/0` on ESP32 so the network can be started again
- Fix matching of binaries on unaligned boundaries for code compiled with older versions of OTP
- Fix a memory corruption caused by `binary:split/2,3`
- Fix deadlock in socket code
- Fix bug in opcode implementation (`select_val`): when selecting a value among many others a
shallow comparison was performed, so it was working just for plain values such as atoms and small
integers
- Fixed support for setting esp32 boot_path in NVS.
- Fixed race conditions in network:start/stop.
- Fixed crash calling network:sta_rssi(), when network not up.
- Fix error handling when calling `min` and `max` with code compiled before OTP-26: there was a
bug when handling errors from BIFs used as NIFs (when called with `CALL_EXT` and similar opcodes)`
- Fix matching of binaries on unaligned boundaries for code compiled with older versions of OTP

## [0.6.5] - 2024-10-15

Expand Down
2 changes: 1 addition & 1 deletion doc/src/programmers-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ The configuration map supplied to the logger_manager may contain the following k
| Key | Type | Default| Description |
|-----|------|--------|-------------|
| `log_level` | `log_level()` | `notice` | Primary log level |
| `logger` | `logger_config()` | `{handler, default, logger_std_h, undefined}` | Log configuration |
| `logger` | `logger_config()` | `{handler, default, logger_std_h, #{}}` | Log configuration |
| `module_level` | `module_level()` | `undefined` | Log level specific to a set of modules |

where `log_level()` is defined to be:
Expand Down
12 changes: 10 additions & 2 deletions libs/eavmlib/rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,18 @@
% SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
%

{erl_opts, [debug_info]}.
{erl_opts, [debug_info, {i, "../include"}]}.
{deps, []}.
{plugins, [rebar3_hex]}.
{plugins, [rebar3_hex, rebar3_ex_doc]}.

{shell, [
{apps, [eavmlib]}
]}.
{ex_doc, [
{version, "0.1.0"},
{source_url, "https://github.com/atomvm/AtomVM"},
{extras, []},
{main, "atomvm"},
{output, "doc"},
{api_reference, true}
]}.
6 changes: 3 additions & 3 deletions libs/eavmlib/src/ledc.erl
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@
stop/3
]).

-include("ledc.hrl").

-type duty_resolution() :: non_neg_integer().
-type duty_resolution_cfg() :: {duty_resolution, duty_resolution()}.
-type freq_hz() :: non_neg_integer().
-type freq_hz_cfg() :: {freq_hz, freq_hz()}.
-type speed_mode() :: ?LEDC_LOW_SPEED_MODE | ?LEDC_HIGH_SPEED_MODE.
-type speed_mode() :: 0 | 1.
%% Speed modes: use `0' for high speed, `1' for low speed.

-type speed_mode_cfg() :: {speed_mode, speed_mode()}.
-type timer_num() :: 0..3.
-type timer_num_cfg() :: {timer_num, timer_num()}.
Expand Down
87 changes: 41 additions & 46 deletions libs/eavmlib/src/network.erl
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
init/1,
handle_call/3,
handle_cast/2,
handle_continue/2,
handle_info/2,
terminate/2
]).
Expand Down Expand Up @@ -270,31 +271,11 @@ wait_for_ap(ApConfig, Timeout) ->
%%-----------------------------------------------------------------------------
-spec start(Config :: network_config()) -> {ok, pid()} | {error, Reason :: term()}.
start(Config) ->
case gen_server:start({local, ?MODULE}, ?MODULE, Config, []) of
{ok, Pid} = R ->
case gen_server:call(Pid, start) of
ok ->
R;
Error ->
Error
end;
Error ->
Error
end.
gen_server:start({local, ?MODULE}, ?MODULE, Config, []).

-spec start_link(Config :: network_config()) -> {ok, pid()} | {error, Reason :: term()}.
start_link(Config) ->
case gen_server:start_link({local, ?MODULE}, ?MODULE, Config, []) of
{ok, Pid} = R ->
case gen_server:call(Pid, start) of
ok ->
R;
Error ->
Error
end;
Error ->
Error
end.
gen_server:start_link({local, ?MODULE}, ?MODULE, Config, []).

%%-----------------------------------------------------------------------------
%% @returns ok, if the network interface was stopped, or {error, Reason} if
Expand All @@ -314,13 +295,17 @@ stop() ->
%%-----------------------------------------------------------------------------
-spec sta_rssi() -> {ok, Rssi :: db()} | {error, Reason :: term()}.
sta_rssi() ->
Port = get_port(),
Ref = make_ref(),
Port ! {self(), Ref, rssi},
receive
{Ref, {error, Reason}} -> {error, Reason};
{Ref, {rssi, Rssi}} -> {ok, Rssi};
Other -> {error, Other}
case whereis(network_port) of
undefined ->
{error, network_down};
Port ->
Ref = make_ref(),
Port ! {self(), Ref, rssi},
receive
{Ref, {error, Reason}} -> {error, Reason};
{Ref, {rssi, Rssi}} -> {ok, Rssi};
Other -> {error, Other}
end
end.

%%
Expand All @@ -329,28 +314,23 @@ sta_rssi() ->

%% @hidden
init(Config) ->
{ok, #state{config = Config}}.

%% @hidden
handle_call(start, From, #state{config = Config} = State) ->
Port = get_port(),
Ref = make_ref(),
Port ! {self(), Ref, {start, Config}},
wait_start_reply(Ref, From, Port, State);
handle_call(_Msg, _From, State) ->
{reply, {error, unknown_message}, State}.
{ok, #state{config = Config, port = Port, ref = Ref}, {continue, start_port}}.

%% @private
wait_start_reply(Ref, From, Port, State) ->
handle_continue(start_port, #state{config = Config, port = Port, ref = Ref} = State) ->
Port ! {self(), Ref, {start, Config}},
receive
{Ref, ok} ->
gen_server:reply(From, ok),
{noreply, State#state{port = Port, ref = Ref}};
{Ref, {error, Reason} = ER} ->
gen_server:reply(From, {error, Reason}),
{stop, {start_failed, Reason}, ER, State}
{noreply, State};
{Ref, {error, Reason}} ->
{stop, {start_port_failed, Reason}, State}
end.

%% @hidden
handle_call(_Msg, _From, State) ->
{reply, {error, unknown_message}, State}.

%% @hidden
handle_cast(_Msg, State) ->
{noreply, State}.
Expand Down Expand Up @@ -390,10 +370,25 @@ handle_info(Msg, State) ->
{noreply, State}.

%% @hidden
terminate(_Reason, _State) ->
%% Wait for port to be closed
terminate(_Reason, State) ->
Ref = make_ref(),
Port = State#state.port,
PortMonitor = erlang:monitor(port, Port),
network_port ! {?SERVER, Ref, stop},
ok.
wait_for_port_close(PortMonitor, Port).

wait_for_port_close(PortMonitor, Port) ->
receive
{'DOWN', PortMonitor, port, Port, _DownReason} ->
ok;
_Other ->
% Handle unexpected messages if necessary
wait_for_port_close(PortMonitor, Port)
% Timeout after 1 second just in case.
after 1000 ->
{error, timeout}
end.

%%
%% Internal operations
Expand Down
2 changes: 1 addition & 1 deletion libs/esp32boot/esp32init.erl
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ get_boot_path() ->
undefined ->
"/dev/partition/by-name/main.avm";
Path ->
Path
binary_to_list(Path)
end.

get_start_module() ->
Expand Down
40 changes: 29 additions & 11 deletions src/libAtomVM/opcodesswitch.h
Original file line number Diff line number Diff line change
Expand Up @@ -1990,19 +1990,23 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
// Support compilers < OTP26 that generate CALL_EXT
// for min/2 and max/2
const struct Bif *bif = EXPORTED_FUNCTION_TO_BIF(func);
term return_value;
switch (arity) {
case 0:
x_regs[0] = bif->bif0_ptr(ctx);
return_value = bif->bif0_ptr(ctx);
break;
case 1:
x_regs[0] = bif->bif1_ptr(ctx, 0, x_regs[0]);
return_value = bif->bif1_ptr(ctx, 0, x_regs[0]);
break;
case 2:
x_regs[0] = bif->bif2_ptr(ctx, 0, x_regs[0], x_regs[1]);
return_value = bif->bif2_ptr(ctx, 0, x_regs[0], x_regs[1]);
break;
default:
fprintf(stderr, "Invalid arity %" PRIu32 " for bif\n", arity);
AVM_ABORT();
}
PROCESS_MAYBE_TRAP_RETURN_VALUE_RESTORE_PC(return_value, orig_pc);
x_regs[0] = return_value;

break;
}
Expand Down Expand Up @@ -2090,19 +2094,23 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
ctx->e += (n_words + 1);

const struct Bif *bif = EXPORTED_FUNCTION_TO_BIF(func);
term return_value;
switch (arity) {
case 0:
x_regs[0] = bif->bif0_ptr(ctx);
return_value = bif->bif0_ptr(ctx);
break;
case 1:
x_regs[0] = bif->bif1_ptr(ctx, 0, x_regs[0]);
return_value = bif->bif1_ptr(ctx, 0, x_regs[0]);
break;
case 2:
x_regs[0] = bif->bif2_ptr(ctx, 0, x_regs[0], x_regs[1]);
return_value = bif->bif2_ptr(ctx, 0, x_regs[0], x_regs[1]);
break;
default:
fprintf(stderr, "Invalid arity %" PRIu32 " for bif\n", arity);
AVM_ABORT();
}
PROCESS_MAYBE_TRAP_RETURN_VALUE_LAST(return_value);
x_regs[0] = return_value;

DO_RETURN();

Expand Down Expand Up @@ -3107,8 +3115,14 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
#endif

#ifdef IMPL_EXECUTE_LOOP
if (!jump_to_address && (src_value == cmp_value)) {
jump_to_address = mod->labels[jmp_label];
if (!jump_to_address) {
TermCompareResult result = term_compare(
src_value, cmp_value, TermCompareExact, ctx->global);
if (result == TermEquals) {
jump_to_address = mod->labels[jmp_label];
} else if (UNLIKELY(result == TermCompareMemoryAllocFail)) {
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
}
}
#endif
}
Expand Down Expand Up @@ -3535,19 +3549,23 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
// Support compilers < OTP26 that generate CALL_EXT_ONLY
// for min/2 and max/2
const struct Bif *bif = EXPORTED_FUNCTION_TO_BIF(func);
term return_value;
switch (arity) {
case 0:
x_regs[0] = bif->bif0_ptr(ctx);
return_value = bif->bif0_ptr(ctx);
break;
case 1:
x_regs[0] = bif->bif1_ptr(ctx, 0, x_regs[0]);
return_value = bif->bif1_ptr(ctx, 0, x_regs[0]);
break;
case 2:
x_regs[0] = bif->bif2_ptr(ctx, 0, x_regs[0], x_regs[1]);
return_value = bif->bif2_ptr(ctx, 0, x_regs[0], x_regs[1]);
break;
default:
fprintf(stderr, "Invalid arity %" PRIu32 " for bif\n", arity);
AVM_ABORT();
}
PROCESS_MAYBE_TRAP_RETURN_VALUE_LAST(return_value);
x_regs[0] = return_value;

DO_RETURN();

Expand Down
Loading

0 comments on commit 312f7c6

Please sign in to comment.