diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -345,6 +345,7 @@ libc.src.time.gmtime libc.src.time.gmtime_r libc.src.time.mktime + libc.src.time.nanosleep ) endif() diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td --- a/libc/config/linux/api.td +++ b/libc/config/linux/api.td @@ -170,7 +170,7 @@ } def TimeAPI : PublicAPI<"time.h"> { - let Types = ["time_t", "struct tm"]; + let Types = ["time_t", "struct tm", "struct timespec"]; } def ErrnoAPI : PublicAPI<"errno.h"> { diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -368,6 +368,7 @@ libc.src.time.gmtime libc.src.time.gmtime_r libc.src.time.mktime + libc.src.time.nanosleep ) endif() diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt --- a/libc/include/CMakeLists.txt +++ b/libc/include/CMakeLists.txt @@ -93,6 +93,7 @@ .llvm_libc_common_h .llvm-libc-types.time_t .llvm-libc-types.struct_tm + .llvm-libc-types.struct_timespec ) add_gen_header( diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt --- a/libc/include/llvm-libc-types/CMakeLists.txt +++ b/libc/include/llvm-libc-types/CMakeLists.txt @@ -35,6 +35,7 @@ add_header(struct_dirent HDR struct_dirent.h DEPENDS .ino_t .off_t) add_header(struct_sigaction HDR struct_sigaction.h) add_header(struct_tm HDR struct_tm.h) +add_header(struct_timespec HDR struct_timespec.h) add_header(thrd_start_t HDR thrd_start_t.h) add_header(thrd_t HDR thrd_t.h DEPENDS .__thread_type) add_header(time_t HDR time_t.h) diff --git a/libc/include/llvm-libc-types/struct_timespec.h b/libc/include/llvm-libc-types/struct_timespec.h new file mode 100644 --- /dev/null +++ b/libc/include/llvm-libc-types/struct_timespec.h @@ -0,0 +1,20 @@ +//===-- Definition of struct timespec +//-------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef __LLVM_LIBC_TYPES_TIMESPEC_H__ +#define __LLVM_LIBC_TYPES_TIMESPEC_H__ + +#include + +struct timespec { + time_t tv_sec; /* Seconds. */ + long tv_nsec; /* Nanoseconds. */ +}; + +#endif // __LLVM_LIBC_TYPES_TIMESPEC_H__ diff --git a/libc/spec/posix.td b/libc/spec/posix.td --- a/libc/spec/posix.td +++ b/libc/spec/posix.td @@ -24,6 +24,9 @@ def StructDirentPtrPtr : PtrType; def ConstStructDirentPtrPtr : ConstType; +def StructTimeSpec : NamedType<"struct timespec">; +def StructTimeSpecPtr : PtrType; + def POSIX : StandardSpec<"POSIX"> { PtrType CharPtr = PtrType; RestrictedPtrType RestrictedCharPtr = RestrictedPtrType; @@ -368,7 +371,7 @@ >, ] >; - + HeaderSpec StdLib = HeaderSpec< "stdlib.h", [], // Macros @@ -739,6 +742,23 @@ ] >; + HeaderSpec Time = HeaderSpec< + "time.h", + [], // Macros + [StructTimeSpec], // Types + [], // Enumerations + [ + FunctionSpec< + "nanosleep", + RetValSpec, + [ + ArgSpec, + ArgSpec, + ] + >, + ] + >; + let Headers = [ CType, Dirent, @@ -750,6 +770,7 @@ StdLib, SysMMan, SysStat, + Time, UniStd, String ]; diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -22,7 +22,7 @@ [], // Enumerations [] >; - + HeaderSpec CType = HeaderSpec< "ctype.h", [], // Macros @@ -188,7 +188,7 @@ >, ] >; - + HeaderSpec String = HeaderSpec< "string.h", [ @@ -201,7 +201,7 @@ [ FunctionSpec< "memcpy", - RetValSpec, + RetValSpec, [ArgSpec, ArgSpec, ArgSpec] @@ -228,24 +228,24 @@ >, FunctionSpec< "strcpy", - RetValSpec, + RetValSpec, [ArgSpec, ArgSpec] >, FunctionSpec< "strncpy", - RetValSpec, + RetValSpec, [ArgSpec, ArgSpec, ArgSpec] >, FunctionSpec< "strcat", - RetValSpec, + RetValSpec, [ArgSpec, ArgSpec] >, FunctionSpec< "strncat", - RetValSpec, + RetValSpec, [ArgSpec, ArgSpec, ArgSpec] >, FunctionSpec< @@ -265,7 +265,7 @@ >, FunctionSpec< "strxfrm", - RetValSpec, + RetValSpec, [ArgSpec, ArgSpec, ArgSpec] @@ -479,11 +479,11 @@ FunctionSpec<"coshf", RetValSpec, [ArgSpec]>, FunctionSpec<"sinhf", RetValSpec, [ArgSpec]>, FunctionSpec<"tanhf", RetValSpec, [ArgSpec]>, - + FunctionSpec<"acosf", RetValSpec, [ArgSpec]>, FunctionSpec<"asinf", RetValSpec, [ArgSpec]>, FunctionSpec<"atanf", RetValSpec, [ArgSpec]>, - + FunctionSpec<"atanhf", RetValSpec, [ArgSpec]>, ] >; diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt --- a/libc/src/time/CMakeLists.txt +++ b/libc/src/time/CMakeLists.txt @@ -66,3 +66,17 @@ libc.include.time libc.src.errno.errno ) + +add_entrypoint_object( + nanosleep + SRCS + nanosleep.cpp + HDRS + nanosleep.h + DEPENDS + libc.include.errno + libc.include.time + libc.include.sys_syscall + libc.src.__support.OSUtil.osutil + libc.src.errno.errno +) diff --git a/libc/src/time/mktime.h b/libc/src/time/mktime.h --- a/libc/src/time/mktime.h +++ b/libc/src/time/mktime.h @@ -9,7 +9,6 @@ #ifndef LLVM_LIBC_SRC_TIME_MKTIME_H #define LLVM_LIBC_SRC_TIME_MKTIME_H -#include "src/time/mktime.h" #include namespace __llvm_libc { diff --git a/libc/src/time/mktime.h b/libc/src/time/nanosleep.h copy from libc/src/time/mktime.h copy to libc/src/time/nanosleep.h --- a/libc/src/time/mktime.h +++ b/libc/src/time/nanosleep.h @@ -1,4 +1,5 @@ -//===-- Implementation header of mktime -------------------------*- C++ -*-===// +//===-- Implementation header of nanosleep -------------------------*- C++ +//-*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,18 +7,17 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_SRC_TIME_MKTIME_H -#define LLVM_LIBC_SRC_TIME_MKTIME_H +#ifndef LLVM_LIBC_SRC_TIME_NANOSLEEP_H +#define LLVM_LIBC_SRC_TIME_NANOSLEEP_H -#include "src/time/mktime.h" #include namespace __llvm_libc { -time_t mktime(struct tm *t1); +int nanosleep(const struct timespec *req, struct timespec *rem); } // namespace __llvm_libc -#endif // LLVM_LIBC_SRC_TIME_MKTIME_H +#endif // LLVM_LIBC_SRC_TIME_NANOSLEEP_H #include "include/time.h" diff --git a/libc/src/time/nanosleep.cpp b/libc/src/time/nanosleep.cpp new file mode 100644 --- /dev/null +++ b/libc/src/time/nanosleep.cpp @@ -0,0 +1,29 @@ +//===-- Implementation of nanosleep function +//---------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/time/nanosleep.h" +#include "include/sys/syscall.h" // For syscall numbers. +#include "src/__support/OSUtil/syscall.h" // For syscall functions. +#include "src/__support/common.h" + +#include + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(int, nanosleep, + (const struct timespec *req, struct timespec *rem)) { + int ret = __llvm_libc::syscall(SYS_nanosleep, req, rem); + if (ret < 0) { + errno = -ret; + return -1; + } + return ret; +} + +} // namespace __llvm_libc diff --git a/libc/test/src/time/CMakeLists.txt b/libc/test/src/time/CMakeLists.txt --- a/libc/test/src/time/CMakeLists.txt +++ b/libc/test/src/time/CMakeLists.txt @@ -68,3 +68,20 @@ DEPENDS libc.src.time.mktime ) + +add_libc_unittest( + nanosleep + SUITE + libc_time_unittests + SRCS + nanosleep_test.cpp + HDRS + TmHelper.h + TmMatcher.h + CXX_STANDARD + 20 + DEPENDS + libc.include.errno + libc.include.time + libc.src.time.nanosleep +) diff --git a/libc/test/src/time/nanosleep_test.cpp b/libc/test/src/time/nanosleep_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/time/nanosleep_test.cpp @@ -0,0 +1,30 @@ +//===-- Unittests for nanosleep +//---------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include +#include + +#include "src/time/nanosleep.h" +#include "test/ErrnoSetterMatcher.h" +#include "utils/UnitTest/Test.h" + +namespace cpp = __llvm_libc::cpp; + +// TODO: When we have the code to read clocks, test that time has passed. + +TEST(LlvmLibcNanosleep, sleep) { + using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds; + errno = 0; + + struct timespec tim = {1, 500}; + struct timespec tim2 = {0, 0}; + int ret = __llvm_libc::nanosleep(&tim, &tim2); + ASSERT_EQ(errno, 0); + ASSERT_EQ(ret, 0); +}