From ea6a978b06f6dc4bb8c6571d8539851b954945c1 Mon Sep 17 00:00:00 2001 From: Mateusz Furga Date: Wed, 15 Oct 2025 14:24:42 +0200 Subject: [PATCH 1/3] Add os:system_time/0 Signed-off-by: Mateusz Furga --- libs/estdlib/src/io.erl | 12 +++++- src/libAtomVM/nifs.c | 19 +++++++++- src/libAtomVM/nifs.gperf | 1 + tests/erlang_tests/CMakeLists.txt | 2 + tests/erlang_tests/test_os_system_time.erl | 43 ++++++++++++++++++++++ tests/test.c | 1 + 6 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 tests/erlang_tests/test_os_system_time.erl diff --git a/libs/estdlib/src/io.erl b/libs/estdlib/src/io.erl index a885d5708a..4655e737ad 100644 --- a/libs/estdlib/src/io.erl +++ b/libs/estdlib/src/io.erl @@ -43,7 +43,8 @@ columns/1, getopts/0, getopts/1, - printable_range/0 + printable_range/0, + system_time/0 ]). -export_type([device/0, format/0, standard_io/0, standard_error/0, user/0]). @@ -235,6 +236,15 @@ put_chars(standard_io, Chars) -> put_chars(standard_error, Chars) -> put_chars(standard_io, Chars). +%%----------------------------------------------------------------------------- +%% @returns An integer representing system time. +%% @doc Returns the current OS system time in native time unit. +%% @end +%%----------------------------------------------------------------------------- +-spec system_time() -> integer(). +system_time() -> + erlang:nif_error(undefined). + %% @priv convert_request({requests, Requests}) -> {requests, [convert_request(Request) || Request <- Requests]}; diff --git a/src/libAtomVM/nifs.c b/src/libAtomVM/nifs.c index 37a38d06b5..a64d169c65 100644 --- a/src/libAtomVM/nifs.c +++ b/src/libAtomVM/nifs.c @@ -102,6 +102,7 @@ static term nif_binary_replace(Context *ctx, int argc, term argv[]); static term nif_binary_match(Context *ctx, int argc, term argv[]); static term nif_calendar_system_time_to_universal_time_2(Context *ctx, int argc, term argv[]); static term nif_os_getenv_1(Context *ctx, int argc, term argv[]); +static term nif_os_system_time_0(Context *ctx, int argc, term argv[]); static term nif_erlang_delete_element_2(Context *ctx, int argc, term argv[]); static term nif_erlang_atom_to_binary(Context *ctx, int argc, term argv[]); static term nif_erlang_atom_to_list_1(Context *ctx, int argc, term argv[]); @@ -502,6 +503,12 @@ static const struct Nif system_time_to_universal_time_nif = { .nif_ptr = nif_calendar_system_time_to_universal_time_2 }; +static const struct Nif os_system_time_0_nif = +{ + .base.type = NIFFunctionType, + .nif_ptr = nif_os_system_time_0 +}; + const struct Nif os_getenv_nif = { .base.type = NIFFunctionType, .nif_ptr = nif_os_getenv_1 @@ -1657,7 +1664,6 @@ term nif_erlang_monotonic_time_1(Context *ctx, int argc, term argv[]) term nif_erlang_system_time_1(Context *ctx, int argc, term argv[]) { - UNUSED(ctx); UNUSED(argc); struct timespec ts; @@ -1808,6 +1814,17 @@ term nif_calendar_system_time_to_universal_time_2(Context *ctx, int argc, term a return build_datetime_from_tm(ctx, gmtime_r(&ts.tv_sec, &broken_down_time)); } +term nif_os_system_time_0(Context *ctx, int argc, term argv[]) +{ + UNUSED(argc); + UNUSED(argv); + + struct timespec ts; + sys_time(&ts); + + return make_maybe_boxed_int64(ctx, ((int64_t) ts.tv_sec) * 1000000000ULL + ts.tv_nsec); +} + static term nif_os_getenv_1(Context *ctx, int argc, term argv[]) { UNUSED(argc); diff --git a/src/libAtomVM/nifs.gperf b/src/libAtomVM/nifs.gperf index a647c1de04..247d787fe7 100644 --- a/src/libAtomVM/nifs.gperf +++ b/src/libAtomVM/nifs.gperf @@ -45,6 +45,7 @@ binary:match/2, &binary_match_nif binary:match/3, &binary_match_nif calendar:system_time_to_universal_time/2, &system_time_to_universal_time_nif os:getenv/1, &os_getenv_nif +os:system_time/0, &os_system_time_0_nif erlang:atom_to_binary/1, &atom_to_binary_nif erlang:atom_to_binary/2, &atom_to_binary_nif erlang:atom_to_list/1, &atom_to_list_nif diff --git a/tests/erlang_tests/CMakeLists.txt b/tests/erlang_tests/CMakeLists.txt index 267a4b3d29..ef0b00d592 100644 --- a/tests/erlang_tests/CMakeLists.txt +++ b/tests/erlang_tests/CMakeLists.txt @@ -177,6 +177,7 @@ compile_erlang(compact23bitsneginteger) compile_erlang(negatives2) compile_erlang(datetime) compile_erlang(test_system_time) +compile_erlang(test_os_system_time) compile_erlang(is_type) compile_erlang(is_record) compile_erlang(test_bitshift) @@ -700,6 +701,7 @@ set(erlang_test_beams negatives2.beam datetime.beam test_system_time.beam + test_os_system_time.beam is_type.beam test_bitshift.beam test_bitwise.beam diff --git a/tests/erlang_tests/test_os_system_time.erl b/tests/erlang_tests/test_os_system_time.erl new file mode 100644 index 0000000000..c9f7d04e69 --- /dev/null +++ b/tests/erlang_tests/test_os_system_time.erl @@ -0,0 +1,43 @@ +% +% This file is part of AtomVM. +% +% Copyright 2018-2023 Davide Bettio +% Copyright 2025 Mateusz Furga +% +% 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. +% +% SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later +% + +-module(test_os_system_time). + +-export([start/0]). + +start() -> + ok = test_os_system_time(101), + ok = test_os_system_time(10), + ok = test_os_system_time(1), + 0. + +test_os_system_time(SleepMs) -> + After = os:system_time(), + sleep(SleepMs), + Before = os:system_time(), + true = (After < Before), + ok. + +sleep(Ms) -> + receive + after Ms -> + ok + end. diff --git a/tests/test.c b/tests/test.c index b73545d987..f23b253fe3 100644 --- a/tests/test.c +++ b/tests/test.c @@ -166,6 +166,7 @@ struct Test tests[] = { TEST_CASE_EXPECTED(negatives2, -500), TEST_CASE_EXPECTED(datetime, 3), TEST_CASE(test_system_time), + TEST_CASE(test_os_system_time), TEST_CASE_EXPECTED(is_type, 255), TEST_CASE(test_bitshift), TEST_CASE_EXPECTED(test_bitwise, -4), From 680bf8f9a7413ce56271690664886ca80fb57414 Mon Sep 17 00:00:00 2001 From: Mateusz Furga Date: Wed, 15 Oct 2025 14:39:53 +0200 Subject: [PATCH 2/3] Update CHANGELOG.md Signed-off-by: Mateusz Furga --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a16ab5db07..67a36a08ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `erlang:list_to_bitstring` - Reimplemented `lists:keyfind`, `lists:keymember` and `lists:member` as NIFs - Added `AVM_PRINT_PROCESS_CRASH_DUMPS` option +- Added `os:system_time/0` ### Changed From 618be5b1f945445dc71dccfd58b3e7a1a10a173b Mon Sep 17 00:00:00 2001 From: Mateusz Furga Date: Thu, 16 Oct 2025 12:53:50 +0200 Subject: [PATCH 3/3] Move os:system_time/0 spec to correct file. Fix variable names in tests Signed-off-by: Mateusz Furga --- libs/estdlib/src/io.erl | 12 +----------- libs/estdlib/src/os.erl | 11 ++++++++++- tests/erlang_tests/test_os_system_time.erl | 6 +++--- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/libs/estdlib/src/io.erl b/libs/estdlib/src/io.erl index 4655e737ad..a885d5708a 100644 --- a/libs/estdlib/src/io.erl +++ b/libs/estdlib/src/io.erl @@ -43,8 +43,7 @@ columns/1, getopts/0, getopts/1, - printable_range/0, - system_time/0 + printable_range/0 ]). -export_type([device/0, format/0, standard_io/0, standard_error/0, user/0]). @@ -236,15 +235,6 @@ put_chars(standard_io, Chars) -> put_chars(standard_error, Chars) -> put_chars(standard_io, Chars). -%%----------------------------------------------------------------------------- -%% @returns An integer representing system time. -%% @doc Returns the current OS system time in native time unit. -%% @end -%%----------------------------------------------------------------------------- --spec system_time() -> integer(). -system_time() -> - erlang:nif_error(undefined). - %% @priv convert_request({requests, Requests}) -> {requests, [convert_request(Request) || Request <- Requests]}; diff --git a/libs/estdlib/src/os.erl b/libs/estdlib/src/os.erl index 8caba2ba37..d03c4d741e 100644 --- a/libs/estdlib/src/os.erl +++ b/libs/estdlib/src/os.erl @@ -19,7 +19,7 @@ % -module(os). --export([getenv/1]). +-export([getenv/1, system_time/0]). %%----------------------------------------------------------------------------- %% @param Name name of the environment variable @@ -30,3 +30,12 @@ -spec getenv(Name :: nonempty_string()) -> nonempty_string() | false. getenv(_VarName) -> erlang:nif_error(undefined). + +%%----------------------------------------------------------------------------- +%% @returns An integer representing system time. +%% @doc Returns the current OS system time in nanoseconds. +%% @end +%%----------------------------------------------------------------------------- +-spec system_time() -> integer(). +system_time() -> + erlang:nif_error(undefined). diff --git a/tests/erlang_tests/test_os_system_time.erl b/tests/erlang_tests/test_os_system_time.erl index c9f7d04e69..819aa2d581 100644 --- a/tests/erlang_tests/test_os_system_time.erl +++ b/tests/erlang_tests/test_os_system_time.erl @@ -30,10 +30,10 @@ start() -> 0. test_os_system_time(SleepMs) -> - After = os:system_time(), - sleep(SleepMs), Before = os:system_time(), - true = (After < Before), + sleep(SleepMs), + After = os:system_time(), + true = (Before < After), ok. sleep(Ms) ->