[v7] y2038: Introduce __ASSUME_TIME64_SYSCALLS define

Message ID 20190611160243.3134-1-lukma@denx.de
State Committed
Headers

Commit Message

Lukasz Majewski June 11, 2019, 4:02 p.m. UTC
  This define indicates if the Linux kernel provides interfaces (syscalls)
to support 64 bit time.

* sysdeps/unix/sysv/linux/kernel-features.h:
(__ASSUME_TIME64_SYSCALLS): Define.

---
Changes for v7:
- Move the flag description from commit message to in-code comment.
- Check if relevant syscalls were defined in v3.2 (oldest glibc supported
  kernel).
- New syscalls, added to v5.1, like semtimedop_time64, which need extra
  code for handling, shall be excluded from __ASSUME_TIME64_SYSCALLS and
  would receive new flag - e.g. __ASSUME_SEMTIMEDOP_TIME64

Changes for v6:
- Change the logical meaning of __ASSUME_TIME64_SYSCALLS - now it
  indicates if the system supports the 64 bit time ABI (if for both
  __WORDSIZE==64 and __WORDSIZE==32 systems equally functional syscalls
  are provided).
- Update commit description

Changes for v5:
- Rewrite the in-code comment (x32 description more precise)
- Change patch description (for x32)

Changes for v4:
- Exclude this patch from the clock_settime64 patch series
- Rewrite the in-code comment
- Change patch description

Changes for v3:
- Provide more detailed and verbose description
- Change name to __ASSUME_TIME64_SYSCALLS
- Undefine __ASSUME_TIME64_SYSCALLS on x32

Changes for v2:
- New patch

Syscall's ABI compatibility checking:

1. Code to check if syscalls are defined since v3.2 kernel on the
   intersection of archs supported by v3.2 kernel and contemporary glibc
   (SHA1: e6e24243905957c36596f50a22af0acfd83793e2):

(Assumption: syscall ABI change require changing the name - like __NR_epoll_create
and __NR_epoll_create1)

export syscalls_table="\
	clock_gettime clock_settime clock_adjtime \
	clock_getres clock_nanosleep timer_gettime \
	timer_settime timerfd_gettime timerfd_settime \
	utimensat pselect6 ppoll io_pgetevents recvmmsg \
	mq_timedsend mq_timedreceive rt_sigtimedwait futex \
	sched_rr_get_interval"

for syscall in ${syscalls_table} ; do echo -n "syscall: ${syscall} -> "; \
	grep -rnIw "__NR_${syscall}" | grep ^arch/ | \
	grep -vE "mn10300|avr32|cris|m32r|frv|blackfin|xtensa|h8300|vdso" | \
	wc -l; done

Excluded syscalls (needs to be re-checked when syscall is converted to
64 bit):

- recvmmsg - is not defined for s390 (64 bit) and m68k (32 bit)
- io_pgetevents - is not defined at all for 3.2 kernel


2. Architectures (ports) supported by current glibc, but added to Linux
   after v3.2:

find sysdeps/unix/sysv/linux/ -type d | grep linux | \
	grep -vE "x86|sparc|m68k|powerpc|microblaze|arm|sh|ia64|s390|alpha|mips|i386" | \
	grep -vE "generic|net|bits|include|scsi|nfs|sys$"

Ports:
	- 32 bit: nios2, csky, hppa (is the same as parisc?) - no need to
          check as they will either use syscalls with 32 bit time support
          or new ones from v5.1 kernel

	- aarch64, riscv - 64 bit (the __ASSUME_TIME64_SYSCALLS set of
 	  syscalls is defined)

For linux 5.0 - syscalls are available in: include/uapi/asm-generic/unistd.h

for syscall in ${syscalls_table} ; do echo -n "syscall: ${syscall} -> "; \
	grep -rnIw "__NR_${syscall}" | grep ^include/ | \
	grep -vE "mn10300|avr32|cris|m32r|frv|blackfin|xtensa|h8300|vdso" | \
	wc -l; done

The __ASSUME_TIME64_SYSCALLS set of syscalls is also defined in this case.

Considering the above - it shall be safe to 'add' above set of syscalls to
__ASSUME_TIME64_SYSCALLS flag.
---
 sysdeps/unix/sysv/linux/kernel-features.h | 70 +++++++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)
  

Comments

Joseph Myers June 13, 2019, 4:28 p.m. UTC | #1
On Tue, 11 Jun 2019, Lukasz Majewski wrote:

