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 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/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..819aa2d581 --- /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) -> + Before = os:system_time(), + sleep(SleepMs), + After = os:system_time(), + true = (Before < After), + 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),