diff --git a/options/ansi/include/bits/ansi/time_t.h b/options/ansi/include/bits/ansi/time_t.h index 1c29fa0f67..bd0c4a7e5b 100644 --- a/options/ansi/include/bits/ansi/time_t.h +++ b/options/ansi/include/bits/ansi/time_t.h @@ -2,7 +2,8 @@ #ifndef MLIBC_TIME_T #define MLIBC_TIME_T -typedef long time_t; +#include +typedef __mlibc_int64 time_t; #endif diff --git a/options/ansi/include/bits/ansi/timespec.h b/options/ansi/include/bits/ansi/timespec.h index d34aa649e3..13a6e546e6 100644 --- a/options/ansi/include/bits/ansi/timespec.h +++ b/options/ansi/include/bits/ansi/timespec.h @@ -3,10 +3,16 @@ #define MLIBC_TIMESPEC_H #include +#include +// Equivalent of timespec64 in glibc. +// Should be used only with 64-bit syscalls +// or with appropriate compat syscalls. struct timespec { time_t tv_sec; - long tv_nsec; + // tv_nspec is required to be long by the C standard. + // However linux kernel expects long long. So we add padding. + __MLIBC_FIELD_PADDED(long, long long, tv_nsec); }; #endif // MLIBC_TIMESPEC_H diff --git a/options/internal/include/bits/field-padding.h b/options/internal/include/bits/field-padding.h new file mode 100644 index 0000000000..935953613d --- /dev/null +++ b/options/internal/include/bits/field-padding.h @@ -0,0 +1,9 @@ +#ifndef MLIBC_FIELD_PADDING_H +#define MLIBC_FIELD_PADDING_H + +#define __MLIBC_FIELD_PADDED(T, AT, F) \ + AT : (sizeof(AT)-sizeof(T))*8*(__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__); \ + T F; \ + AT : (sizeof(AT)-sizeof(T))*8*(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) + +#endif diff --git a/sysdeps/linux/generic/sysdeps.cpp b/sysdeps/linux/generic/sysdeps.cpp index 447ec75b7e..355166aebf 100644 --- a/sysdeps/linux/generic/sysdeps.cpp +++ b/sysdeps/linux/generic/sysdeps.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -235,7 +236,11 @@ int sys_vm_unmap(void *pointer, size_t size) { int sys_clock_get(int clock, time_t *secs, long *nanos) { struct timespec tp = {}; +#if UINTPTR_MAX == UINT64_MAX auto ret = do_syscall(SYS_clock_gettime, clock, &tp); +#else + auto ret = do_syscall(SYS_clock_gettime64, clock, &tp); +#endif if (int e = sc_error(ret); e) return e; *secs = tp.tv_sec; @@ -245,7 +250,11 @@ int sys_clock_get(int clock, time_t *secs, long *nanos) { int sys_clock_getres(int clock, time_t *secs, long *nanos) { struct timespec tp = {}; +#if UINTPTR_MAX == UINT64_MAX auto ret = do_syscall(SYS_clock_getres, clock, &tp); +#else + auto ret = do_syscall(SYS_clock_getres_time64, clock, &tp); +#endif if (int e = sc_error(ret); e) return e; *secs = tp.tv_sec; @@ -272,14 +281,22 @@ int sys_stat(fsfd_target fsfdt, int fd, const char *path, int flags, struct stat } int sys_statfs(const char *path, struct statfs *buf) { +#if UINTPTR_MAX == UINT64_MAX auto ret = do_cp_syscall(SYS_statfs, path, buf); +#else + auto ret = do_cp_syscall(SYS_statfs64, path, buf); +#endif if (int e = sc_error(ret); e) return e; return 0; } int sys_fstatfs(int fd, struct statfs *buf) { +#if UINTPTR_MAX == UINT64_MAX auto ret = do_cp_syscall(SYS_fstatfs, fd, buf); +#else + auto ret = do_cp_syscall(SYS_fstatfs64, fd, buf); +#endif if (int e = sc_error(ret); e) return e; return 0; @@ -307,11 +324,11 @@ int sys_sigaction(int signum, const struct sigaction *act, static_assert(sizeof(sigset_t) == 8); - auto ret = do_syscall(SYS_rt_sigaction, signum, act ? - &kernel_act : NULL, oldact ? - &kernel_oldact : NULL, sizeof(sigset_t)); - if (int e = sc_error(ret); e) - return e; + auto ret = do_syscall(SYS_rt_sigaction, signum, act ? + &kernel_act : NULL, oldact ? + &kernel_oldact : NULL, sizeof(sigset_t)); + if (int e = sc_error(ret); e) + return e; if (oldact) { oldact->sa_handler = kernel_oldact.handler; @@ -763,9 +780,42 @@ int sys_setpriority(int which, id_t who, int prio) { } int sys_setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value) { +#if UINTPTR_MAX == UINT64_MAX auto ret = do_syscall(SYS_setitimer, which, new_value, old_value); + if (int e = sc_error(ret); e) return e; + +#else + if (new_value->it_interval.tv_sec > INT32_MAX) + return -ENOTSUP; + if (new_value->it_value.tv_sec > INT32_MAX) + return -ENOTSUP; + + long new_isec = (long)new_value->it_interval.tv_sec; + long new_vsec = (long)new_value->it_value.tv_sec; + + long new_raw[4] = { + new_isec, new_value->it_interval.tv_usec, + new_vsec, new_value->it_value.tv_usec, + }; + long old_raw[4]; + + auto ret = do_syscall(SYS_setitimer, which, new_raw, old_raw); + + if (int e = sc_error(ret); e) { + return e; + } + + + if (old_value) { + old_value->it_interval.tv_sec = old_raw[0]; + old_value->it_interval.tv_usec = old_raw[1]; + old_value->it_value.tv_sec = old_raw[2]; + old_value->it_value.tv_usec = old_raw[3]; + } + +#endif return 0; } @@ -811,7 +861,11 @@ int sys_timer_create(clockid_t clk, struct sigevent *__restrict evp, timer_t *__ } int sys_timer_settime(timer_t t, int flags, const struct itimerspec *__restrict val, struct itimerspec *__restrict old) { +#if UINTPTR_MAX == UINT64_MAX auto ret = do_syscall(SYS_timer_settime, t, flags, val, old); +#else + auto ret = do_syscall(SYS_timer_settime64, t, flags, val, old); +#endif if (int e = sc_error(ret); e) { return e; } @@ -1019,7 +1073,11 @@ int sys_timerfd_create(int clockid, int flags, int *fd) { } int sys_timerfd_settime(int fd, int flags, const struct itimerspec *value, struct itimerspec *oldvalue) { +#if UINTPTR_MAX == UINT64_MAX auto ret = do_syscall(SYS_timerfd_settime, fd, flags, value, oldvalue); +#else + auto ret = do_syscall(SYS_timerfd_settime64, fd, flags, value, oldvalue); +#endif if (int e = sc_error(ret); e) return e; return 0; @@ -1579,9 +1637,15 @@ int sys_futex_tid() { } int sys_futex_wait(int *pointer, int expected, const struct timespec *time) { +#if UINTPTR_MAX == UINT64_MAX auto ret = do_cp_syscall(SYS_futex, pointer, FUTEX_WAIT, expected, time); +#else + auto ret = do_cp_syscall(SYS_futex_time64, pointer, FUTEX_WAIT, expected, time); +#endif + if (int e = sc_error(ret); e) return e; + return 0; } diff --git a/tests/ansi/timegm.c b/tests/ansi/timegm.c index f5af03ea43..6a7e0c07fb 100644 --- a/tests/ansi/timegm.c +++ b/tests/ansi/timegm.c @@ -1,6 +1,7 @@ #include #include #include +#include int main() { struct tm soon = {}; @@ -14,7 +15,7 @@ int main() { time_t expected_result = 0; // This should be epoch. result = timegm(&soon); - printf("epoch: %ld\n", result); + printf("epoch: %" PRId64 "\n", result); assert(result == expected_result); soon.tm_sec = 12; @@ -26,7 +27,7 @@ int main() { expected_result = 1652803692; result = timegm(&soon); // On my host, this returned 1652803692, verify this. - printf("epoch: %ld\n", result); + printf("epoch: %" PRId64 "\n", result); assert(result == expected_result); soon.tm_sec = 45; @@ -38,7 +39,7 @@ int main() { expected_result = -9181035; result = timegm(&soon); // On my host, this returned -9181035, verify this. - printf("epoch: %ld\n", result); + printf("epoch: %" PRId64 "\n", result); assert(result == expected_result); return 0;