> Syscall's ABI compatibility checking:
> 
> 1. Code to check if syscalls are defined since v3.2 kernel on the
>    intersection of archs supported by v3.2 kernel and contemporary glibc
>    (SHA1: e6e24243905957c36596f50a22af0acfd83793e2):
> 
> (Assumption: syscall ABI change require changing the name - like __NR_epoll_create
> and __NR_epoll_create1)
> 
> export syscalls_table="\
> 	clock_gettime clock_settime clock_adjtime \
> 	clock_getres clock_nanosleep timer_gettime \
> 	timer_settime timerfd_gettime timerfd_settime \
> 	utimensat pselect6 ppoll io_pgetevents recvmmsg \
> 	mq_timedsend mq_timedreceive rt_sigtimedwait futex \
> 	sched_rr_get_interval"
> 
> for syscall in ${syscalls_table} ; do echo -n "syscall: ${syscall} -> "; \
> 	grep -rnIw "__NR_${syscall}" | grep ^arch/ | \
> 	grep -vE "mn10300|avr32|cris|m32r|frv|blackfin|xtensa|h8300|vdso" | \
> 	wc -l; done

This is not quite sufficient.  It's possible for a syscall to be mentioned 
in an architecture's asm/unistd.h but not in the actual syscall table, for 
example (or mentioned inside #if 0).

You do need to check the relevant files for each architecture.  *But* only 
architectures with 64-bit syscall interfaces are relevant, because those 
with 32-bit syscall interfaces won't get __ASSUME_TIME64_SYSCALLS defined 
for kernels before 5.1 anyway.  So it doesn't matter whether a syscall was 
present for arm or m68k, for example.

(For example: before 3.15, microblaze didn't have pselect6 in its syscall 
table, though it had it in asm/unistd.h.  But there's no reason to exclude 
pselect6 from this patch, because microblaze is a 32-bit architecture, and 
all 64-bit architectures / syscall ABIs had that syscall already in 3.2.)

So you care about (glibc architecture names): aarch64 alpha ia64 mips (n64 
and n32 syscall ABIs) powerpc (64-bit syscall ABI) riscv (64-bit syscall 
ABI) s390 (64-bit syscall ABI) sparc (64-bit syscall ABI) x86_64 (classic 
and x32 syscall ABIs).  The 64-bit versions of hppa and sh are not 
relevant because they aren't supported by glibc.

> 	- 32 bit: nios2, csky, hppa (is the same as parisc?) - no need to

Yes, hppa is called parisc in the Linux kernel.  There are a few such 
cases where the names are different (e.g. the Linux kernel uses "arm64" as 
the name for aarch64).
  
Lukasz Majewski June 13, 2019, 10:34 p.m. UTC | #2
Hi Joseph,

> On Tue, 11 Jun 2019, Lukasz Majewski wrote:
> 
> > Syscall's ABI compatibility checking:
> > 
> > 1. Code to check if syscalls are defined since v3.2 kernel on the
> >    intersection of archs supported by v3.2 kernel and contemporary
> > glibc (SHA1: e6e24243905957c36596f50a22af0acfd83793e2):
> > 
> > (Assumption: syscall ABI change require changing the name - like
> > __NR_epoll_create and __NR_epoll_create1)
> > 
> > export syscalls_table="\
> > 	clock_gettime clock_settime clock_adjtime \
> > 	clock_getres clock_nanosleep timer_gettime \
> > 	timer_settime timerfd_gettime timerfd_settime \
> > 	utimensat pselect6 ppoll io_pgetevents recvmmsg \
> > 	mq_timedsend mq_timedreceive rt_sigtimedwait futex \
> > 	sched_rr_get_interval"
> > 
> > for syscall in ${syscalls_table} ; do echo -n "syscall: ${syscall}
> > -> "; \ grep -rnIw "__NR_${syscall}" | grep ^arch/ | \
> > 	grep -vE
> > "mn10300|avr32|cris|m32r|frv|blackfin|xtensa|h8300|vdso" | \ wc -l;
> > done  
> 
> This is not quite sufficient.  It's possible for a syscall to be
> mentioned in an architecture's asm/unistd.h but not in the actual
> syscall table, for example (or mentioned inside #if 0).
> 
> You do need to check the relevant files for each architecture.  *But*
> only architectures with 64-bit syscall interfaces are relevant,
> because those with 32-bit syscall interfaces won't get
> __ASSUME_TIME64_SYSCALLS defined for kernels before 5.1 anyway.  So
> it doesn't matter whether a syscall was present for arm or m68k, for
> example.

Thanks for clarification.

> 
> (For example: before 3.15, microblaze didn't have pselect6 in its
> syscall table, though it had it in asm/unistd.h.  But there's no
> reason to exclude pselect6 from this patch, because microblaze is a
> 32-bit architecture, and all 64-bit architectures / syscall ABIs had
> that syscall already in 3.2.)

Ok.

> 
> So you care about (glibc architecture names): aarch64 alpha ia64 mips
> (n64 and n32 syscall ABIs) powerpc (64-bit syscall ABI) riscv (64-bit
> syscall ABI) s390 (64-bit syscall ABI) sparc (64-bit syscall ABI)
> x86_64 (classic and x32 syscall ABIs).  The 64-bit versions of hppa
> and sh are not relevant because they aren't supported by glibc.

Thanks for listing them.

> 
> > 	- 32 bit: nios2, csky, hppa (is the same as parisc?) - no
> > need to  
> 
> Yes, hppa is called parisc in the Linux kernel.  There are a few such 
> cases where the names are different (e.g. the Linux kernel uses
> "arm64" as the name for aarch64).
> 

If I may ask - do I need to further fix/re-word in-patch comment and
patch description?

Is it precise and semantically correct?


Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
  
Joseph Myers June 13, 2019, 10:50 p.m. UTC | #3
On Fri, 14 Jun 2019, Lukasz Majewski wrote:

> If I may ask - do I need to further fix/re-word in-patch comment and
> patch description?
> 
> Is it precise and semantically correct?

Well, "present 64 bit time support" seems a bad way to describe support as 
of 5.0 and before (i.e. past support).  Likewise the "currently provide 64 
bit time support" description for the same class of systems.  Descriptions 
like that in terms of what's "current" in some external piece of software 
are always going to be problematic in comments.

The relevant class of systems you're trying to describe isn't ones with 
"present" or "current" support for 64-bit time (as of now, all Linux 
kernel architectures currently have such support).  It's ones with such 
support *with unsuffixed syscall names* (in distinction to those systems 
where the support is with syscalls with a "time64" suffix).
  

Patch

diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h
index bc5c959f58..cf99cfac17 100644
--- a/sysdeps/unix/sysv/linux/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/kernel-features.h
@@ -143,3 +143,73 @@ 
    */
 
 #define __ASSUME_CLONE_DEFAULT 1
+
+/* This flag indicates support for Linux kernel syscalls, which are able
+   to handle 64 bit time ABI. It is defined for architectures with both
+   present 64 bit time support (__WORDSIZE == 64 and __SYSCALL_WORDSIZE
+   == 64) as well as ones gaining it with new syscalls added to Linux
+   kernel version 5.1 (listed below).
+
+   To be more specific - this flag focuses on higer level of abstraction,
+   which indicates the system's ability to support 64 bit time.
+
+   In the other words this flag indicates availability of specific 64 bit
+   time supporting interfaces (syscalls in this case) from Linux kernel.
+
+   As an example - the syscall to set clock (clock_settime) - if the
+   __ASSUME_TIME64_SYSCALLS is defined, it indicates that 64 bit time can
+   be set in the system.
+
+   On systems with __WORDSIZE == 64 the __NR_clock_settime syscall is used
+   to achieve this goal. Contrary, systems with __WORDSIZE == 32 do use
+   new __NR_clock_settime64 syscall available from Linux version 5.1.
+
+   The __ASSUME_TIME64_SYSCALLS is defined for:
+
+   1. Systems which currently provide 64 bit time support (__WORDSIZE == 64).
+
+   2. For 'x32' architecture, which is a special case in respect to 64 bit
+      time support (it has __WORDSIZE==32 but __TIMESIZE==64)
+
+      For point 1 and 2, defined __ASSUME_TIME64_SYSCALL means, that the
+      syscall semantics are identical for both the old syscall (on systems
+      where __WORDSIZE or _SYSCALL_WORDSIZE is 64) and for the new one (if
+      ever defined from listed below v5.1 subset), so that no code will
+      ever have to handle the two syscalls differently.
+
+   3. Systems with __WORDSIZE==32, which gain 64 bit time support with new
+      set of syscalls added to Linux kernel 5.1.
+
+   List of new syscalls added to v5.1. kernel (they accept data based on
+   struct timespec and timeval with 64 bit tv_sec) consistent with
+    __ASSUME_TIME64_SYSCALLS flag definition:
+
+   clock_gettime64
+   clock_settime64
+   clock_adjtime64
+   clock_getres_time64
+   clock_nanosleep_time64
+   timer_gettime64
+   timer_settime64
+   timerfd_gettime64
+   timerfd_settime64
+   utimensat_time64
+   pselect6_time64
+   ppoll_time64
+   mq_timedsend_time64
+   mq_timedreceive_time64
+   rt_sigtimedwait_time64
+   futex_time64
+   sched_rr_get_interval_time64
+
+   Listed above syscalls have counterparts already providing 64 bit time support
+   on systems with __WORDSIZE == 64 or __SYSCALL_WORDSIZE == 64 since the oldest
+   supported by glibc Linux kernel (v3.2).  */
+
+#include <bits/wordsize.h>
+#if (__WORDSIZE == 64                                                   \
+     || (__WORDSIZE == 32                                               \
+         && (__LINUX_KERNEL_VERSION >= 0x050100                         \
+             || (defined __SYSCALL_WORDSIZE && __SYSCALL_WORDSIZE == 64))))
+# define __ASSUME_TIME64_SYSCALLS 1
+#endif