public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v6 0/3] Support y2038 semctl_syscall()
@ 2020-04-28 22:05 Alistair Francis
  2020-04-28 22:05 ` [PATCH v6 1/3] bits/sem.h: Split out struct semid_ds Alistair Francis
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Alistair Francis @ 2020-04-28 22:05 UTC (permalink / raw)
  To: libc-alpha; +Cc: alistair23, Alistair Francis

This series does three things:
 1. Creates a bits/semid_ds_t.h file (in every arch) that specifies
    struct semid_ds so we no longer have to use macros defined in
    sem-pad.h.
 2. Removes the sem-pad.h file as it is no longer needed.
 3. Adds a new __semid_ds32 that is passed to the kernel (as part of
    a union) when running on 32-bit systems. If we are doing an
    IPC_STAT command then the 32-bit sem_{c,o}time{_high} values are
    combined to create a 64-bit value.

The semctl_syscall() function passes a union semun to the kernel. The
union includes struct semid_ds as a member. On 32-bit architectures the
Linux kernel provides a *_high version of the 32-bit sem_otime and
sem_ctime values. These can be combined to get a 64-bit version of the
time.

This patch adjusts the struct semid_ds to support the *_high versions
of sem_otime and sem_ctime. For 32-bit systems with a 64-bit time_t
this can be used to get a 64-bit time from the two 32-bit values.

This series was tested by running:
  ./scripts/build-many-glibcs.py ... compilers
  ./scripts/build-many-glibcs.py ... glibcs
on my x86_64 machine.

I also ran make check on RV32 and I only see a total of 9 test failures.

v6:
 - Update the 3rd patch to pass a temp buffer to the kernel
v5:
 - Address v4 review comments
 - Set the semid_ds struct from a temp struct
v4:
 - Remove the __IPC_TIME64 macro
    - It was only used once and doesn't work if __IPC_64 is 0 (which is
      usually is)
 - Address failures pointed out by Vineet Gupta

Alistair Francis (3):
  bits/sem.h: Split out struct semid_ds
  semctl: Remove the sem-pad.h file
  sysv: linux: Pass 64-bit version of semctl syscall

 sysdeps/unix/sysv/linux/Makefile              |  3 +-
 sysdeps/unix/sysv/linux/bits/sem.h            | 26 +---------
 .../sysv/linux/bits/types/struct_semid_ds.h   | 46 ++++++++++++++++++
 .../bits/types/struct_semid_ds.h}             | 31 ++++++------
 .../unix/sysv/linux/hppa/struct__semid_ds32.h | 32 +++++++++++++
 .../bits/types/struct_semid_ds.h}             | 20 +++++---
 .../{bits/sem-pad.h => struct__semid_ds32.h}  | 20 +++++---
 .../unix/sysv/linux/powerpc/bits/sem-pad.h    | 26 ----------
 .../powerpc/bits/types/struct_semid_ds.h      | 39 +++++++++++++++
 .../sysv/linux/powerpc/struct__semid_ds32.h   | 32 +++++++++++++
 sysdeps/unix/sysv/linux/semctl.c              | 47 +++++++++++++++++--
 .../linux/sparc/bits/types/struct_semid_ds.h  | 39 +++++++++++++++
 .../sysv/linux/sparc/struct__semid_ds32.h     | 32 +++++++++++++
 sysdeps/unix/sysv/linux/struct__semid_ds32.h  | 32 +++++++++++++
 sysdeps/unix/sysv/linux/x86/bits/sem-pad.h    | 24 ----------
 .../bits/types/struct_semid_ds.h}             | 22 ++++++---
 .../unix/sysv/linux/x86/struct__semid_ds32.h  | 32 +++++++++++++
 17 files changed, 389 insertions(+), 114 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h
 rename sysdeps/unix/sysv/linux/{bits/sem-pad.h => hppa/bits/types/struct_semid_ds.h} (51%)
 create mode 100644 sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h
 rename sysdeps/unix/sysv/linux/{sparc/bits/sem-pad.h => mips/bits/types/struct_semid_ds.h} (56%)
 rename sysdeps/unix/sysv/linux/mips/{bits/sem-pad.h => struct__semid_ds32.h} (52%)
 delete mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/sem-pad.h
 create mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/types/struct_semid_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h
 create mode 100644 sysdeps/unix/sysv/linux/sparc/bits/types/struct_semid_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h
 create mode 100644 sysdeps/unix/sysv/linux/struct__semid_ds32.h
 delete mode 100644 sysdeps/unix/sysv/linux/x86/bits/sem-pad.h
 rename sysdeps/unix/sysv/linux/{hppa/bits/sem-pad.h => x86/bits/types/struct_semid_ds.h} (53%)
 create mode 100644 sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h

-- 
2.26.2


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v6 1/3] bits/sem.h: Split out struct semid_ds
  2020-04-28 22:05 [PATCH v6 0/3] Support y2038 semctl_syscall() Alistair Francis
@ 2020-04-28 22:05 ` Alistair Francis
  2020-04-28 22:05 ` [PATCH v6 2/3] semctl: Remove the sem-pad.h file Alistair Francis
  2020-04-28 22:05 ` [PATCH v6 3/3] sysv: linux: Pass 64-bit version of semctl syscall Alistair Francis
  2 siblings, 0 replies; 8+ messages in thread
From: Alistair Francis @ 2020-04-28 22:05 UTC (permalink / raw)
  To: libc-alpha; +Cc: alistair23, Alistair Francis, Adhemerval Zanella

Split out the struct semid_ds into it's own file. This will allow us to
have architectures specify their own version.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
---
 sysdeps/unix/sysv/linux/Makefile              |  1 +
 sysdeps/unix/sysv/linux/bits/sem.h            | 24 +----------
 .../sysv/linux/bits/types/struct_semid_ds.h   | 43 +++++++++++++++++++
 3 files changed, 45 insertions(+), 23 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h

diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index 089a4899d5..db35c29351 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -90,6 +90,7 @@ sysdep_headers += sys/mount.h sys/acct.h \
 		  bits/termios-baud.h bits/termios-c_cflag.h \
 		  bits/termios-c_lflag.h bits/termios-tcflow.h \
 		  bits/termios-misc.h \
+		  bits/types/struct_semid_ds.h \
 		  bits/ipc-perm.h
 
 tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
diff --git a/sysdeps/unix/sysv/linux/bits/sem.h b/sysdeps/unix/sysv/linux/bits/sem.h
index e0f4155c67..0d1813ec67 100644
--- a/sysdeps/unix/sysv/linux/bits/sem.h
+++ b/sysdeps/unix/sysv/linux/bits/sem.h
@@ -21,6 +21,7 @@
 
 #include <sys/types.h>
 #include <bits/sem-pad.h>
+#include <bits/types/struct_semid_ds.h>
 
 /* Flags for `semop'.  */
 #define SEM_UNDO	0x1000		/* undo the operation on exit */
@@ -34,29 +35,6 @@
 #define SETVAL		16		/* set semval */
 #define SETALL		17		/* set all semval's */
 
-
-#if __SEM_PAD_BEFORE_TIME
-# define __SEM_PAD_TIME(NAME, RES)				\
-  __syscall_ulong_t __glibc_reserved ## RES; __time_t NAME
-#elif __SEM_PAD_AFTER_TIME
-# define __SEM_PAD_TIME(NAME, RES)				\
-  __time_t NAME; __syscall_ulong_t __glibc_reserved ## RES
-#else
-# define __SEM_PAD_TIME(NAME, RES)		\
-  __time_t NAME
-#endif
-
-/* Data structure describing a set of semaphores.  */
-struct semid_ds
-{
-  struct ipc_perm sem_perm;		/* operation permission struct */
-  __SEM_PAD_TIME (sem_otime, 1);	/* last semop() time */
-  __SEM_PAD_TIME (sem_ctime, 2);	/* last time changed by semctl() */
-  __syscall_ulong_t sem_nsems;		/* number of semaphores in set */
-  __syscall_ulong_t __glibc_reserved3;
-  __syscall_ulong_t __glibc_reserved4;
-};
-
 /* The user should define a union like the following to use it for arguments
    for `semctl'.
 
diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h
new file mode 100644
index 0000000000..0e136961d5
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h
@@ -0,0 +1,43 @@
+/* Generic implementation of the semaphore struct semid_ds.
+   Copyright (C) 1995-2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_SEM_H
+# error "Never include <bits/types/struct_semid_ds.h> directly; use <sys/sem.h> instead."
+#endif
+
+#if __SEM_PAD_BEFORE_TIME
+# define __SEM_PAD_TIME(NAME, RES)        \
+  __syscall_ulong_t __glibc_reserved ## RES; __time_t NAME
+#elif __SEM_PAD_AFTER_TIME
+# define __SEM_PAD_TIME(NAME, RES)        \
+  __time_t NAME; __syscall_ulong_t __glibc_reserved ## RES
+#else
+# define __SEM_PAD_TIME(NAME, RES)    \
+  __time_t NAME
+#endif
+
+/* Data structure describing a set of semaphores.  */
+struct semid_ds
+{
+  struct ipc_perm sem_perm;		/* operation permission struct */
+  __SEM_PAD_TIME (sem_otime, 1);	/* last semop() time */
+  __SEM_PAD_TIME (sem_ctime, 2);	/* last time changed by semctl() */
+  __syscall_ulong_t sem_nsems;		/* number of semaphores in set */
+  __syscall_ulong_t __glibc_reserved3;
+  __syscall_ulong_t __glibc_reserved4;
+};
-- 
2.26.2


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v6 2/3] semctl: Remove the sem-pad.h file
  2020-04-28 22:05 [PATCH v6 0/3] Support y2038 semctl_syscall() Alistair Francis
  2020-04-28 22:05 ` [PATCH v6 1/3] bits/sem.h: Split out struct semid_ds Alistair Francis
@ 2020-04-28 22:05 ` Alistair Francis
  2020-04-28 22:05 ` [PATCH v6 3/3] sysv: linux: Pass 64-bit version of semctl syscall Alistair Francis
  2 siblings, 0 replies; 8+ messages in thread
From: Alistair Francis @ 2020-04-28 22:05 UTC (permalink / raw)
  To: libc-alpha; +Cc: alistair23, Alistair Francis, Adhemerval Zanella

Remove the sem-pad.h file and instead have architectures override the
struct semid_ds via the bits/types/struct_semid_ds.h file.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
---
 sysdeps/unix/sysv/linux/Makefile              |  2 +-
 sysdeps/unix/sysv/linux/bits/sem.h            |  2 +-
 .../sysv/linux/bits/types/struct_semid_ds.h   | 29 +++++++-------
 .../bits/types/struct_semid_ds.h}             | 31 ++++++++-------
 sysdeps/unix/sysv/linux/mips/bits/sem-pad.h   | 24 ------------
 .../bits/types/struct_semid_ds.h}             | 20 ++++++----
 .../unix/sysv/linux/powerpc/bits/sem-pad.h    | 26 -------------
 .../powerpc/bits/types/struct_semid_ds.h      | 39 +++++++++++++++++++
 .../linux/sparc/bits/types/struct_semid_ds.h  | 39 +++++++++++++++++++
 sysdeps/unix/sysv/linux/x86/bits/sem-pad.h    | 24 ------------
 .../bits/types/struct_semid_ds.h}             | 22 +++++++----
 11 files changed, 141 insertions(+), 117 deletions(-)
 rename sysdeps/unix/sysv/linux/{bits/sem-pad.h => hppa/bits/types/struct_semid_ds.h} (51%)
 delete mode 100644 sysdeps/unix/sysv/linux/mips/bits/sem-pad.h
 rename sysdeps/unix/sysv/linux/{sparc/bits/sem-pad.h => mips/bits/types/struct_semid_ds.h} (56%)
 delete mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/sem-pad.h
 create mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/types/struct_semid_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/sparc/bits/types/struct_semid_ds.h
 delete mode 100644 sysdeps/unix/sysv/linux/x86/bits/sem-pad.h
 rename sysdeps/unix/sysv/linux/{hppa/bits/sem-pad.h => x86/bits/types/struct_semid_ds.h} (53%)

diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index db35c29351..434b008a91 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -84,7 +84,7 @@ sysdep_headers += sys/mount.h sys/acct.h \
 		  bits/siginfo-arch.h bits/siginfo-consts-arch.h \
 		  bits/procfs.h bits/procfs-id.h bits/procfs-extra.h \
 		  bits/procfs-prregset.h bits/mman-map-flags-generic.h \
-		  bits/msq-pad.h bits/sem-pad.h bits/shmlba.h bits/shm-pad.h \
+		  bits/msq-pad.h bits/shmlba.h bits/shm-pad.h \
 		  bits/termios-struct.h bits/termios-c_cc.h \
 		  bits/termios-c_iflag.h bits/termios-c_oflag.h \
 		  bits/termios-baud.h bits/termios-c_cflag.h \
diff --git a/sysdeps/unix/sysv/linux/bits/sem.h b/sysdeps/unix/sysv/linux/bits/sem.h
index 0d1813ec67..ba1169fdb3 100644
--- a/sysdeps/unix/sysv/linux/bits/sem.h
+++ b/sysdeps/unix/sysv/linux/bits/sem.h
@@ -20,7 +20,7 @@
 #endif
 
 #include <sys/types.h>
-#include <bits/sem-pad.h>
+#include <bits/timesize.h>
 #include <bits/types/struct_semid_ds.h>
 
 /* Flags for `semop'.  */
diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h
index 0e136961d5..4222e6a59f 100644
--- a/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h
+++ b/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h
@@ -20,24 +20,27 @@
 # error "Never include <bits/types/struct_semid_ds.h> directly; use <sys/sem.h> instead."
 #endif
 
-#if __SEM_PAD_BEFORE_TIME
-# define __SEM_PAD_TIME(NAME, RES)        \
-  __syscall_ulong_t __glibc_reserved ## RES; __time_t NAME
-#elif __SEM_PAD_AFTER_TIME
-# define __SEM_PAD_TIME(NAME, RES)        \
-  __time_t NAME; __syscall_ulong_t __glibc_reserved ## RES
-#else
-# define __SEM_PAD_TIME(NAME, RES)    \
-  __time_t NAME
-#endif
-
 /* Data structure describing a set of semaphores.  */
+#if __TIMESIZE == 32
+struct semid_ds
+{
+  struct ipc_perm sem_perm;        /* operation permission struct */
+  __time_t sem_otime;              /* last semop() time */
+  __syscall_ulong_t __glibc_reserved1;
+  __time_t sem_ctime;             /* last time changed by semctl() */
+  __syscall_ulong_t __glibc_reserved2;
+  __syscall_ulong_t sem_nsems;    /* number of semaphores in set */
+  __syscall_ulong_t __glibc_reserved3;
+  __syscall_ulong_t __glibc_reserved4;
+};
+#else
 struct semid_ds
 {
   struct ipc_perm sem_perm;		/* operation permission struct */
-  __SEM_PAD_TIME (sem_otime, 1);	/* last semop() time */
-  __SEM_PAD_TIME (sem_ctime, 2);	/* last time changed by semctl() */
+  __time_t sem_otime;			/* last semop() time */
+  __time_t sem_ctime;			/* last time changed by semctl() */
   __syscall_ulong_t sem_nsems;		/* number of semaphores in set */
   __syscall_ulong_t __glibc_reserved3;
   __syscall_ulong_t __glibc_reserved4;
 };
+#endif
diff --git a/sysdeps/unix/sysv/linux/bits/sem-pad.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_semid_ds.h
similarity index 51%
rename from sysdeps/unix/sysv/linux/bits/sem-pad.h
rename to sysdeps/unix/sysv/linux/hppa/bits/types/struct_semid_ds.h
index 566ce039cc..d4c50b5ef8 100644
--- a/sysdeps/unix/sysv/linux/bits/sem-pad.h
+++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_semid_ds.h
@@ -1,5 +1,5 @@
-/* Define where padding goes in struct semid_ds.  Generic version.
-   Copyright (C) 2018-2020 Free Software Foundation, Inc.
+/* HPPA implementation of the semaphore struct semid_ds
+   Copyright (C) 1995-2020 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -17,17 +17,20 @@
    <https://www.gnu.org/licenses/>.  */
 
 #ifndef _SYS_SEM_H
-# error "Never use <bits/sem-pad.h> directly; include <sys/sem.h> instead."
+# error "Never include <bits/types/struct_semid_ds.h> directly; use <sys/sem.h> instead."
 #endif
 
-#include <bits/timesize.h>
-
-/* On most architectures, padding goes after time fields for 32-bit
-   systems and is omitted for 64-bit systems.  Some architectures pad
-   before time fields instead, or omit padding despite being 32-bit,
-   or include it despite being 64-bit.  This must match the layout
-   used for struct semid64_ds in <asm/sembuf.h>, as glibc does not do
-   layout conversions for this structure.  */
-
-#define __SEM_PAD_AFTER_TIME (__TIMESIZE == 32)
-#define __SEM_PAD_BEFORE_TIME 0
+/* Data structure describing a set of semaphores.  */
+#if __TIMESIZE == 32
+struct semid_ds
+{
+  struct ipc_perm sem_perm;   /* operation permission struct */
+  __syscall_ulong_t __glibc_reserved1;
+  __time_t sem_otime;         /* last semop() time */
+  __syscall_ulong_t __glibc_reserved2;
+  __time_t sem_ctime;         /* last time changed by semctl() */
+  __syscall_ulong_t sem_nsems;    /* number of semaphores in set */
+  __syscall_ulong_t __glibc_reserved3;
+  __syscall_ulong_t __glibc_reserved4;
+};
+#endif
diff --git a/sysdeps/unix/sysv/linux/mips/bits/sem-pad.h b/sysdeps/unix/sysv/linux/mips/bits/sem-pad.h
deleted file mode 100644
index 4c581f7694..0000000000
--- a/sysdeps/unix/sysv/linux/mips/bits/sem-pad.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Define where padding goes in struct semid_ds.  MIPS version.
-   Copyright (C) 2018-2020 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#ifndef _SYS_SEM_H
-# error "Never use <bits/sem-pad.h> directly; include <sys/sem.h> instead."
-#endif
-
-#define __SEM_PAD_AFTER_TIME 0
-#define __SEM_PAD_BEFORE_TIME 0
diff --git a/sysdeps/unix/sysv/linux/sparc/bits/sem-pad.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h
similarity index 56%
rename from sysdeps/unix/sysv/linux/sparc/bits/sem-pad.h
rename to sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h
index 5f4e214d12..8954209a29 100644
--- a/sysdeps/unix/sysv/linux/sparc/bits/sem-pad.h
+++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h
@@ -1,5 +1,5 @@
-/* Define where padding goes in struct semid_ds.  SPARC version.
-   Copyright (C) 2018-2020 Free Software Foundation, Inc.
+/* MIPS implementation of the semaphore struct semid_ds
+   Copyright (C) 1995-2020 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -17,10 +17,16 @@
    <https://www.gnu.org/licenses/>.  */
 
 #ifndef _SYS_SEM_H
-# error "Never use <bits/sem-pad.h> directly; include <sys/sem.h> instead."
+# error "Never include <bits/types/struct_semid_ds.h> directly; use <sys/sem.h> instead."
 #endif
 
-#include <bits/timesize.h>
-
-#define __SEM_PAD_AFTER_TIME 0
-#define __SEM_PAD_BEFORE_TIME (__TIMESIZE == 32)
+/* Data structure describing a set of semaphores.  */
+struct semid_ds
+{
+  struct ipc_perm sem_perm;		/* operation permission struct */
+  __time_t sem_otime;	/* last semop() time */
+  __time_t sem_ctime;	/* last time changed by semctl() */
+  __syscall_ulong_t sem_nsems;		/* number of semaphores in set */
+  __syscall_ulong_t __glibc_reserved3;
+  __syscall_ulong_t __glibc_reserved4;
+};
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/sem-pad.h b/sysdeps/unix/sysv/linux/powerpc/bits/sem-pad.h
deleted file mode 100644
index 42d8827906..0000000000
--- a/sysdeps/unix/sysv/linux/powerpc/bits/sem-pad.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Define where padding goes in struct semid_ds.  PowerPC version.
-   Copyright (C) 2018-2020 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#ifndef _SYS_SEM_H
-# error "Never use <bits/sem-pad.h> directly; include <sys/sem.h> instead."
-#endif
-
-#include <bits/timesize.h>
-
-#define __SEM_PAD_AFTER_TIME 0
-#define __SEM_PAD_BEFORE_TIME (__TIMESIZE == 32)
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_semid_ds.h
new file mode 100644
index 0000000000..300a9b98e9
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_semid_ds.h
@@ -0,0 +1,39 @@
+/* PowerPC implementation of the semaphore struct semid_ds.
+   Copyright (C) 1995-2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_SEM_H
+# error "Never include <bits/types/struct_semid_ds.h> directly; use <sys/sem.h> instead."
+#endif
+
+/* Data structure describing a set of semaphores.  */
+struct semid_ds
+{
+  struct ipc_perm sem_perm;   /* operation permission struct */
+#if __TIMESIZE == 32
+  __syscall_ulong_t __glibc_reserved1;
+  __time_t sem_otime;         /* last semop() time */
+  __syscall_ulong_t __glibc_reserved2;
+  __time_t sem_ctime;        /* last time changed by semctl() */
+#else
+  __time_t sem_otime;         /* last semop() time */
+  __time_t sem_ctime;         /* last time changed by semctl() */
+#endif
+  __syscall_ulong_t sem_nsems;    /* number of semaphores in set */
+  __syscall_ulong_t __glibc_reserved3;
+  __syscall_ulong_t __glibc_reserved4;
+};
diff --git a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_semid_ds.h
new file mode 100644
index 0000000000..46fcd79fb6
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_semid_ds.h
@@ -0,0 +1,39 @@
+/* Sparc implementation of the semaphore struct semid_ds
+   Copyright (C) 1995-2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_SEM_H
+# error "Never include <bits/types/struct_semid_ds.h> directly; use <sys/sem.h> instead."
+#endif
+
+/* Data structure describing a set of semaphores.  */
+struct semid_ds
+{
+  struct ipc_perm sem_perm;   /* operation permission struct */
+#if __TIMESIZE == 32
+  __syscall_ulong_t __glibc_reserved1;
+  __time_t sem_otime;         /* last semop() time */
+  __syscall_ulong_t __glibc_reserved2;
+  __time_t sem_ctime;        /* last time changed by semctl() */
+#else
+  __time_t sem_otime;         /* last semop() time */
+  __time_t sem_ctime;         /* last time changed by semctl() */
+#endif
+  __syscall_ulong_t sem_nsems;    /* number of semaphores in set */
+  __syscall_ulong_t __glibc_reserved3;
+  __syscall_ulong_t __glibc_reserved4;
+};
diff --git a/sysdeps/unix/sysv/linux/x86/bits/sem-pad.h b/sysdeps/unix/sysv/linux/x86/bits/sem-pad.h
deleted file mode 100644
index 102e226997..0000000000
--- a/sysdeps/unix/sysv/linux/x86/bits/sem-pad.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Define where padding goes in struct semid_ds.  x86 version.
-   Copyright (C) 2018-2020 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#ifndef _SYS_SEM_H
-# error "Never use <bits/sem-pad.h> directly; include <sys/sem.h> instead."
-#endif
-
-#define __SEM_PAD_AFTER_TIME 1
-#define __SEM_PAD_BEFORE_TIME 0
diff --git a/sysdeps/unix/sysv/linux/hppa/bits/sem-pad.h b/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h
similarity index 53%
rename from sysdeps/unix/sysv/linux/hppa/bits/sem-pad.h
rename to sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h
index ee0332325b..f7ec89d115 100644
--- a/sysdeps/unix/sysv/linux/hppa/bits/sem-pad.h
+++ b/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h
@@ -1,5 +1,5 @@
-/* Define where padding goes in struct semid_ds.  HPPA version.
-   Copyright (C) 2018-2020 Free Software Foundation, Inc.
+/* x86 implementation of the semaphore struct semid_ds.
+   Copyright (C) 1995-2020 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -17,10 +17,18 @@
    <https://www.gnu.org/licenses/>.  */
 
 #ifndef _SYS_SEM_H
-# error "Never use <bits/sem-pad.h> directly; include <sys/sem.h> instead."
+# error "Never include <bits/types/struct_semid_ds.h> directly; use <sys/sem.h> instead."
 #endif
 
-#include <bits/timesize.h>
-
-#define __SEM_PAD_AFTER_TIME 0
-#define __SEM_PAD_BEFORE_TIME (__TIMESIZE == 32)
+/* Data structure describing a set of semaphores.  */
+struct semid_ds
+{
+  struct ipc_perm sem_perm;   /* operation permission struct */
+  __time_t sem_otime;  /* last semop() time */
+  __syscall_ulong_t __glibc_reserved1;
+  __time_t sem_ctime;  /* last time changed by semctl() */
+  __syscall_ulong_t __glibc_reserved2;
+  __syscall_ulong_t sem_nsems;    /* number of semaphores in set */
+  __syscall_ulong_t __glibc_reserved3;
+  __syscall_ulong_t __glibc_reserved4;
+};
-- 
2.26.2


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v6 3/3] sysv: linux: Pass 64-bit version of semctl syscall
  2020-04-28 22:05 [PATCH v6 0/3] Support y2038 semctl_syscall() Alistair Francis
  2020-04-28 22:05 ` [PATCH v6 1/3] bits/sem.h: Split out struct semid_ds Alistair Francis
  2020-04-28 22:05 ` [PATCH v6 2/3] semctl: Remove the sem-pad.h file Alistair Francis
@ 2020-04-28 22:05 ` Alistair Francis
  2020-04-29 21:09   ` Adhemerval Zanella
  2 siblings, 1 reply; 8+ messages in thread
From: Alistair Francis @ 2020-04-28 22:05 UTC (permalink / raw)
  To: libc-alpha; +Cc: alistair23, Alistair Francis

The semctl_syscall() function passes a union semun to the kernel. The
union includes struct semid_ds as a member. On 32-bit architectures the
Linux kernel provides a *_high version of the 32-bit sem_otime and
sem_ctime values. These can be combined to get a 64-bit version of the
time.

This patch adjusts the struct semid_ds to support the *_high versions
of sem_otime and sem_ctime. For 32-bit systems with a 64-bit time_t
this can be used to get a 64-bit time from the two 32-bit values.

Due to alignment differences between 64-bit and 32-bit variables we
also need to set nsems to ensure it's correct.
---
 .../unix/sysv/linux/hppa/struct__semid_ds32.h | 32 +++++++++++++
 .../unix/sysv/linux/mips/struct__semid_ds32.h | 30 ++++++++++++
 .../sysv/linux/powerpc/struct__semid_ds32.h   | 32 +++++++++++++
 sysdeps/unix/sysv/linux/semctl.c              | 47 +++++++++++++++++--
 .../sysv/linux/sparc/struct__semid_ds32.h     | 32 +++++++++++++
 sysdeps/unix/sysv/linux/struct__semid_ds32.h  | 32 +++++++++++++
 .../unix/sysv/linux/x86/struct__semid_ds32.h  | 32 +++++++++++++
 7 files changed, 233 insertions(+), 4 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h
 create mode 100644 sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h
 create mode 100644 sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h
 create mode 100644 sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h
 create mode 100644 sysdeps/unix/sysv/linux/struct__semid_ds32.h
 create mode 100644 sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h

diff --git a/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h
new file mode 100644
index 0000000000..9eceaaff2d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h
@@ -0,0 +1,32 @@
+/* HPPA implementation of the semaphore struct __semid_ds32.
+   Copyright (C) 1995-2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#if __WORDSIZE == 32
+/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
+   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
+struct __semid_ds32 {
+  struct ipc_perm sem_perm;              /* operation permission struct */
+  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
+  __syscall_ulong_t   sem_otime;         /* last semop() time */
+  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
+  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
+  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
+  __syscall_ulong_t   __glibc_reserved3;
+  __syscall_ulong_t   __glibc_reserved4;
+};
+#endif
diff --git a/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h
new file mode 100644
index 0000000000..2e3e2fc562
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h
@@ -0,0 +1,30 @@
+/* MIPS implementation of the semaphore struct __semid_ds32.
+   Copyright (C) 1995-2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#if __WORDSIZE == 32
+/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
+   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
+struct __semid_ds32 {
+  struct ipc_perm sem_perm;              /* operation permission struct */
+  __syscall_ulong_t   sem_otime;         /* last semop time */
+  __syscall_ulong_t   sem_ctime;         /* last change time */
+  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
+  __syscall_ulong_t   sem_otime_high;
+  __syscall_ulong_t   sem_ctime_high;
+};
+#endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h
new file mode 100644
index 0000000000..f509db5a02
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h
@@ -0,0 +1,32 @@
+/* PowerPC implementation of the semaphore struct __semid_ds32.
+   Copyright (C) 1995-2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#if __WORDSIZE == 32
+/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
+   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
+struct __semid_ds32 {
+  struct ipc_perm sem_perm;              /* operation permission struct */
+  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
+  __syscall_ulong_t   sem_otime;         /* last semop() time */
+  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
+  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
+  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
+  __syscall_ulong_t   __glibc_reserved3;
+  __syscall_ulong_t   __glibc_reserved4;
+};
+#endif
diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c
index 30571af49f..0634cc1abe 100644
--- a/sysdeps/unix/sysv/linux/semctl.c
+++ b/sysdeps/unix/sysv/linux/semctl.c
@@ -22,8 +22,13 @@
 #include <sysdep.h>
 #include <shlib-compat.h>
 #include <errno.h>
+#include <struct__semid_ds32.h>
 #include <linux/posix_types.h>  /* For __kernel_mode_t.  */
 
+#define IPC_TIME64 \
+ (__WORDSIZE == 32 && __TIMESIZE == 64 \
+     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
+
 /* Define a `union semun' suitable for Linux here.  */
 union semun
 {
@@ -44,13 +49,47 @@ union semun
 static int
 semctl_syscall (int semid, int semnum, int cmd, union semun arg)
 {
+  int ret;
+#if IPC_TIME64
+  struct __semid_ds32 tmp;
+  struct semid_ds *orig;
+  bool restore = false;
+  if (cmd == IPC_STAT || cmd == SEM_STAT || cmd == SEM_STAT_ANY)
+    {
+      tmp = (struct __semid_ds32) {
+        .sem_perm  = arg.buf->sem_perm,
+        .sem_otime = arg.buf->sem_otime,
+        .sem_ctime = arg.buf->sem_ctime,
+        .sem_nsems = arg.buf->sem_nsems,
+      };
+      orig = arg.buf;
+      arg.buf = (struct semid_ds*)&tmp;
+      restore = true;
+    }
+#endif
+
 #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
-  return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64,
-			      arg.array);
+  ret = INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64,
+                             arg.array);
 #else
-  return INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64,
-			      SEMCTL_ARG_ADDRESS (arg));
+  ret = INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64,
+                             SEMCTL_ARG_ADDRESS (arg));
 #endif
+
+#if IPC_TIME64
+  if (ret >= 0 && restore)
+    {
+      arg.buf = orig;
+      arg.buf->sem_perm  = tmp.sem_perm;
+      arg.buf->sem_otime = tmp.sem_otime
+                           | ((time_t) tmp.sem_otime_high << 32);
+      arg.buf->sem_ctime = tmp.sem_ctime
+                           | ((time_t) tmp.sem_ctime_high << 32);
+      arg.buf->sem_nsems = tmp.sem_nsems;
+    }
+#endif
+
+    return ret;
 }
 
 int
diff --git a/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h
new file mode 100644
index 0000000000..f641825d37
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h
@@ -0,0 +1,32 @@
+/* Sparc implementation of the semaphore struct __semid_ds32.
+   Copyright (C) 1995-2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#if __WORDSIZE == 32
+/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
+   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
+struct __semid_ds32 {
+  struct ipc_perm sem_perm;              /* operation permission struct */
+  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
+  __syscall_ulong_t   sem_otime;         /* last semop() time */
+  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
+  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
+  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
+  __syscall_ulong_t   __glibc_reserved3;
+  __syscall_ulong_t   __glibc_reserved4;
+};
+#endif
diff --git a/sysdeps/unix/sysv/linux/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/struct__semid_ds32.h
new file mode 100644
index 0000000000..51ff83206d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/struct__semid_ds32.h
@@ -0,0 +1,32 @@
+/* Generic implementation of the semaphore struct __semid_ds32.
+   Copyright (C) 1995-2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#if __WORDSIZE == 32
+/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
+   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
+struct __semid_ds32 {
+  struct ipc_perm sem_perm;              /* operation permission struct */
+  __syscall_ulong_t   sem_otime;         /* last semop() time */
+  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
+  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
+  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
+  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
+  __syscall_ulong_t   __glibc_reserved3;
+  __syscall_ulong_t   __glibc_reserved4;
+};
+#endif
diff --git a/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h
new file mode 100644
index 0000000000..f65c9fc877
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h
@@ -0,0 +1,32 @@
+/* x86 implementation of the semaphore struct __semid_ds32.
+   Copyright (C) 1995-2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifdef __i386__
+/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
+   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
+struct __semid_ds32 {
+  struct ipc_perm sem_perm;              /* operation permission struct */
+  __syscall_ulong_t   sem_otime;         /* last semop() time */
+  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
+  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
+  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
+  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
+  __syscall_ulong_t   __glibc_reserved3;
+  __syscall_ulong_t   __glibc_reserved4;
+};
+#endif
-- 
2.26.2


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v6 3/3] sysv: linux: Pass 64-bit version of semctl syscall
  2020-04-28 22:05 ` [PATCH v6 3/3] sysv: linux: Pass 64-bit version of semctl syscall Alistair Francis
@ 2020-04-29 21:09   ` Adhemerval Zanella
  2020-04-29 23:24     ` Alistair Francis
  0 siblings, 1 reply; 8+ messages in thread
From: Adhemerval Zanella @ 2020-04-29 21:09 UTC (permalink / raw)
  To: libc-alpha, Alistair Francis, Alistair Francis, Arnd Bergmann



On 28/04/2020 19:05, Alistair Francis via Libc-alpha wrote:
> The semctl_syscall() function passes a union semun to the kernel. The
> union includes struct semid_ds as a member. On 32-bit architectures the
> Linux kernel provides a *_high version of the 32-bit sem_otime and
> sem_ctime values. These can be combined to get a 64-bit version of the
> time.
> 
> This patch adjusts the struct semid_ds to support the *_high versions
> of sem_otime and sem_ctime. For 32-bit systems with a 64-bit time_t
> this can be used to get a 64-bit time from the two 32-bit values.
> 
> Due to alignment differences between 64-bit and 32-bit variables we
> also need to set nsems to ensure it's correct.

I think this approach might trigger an issue on semid_ds definition for 
time64 that I only noticed now.

Since the idea of semctl is not use a different entrypoint neither to add
aditional flag when issuing the syscall (either semctl or ipc), with this
change we need to assure that __TIMESIZE == 32 sem_otime alignment matches
__TIMESIZE == 64 one.

However for semid_ds and msqid_ds time_t members can't not properly aligned
to be expanded to 64-bit (shmid_ds has a shm_segsz field before the
timestamp fields) due to the ipc_perm header consisting of 9 32-bit words
except on parisc/powerpc/sparc.  The alignment difference will make 
semctl once programs states build against a semid_ds with time_t
being an 64-bit type.

So we have 2 options here:

  1. Keep the semid_ds layout as the kernel expected one and add the
     newer time64 timestamps at the *end*, and redefine the command 
     arguments that passes a struct semid_ds to use 
     (IPC_STAT, SEM_STAT, SEM_STAT_ANY) to indicate that the semid_ds
     is a time64 one.  The IPC_64 bit might be a feasible hack since
     kernel won't use on possible new commands.

  2. Add a new semctl64 to handle the time64 one semid_ds.

> ---
>  .../unix/sysv/linux/hppa/struct__semid_ds32.h | 32 +++++++++++++
>  .../unix/sysv/linux/mips/struct__semid_ds32.h | 30 ++++++++++++
>  .../sysv/linux/powerpc/struct__semid_ds32.h   | 32 +++++++++++++
>  sysdeps/unix/sysv/linux/semctl.c              | 47 +++++++++++++++++--
>  .../sysv/linux/sparc/struct__semid_ds32.h     | 32 +++++++++++++
>  sysdeps/unix/sysv/linux/struct__semid_ds32.h  | 32 +++++++++++++
>  .../unix/sysv/linux/x86/struct__semid_ds32.h  | 32 +++++++++++++
>  7 files changed, 233 insertions(+), 4 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h
>  create mode 100644 sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h
>  create mode 100644 sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h
>  create mode 100644 sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h
>  create mode 100644 sysdeps/unix/sysv/linux/struct__semid_ds32.h
>  create mode 100644 sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h
> 
> diff --git a/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h
> new file mode 100644
> index 0000000000..9eceaaff2d
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h
> @@ -0,0 +1,32 @@
> +/* HPPA implementation of the semaphore struct __semid_ds32.
> +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#if __WORDSIZE == 32
> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
> +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
> +struct __semid_ds32 {
> +  struct ipc_perm sem_perm;              /* operation permission struct */
> +  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
> +  __syscall_ulong_t   sem_otime;         /* last semop() time */
> +  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
> +  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
> +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
> +  __syscall_ulong_t   __glibc_reserved3;
> +  __syscall_ulong_t   __glibc_reserved4;
> +};
> +#endif

No need to define it for __WORDSIZE == 32, the ABI just supports it
anyway.

> diff --git a/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h
> new file mode 100644
> index 0000000000..2e3e2fc562
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h
> @@ -0,0 +1,30 @@
> +/* MIPS implementation of the semaphore struct __semid_ds32.
> +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#if __WORDSIZE == 32
> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
> +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
> +struct __semid_ds32 {
> +  struct ipc_perm sem_perm;              /* operation permission struct */
> +  __syscall_ulong_t   sem_otime;         /* last semop time */
> +  __syscall_ulong_t   sem_ctime;         /* last change time */
> +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
> +  __syscall_ulong_t   sem_otime_high;
> +  __syscall_ulong_t   sem_ctime_high;
> +};
> +#endif

Ok, it cover mips64-n32 as well.

> diff --git a/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h
> new file mode 100644
> index 0000000000..f509db5a02
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h
> @@ -0,0 +1,32 @@
> +/* PowerPC implementation of the semaphore struct __semid_ds32.
> +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#if __WORDSIZE == 32
> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
> +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
> +struct __semid_ds32 {
> +  struct ipc_perm sem_perm;              /* operation permission struct */
> +  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
> +  __syscall_ulong_t   sem_otime;         /* last semop() time */
> +  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
> +  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
> +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
> +  __syscall_ulong_t   __glibc_reserved3;
> +  __syscall_ulong_t   __glibc_reserved4;
> +};
> +#endif

Ok.

> diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c
> index 30571af49f..0634cc1abe 100644
> --- a/sysdeps/unix/sysv/linux/semctl.c
> +++ b/sysdeps/unix/sysv/linux/semctl.c
> @@ -22,8 +22,13 @@
>  #include <sysdep.h>
>  #include <shlib-compat.h>
>  #include <errno.h>
> +#include <struct__semid_ds32.h>
>  #include <linux/posix_types.h>  /* For __kernel_mode_t.  */
>  
> +#define IPC_TIME64 \
> + (__WORDSIZE == 32 && __TIMESIZE == 64 \
> +     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))

I think it would be better to move this definition to the common
ipc_priv.h header since it will most likely be used on msgctl
and shmctl y2038 support as well.

> +
>  /* Define a `union semun' suitable for Linux here.  */
>  union semun
>  {
> @@ -44,13 +49,47 @@ union semun
>  static int
>  semctl_syscall (int semid, int semnum, int cmd, union semun arg)
>  {
> +  int ret;
> +#if IPC_TIME64

I think we shoul add a comment stating why we need a auxiliary buffer 
for STAT/STAT_ANY operations.  Something like:

   A temporary buffer is used to avoid both an issue where the export
   semid_ds might not have follow kernel expected layout (due
   sem_{o,c}time alignment in 64-bit time case) and the issue where
   some kernel version might not clear the high bits when returning
   then sem_{o,c}time information.

> +  struct __semid_ds32 tmp;
> +  struct semid_ds *orig;
> +  bool restore = false;
> +  if (cmd == IPC_STAT || cmd == SEM_STAT || cmd == SEM_STAT_ANY)
> +    {
> +      tmp = (struct __semid_ds32) {
> +        .sem_perm  = arg.buf->sem_perm,
> +        .sem_otime = arg.buf->sem_otime,
> +        .sem_ctime = arg.buf->sem_ctime,
> +        .sem_nsems = arg.buf->sem_nsems,
> +      };

We need to fully initialize the temporary struct to avoid a kernel
issue fixed in 4693916846269d633a3664586650dbfac2c5562f (4.14) where
kernel does not clear the timestamps high bits.

> +      orig = arg.buf;
> +      arg.buf = (struct semid_ds*)&tmp;

Space before &tmp.

> +      restore = true;
> +    }
> +#endif
> +
>  #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
> -  return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64,
> -			      arg.array);
> +  ret = INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64,
> +                             arg.array);
>  #else
> -  return INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64,
> -			      SEMCTL_ARG_ADDRESS (arg));
> +  ret = INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64,
> +                             SEMCTL_ARG_ADDRESS (arg));
>  #endif

Ok.

> +
> +#if IPC_TIME64
> +  if (ret >= 0 && restore)
> +    {
> +      arg.buf = orig;
> +      arg.buf->sem_perm  = tmp.sem_perm;
> +      arg.buf->sem_otime = tmp.sem_otime
> +                           | ((time_t) tmp.sem_otime_high << 32);
> +      arg.buf->sem_ctime = tmp.sem_ctime
> +                           | ((time_t) tmp.sem_ctime_high << 32);
> +      arg.buf->sem_nsems = tmp.sem_nsems;

I think it would be better to use __time64_t explicit here.

> +    }
> +#endif
> +
> +    return ret;
>  }
>  
>  int
> diff --git a/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h
> new file mode 100644
> index 0000000000..f641825d37
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h
> @@ -0,0 +1,32 @@
> +/* Sparc implementation of the semaphore struct __semid_ds32.
> +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#if __WORDSIZE == 32
> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
> +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
> +struct __semid_ds32 {
> +  struct ipc_perm sem_perm;              /* operation permission struct */
> +  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
> +  __syscall_ulong_t   sem_otime;         /* last semop() time */
> +  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
> +  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
> +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
> +  __syscall_ulong_t   __glibc_reserved3;
> +  __syscall_ulong_t   __glibc_reserved4;
> +};
> +#endif

Ok.

> diff --git a/sysdeps/unix/sysv/linux/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/struct__semid_ds32.h
> new file mode 100644
> index 0000000000..51ff83206d
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/struct__semid_ds32.h
> @@ -0,0 +1,32 @@
> +/* Generic implementation of the semaphore struct __semid_ds32.
> +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#if __WORDSIZE == 32
> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
> +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
> +struct __semid_ds32 {
> +  struct ipc_perm sem_perm;              /* operation permission struct */
> +  __syscall_ulong_t   sem_otime;         /* last semop() time */
> +  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
> +  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
> +  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
> +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
> +  __syscall_ulong_t   __glibc_reserved3;
> +  __syscall_ulong_t   __glibc_reserved4;
> +};
> +#endif

Ok.

> diff --git a/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h
> new file mode 100644
> index 0000000000..f65c9fc877
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h
> @@ -0,0 +1,32 @@
> +/* x86 implementation of the semaphore struct __semid_ds32.
> +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifdef __i386__
> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
> +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
> +struct __semid_ds32 {
> +  struct ipc_perm sem_perm;              /* operation permission struct */
> +  __syscall_ulong_t   sem_otime;         /* last semop() time */
> +  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
> +  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
> +  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
> +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
> +  __syscall_ulong_t   __glibc_reserved3;
> +  __syscall_ulong_t   __glibc_reserved4;
> +};
> +#endif
> 

Ok.



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v6 3/3] sysv: linux: Pass 64-bit version of semctl syscall
  2020-04-29 21:09   ` Adhemerval Zanella
@ 2020-04-29 23:24     ` Alistair Francis
  2020-04-30 15:06       ` Adhemerval Zanella
  0 siblings, 1 reply; 8+ messages in thread
From: Alistair Francis @ 2020-04-29 23:24 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: GNU C Library, Alistair Francis, Arnd Bergmann

On Wed, Apr 29, 2020 at 2:09 PM Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
>
>
>
> On 28/04/2020 19:05, Alistair Francis via Libc-alpha wrote:
> > The semctl_syscall() function passes a union semun to the kernel. The
> > union includes struct semid_ds as a member. On 32-bit architectures the
> > Linux kernel provides a *_high version of the 32-bit sem_otime and
> > sem_ctime values. These can be combined to get a 64-bit version of the
> > time.
> >
> > This patch adjusts the struct semid_ds to support the *_high versions
> > of sem_otime and sem_ctime. For 32-bit systems with a 64-bit time_t
> > this can be used to get a 64-bit time from the two 32-bit values.
> >
> > Due to alignment differences between 64-bit and 32-bit variables we
> > also need to set nsems to ensure it's correct.
>
> I think this approach might trigger an issue on semid_ds definition for
> time64 that I only noticed now.
>
> Since the idea of semctl is not use a different entrypoint neither to add
> aditional flag when issuing the syscall (either semctl or ipc), with this
> change we need to assure that __TIMESIZE == 32 sem_otime alignment matches
> __TIMESIZE == 64 one.

I don't follow. We don't assume that sem_otime has the same allignment
for __TIMESIZE == 32 and 64. In fact for RV32 they are not alligned
the same.

>
> However for semid_ds and msqid_ds time_t members can't not properly aligned
> to be expanded to 64-bit (shmid_ds has a shm_segsz field before the
> timestamp fields) due to the ipc_perm header consisting of 9 32-bit words
> except on parisc/powerpc/sparc.  The alignment difference will make
> semctl once programs states build against a semid_ds with time_t
> being an 64-bit type.

I am missing something here as well, as that is exactly what RV32 is
testing and the glibc tests are passing (and a LInux rootFS boots).

>
> So we have 2 options here:
>
>   1. Keep the semid_ds layout as the kernel expected one and add the
>      newer time64 timestamps at the *end*, and redefine the command
>      arguments that passes a struct semid_ds to use
>      (IPC_STAT, SEM_STAT, SEM_STAT_ANY) to indicate that the semid_ds
>      is a time64 one.  The IPC_64 bit might be a feasible hack since
>      kernel won't use on possible new commands.
>
>   2. Add a new semctl64 to handle the time64 one semid_ds.
>
> > ---
> >  .../unix/sysv/linux/hppa/struct__semid_ds32.h | 32 +++++++++++++
> >  .../unix/sysv/linux/mips/struct__semid_ds32.h | 30 ++++++++++++
> >  .../sysv/linux/powerpc/struct__semid_ds32.h   | 32 +++++++++++++
> >  sysdeps/unix/sysv/linux/semctl.c              | 47 +++++++++++++++++--
> >  .../sysv/linux/sparc/struct__semid_ds32.h     | 32 +++++++++++++
> >  sysdeps/unix/sysv/linux/struct__semid_ds32.h  | 32 +++++++++++++
> >  .../unix/sysv/linux/x86/struct__semid_ds32.h  | 32 +++++++++++++
> >  7 files changed, 233 insertions(+), 4 deletions(-)
> >  create mode 100644 sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h
> >  create mode 100644 sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h
> >  create mode 100644 sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h
> >  create mode 100644 sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h
> >  create mode 100644 sysdeps/unix/sysv/linux/struct__semid_ds32.h
> >  create mode 100644 sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h
> >
> > diff --git a/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h
> > new file mode 100644
> > index 0000000000..9eceaaff2d
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h
> > @@ -0,0 +1,32 @@
> > +/* HPPA implementation of the semaphore struct __semid_ds32.
> > +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
> > +   This file is part of the GNU C Library.
> > +
> > +   The GNU C Library is free software; you can redistribute it and/or
> > +   modify it under the terms of the GNU Lesser General Public
> > +   License as published by the Free Software Foundation; either
> > +   version 2.1 of the License, or (at your option) any later version.
> > +
> > +   The GNU C Library is distributed in the hope that it will be useful,
> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> > +   Lesser General Public License for more details.
> > +
> > +   You should have received a copy of the GNU Lesser General Public
> > +   License along with the GNU C Library; if not, see
> > +   <https://www.gnu.org/licenses/>.  */
> > +
> > +#if __WORDSIZE == 32
> > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
> > +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
> > +struct __semid_ds32 {
> > +  struct ipc_perm sem_perm;              /* operation permission struct */
> > +  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
> > +  __syscall_ulong_t   sem_otime;         /* last semop() time */
> > +  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
> > +  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
> > +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
> > +  __syscall_ulong_t   __glibc_reserved3;
> > +  __syscall_ulong_t   __glibc_reserved4;
> > +};
> > +#endif
>
> No need to define it for __WORDSIZE == 32, the ABI just supports it
> anyway.

Ok, I have removed these.

>
> > diff --git a/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h
> > new file mode 100644
> > index 0000000000..2e3e2fc562
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h
> > @@ -0,0 +1,30 @@
> > +/* MIPS implementation of the semaphore struct __semid_ds32.
> > +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
> > +   This file is part of the GNU C Library.
> > +
> > +   The GNU C Library is free software; you can redistribute it and/or
> > +   modify it under the terms of the GNU Lesser General Public
> > +   License as published by the Free Software Foundation; either
> > +   version 2.1 of the License, or (at your option) any later version.
> > +
> > +   The GNU C Library is distributed in the hope that it will be useful,
> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> > +   Lesser General Public License for more details.
> > +
> > +   You should have received a copy of the GNU Lesser General Public
> > +   License along with the GNU C Library; if not, see
> > +   <https://www.gnu.org/licenses/>.  */
> > +
> > +#if __WORDSIZE == 32
> > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
> > +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
> > +struct __semid_ds32 {
> > +  struct ipc_perm sem_perm;              /* operation permission struct */
> > +  __syscall_ulong_t   sem_otime;         /* last semop time */
> > +  __syscall_ulong_t   sem_ctime;         /* last change time */
> > +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
> > +  __syscall_ulong_t   sem_otime_high;
> > +  __syscall_ulong_t   sem_ctime_high;
> > +};
> > +#endif
>
> Ok, it cover mips64-n32 as well.
>
> > diff --git a/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h
> > new file mode 100644
> > index 0000000000..f509db5a02
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h
> > @@ -0,0 +1,32 @@
> > +/* PowerPC implementation of the semaphore struct __semid_ds32.
> > +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
> > +   This file is part of the GNU C Library.
> > +
> > +   The GNU C Library is free software; you can redistribute it and/or
> > +   modify it under the terms of the GNU Lesser General Public
> > +   License as published by the Free Software Foundation; either
> > +   version 2.1 of the License, or (at your option) any later version.
> > +
> > +   The GNU C Library is distributed in the hope that it will be useful,
> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> > +   Lesser General Public License for more details.
> > +
> > +   You should have received a copy of the GNU Lesser General Public
> > +   License along with the GNU C Library; if not, see
> > +   <https://www.gnu.org/licenses/>.  */
> > +
> > +#if __WORDSIZE == 32
> > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
> > +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
> > +struct __semid_ds32 {
> > +  struct ipc_perm sem_perm;              /* operation permission struct */
> > +  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
> > +  __syscall_ulong_t   sem_otime;         /* last semop() time */
> > +  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
> > +  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
> > +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
> > +  __syscall_ulong_t   __glibc_reserved3;
> > +  __syscall_ulong_t   __glibc_reserved4;
> > +};
> > +#endif
>
> Ok.
>
> > diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c
> > index 30571af49f..0634cc1abe 100644
> > --- a/sysdeps/unix/sysv/linux/semctl.c
> > +++ b/sysdeps/unix/sysv/linux/semctl.c
> > @@ -22,8 +22,13 @@
> >  #include <sysdep.h>
> >  #include <shlib-compat.h>
> >  #include <errno.h>
> > +#include <struct__semid_ds32.h>
> >  #include <linux/posix_types.h>  /* For __kernel_mode_t.  */
> >
> > +#define IPC_TIME64 \
> > + (__WORDSIZE == 32 && __TIMESIZE == 64 \
> > +     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
>
> I think it would be better to move this definition to the common
> ipc_priv.h header since it will most likely be used on msgctl
> and shmctl y2038 support as well.

Done.

>
> > +
> >  /* Define a `union semun' suitable for Linux here.  */
> >  union semun
> >  {
> > @@ -44,13 +49,47 @@ union semun
> >  static int
> >  semctl_syscall (int semid, int semnum, int cmd, union semun arg)
> >  {
> > +  int ret;
> > +#if IPC_TIME64
>
> I think we shoul add a comment stating why we need a auxiliary buffer
> for STAT/STAT_ANY operations.  Something like:
>
>    A temporary buffer is used to avoid both an issue where the export
>    semid_ds might not have follow kernel expected layout (due
>    sem_{o,c}time alignment in 64-bit time case) and the issue where
>    some kernel version might not clear the high bits when returning
>    then sem_{o,c}time information.

Added

>
> > +  struct __semid_ds32 tmp;
> > +  struct semid_ds *orig;
> > +  bool restore = false;
> > +  if (cmd == IPC_STAT || cmd == SEM_STAT || cmd == SEM_STAT_ANY)
> > +    {
> > +      tmp = (struct __semid_ds32) {
> > +        .sem_perm  = arg.buf->sem_perm,
> > +        .sem_otime = arg.buf->sem_otime,
> > +        .sem_ctime = arg.buf->sem_ctime,
> > +        .sem_nsems = arg.buf->sem_nsems,
> > +      };
>
> We need to fully initialize the temporary struct to avoid a kernel
> issue fixed in 4693916846269d633a3664586650dbfac2c5562f (4.14) where
> kernel does not clear the timestamps high bits.

Added.

>
> > +      orig = arg.buf;
> > +      arg.buf = (struct semid_ds*)&tmp;
>
> Space before &tmp.

Added.

>
> > +      restore = true;
> > +    }
> > +#endif
> > +
> >  #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
> > -  return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64,
> > -                           arg.array);
> > +  ret = INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64,
> > +                             arg.array);
> >  #else
> > -  return INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64,
> > -                           SEMCTL_ARG_ADDRESS (arg));
> > +  ret = INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64,
> > +                             SEMCTL_ARG_ADDRESS (arg));
> >  #endif
>
> Ok.
>
> > +
> > +#if IPC_TIME64
> > +  if (ret >= 0 && restore)
> > +    {
> > +      arg.buf = orig;
> > +      arg.buf->sem_perm  = tmp.sem_perm;
> > +      arg.buf->sem_otime = tmp.sem_otime
> > +                           | ((time_t) tmp.sem_otime_high << 32);
> > +      arg.buf->sem_ctime = tmp.sem_ctime
> > +                           | ((time_t) tmp.sem_ctime_high << 32);
> > +      arg.buf->sem_nsems = tmp.sem_nsems;
>
> I think it would be better to use __time64_t explicit here.

Done.

Alistair

>
> > +    }
> > +#endif
> > +
> > +    return ret;
> >  }
> >
> >  int
> > diff --git a/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h
> > new file mode 100644
> > index 0000000000..f641825d37
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h
> > @@ -0,0 +1,32 @@
> > +/* Sparc implementation of the semaphore struct __semid_ds32.
> > +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
> > +   This file is part of the GNU C Library.
> > +
> > +   The GNU C Library is free software; you can redistribute it and/or
> > +   modify it under the terms of the GNU Lesser General Public
> > +   License as published by the Free Software Foundation; either
> > +   version 2.1 of the License, or (at your option) any later version.
> > +
> > +   The GNU C Library is distributed in the hope that it will be useful,
> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> > +   Lesser General Public License for more details.
> > +
> > +   You should have received a copy of the GNU Lesser General Public
> > +   License along with the GNU C Library; if not, see
> > +   <https://www.gnu.org/licenses/>.  */
> > +
> > +#if __WORDSIZE == 32
> > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
> > +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
> > +struct __semid_ds32 {
> > +  struct ipc_perm sem_perm;              /* operation permission struct */
> > +  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
> > +  __syscall_ulong_t   sem_otime;         /* last semop() time */
> > +  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
> > +  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
> > +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
> > +  __syscall_ulong_t   __glibc_reserved3;
> > +  __syscall_ulong_t   __glibc_reserved4;
> > +};
> > +#endif
>
> Ok.
>
> > diff --git a/sysdeps/unix/sysv/linux/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/struct__semid_ds32.h
> > new file mode 100644
> > index 0000000000..51ff83206d
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/struct__semid_ds32.h
> > @@ -0,0 +1,32 @@
> > +/* Generic implementation of the semaphore struct __semid_ds32.
> > +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
> > +   This file is part of the GNU C Library.
> > +
> > +   The GNU C Library is free software; you can redistribute it and/or
> > +   modify it under the terms of the GNU Lesser General Public
> > +   License as published by the Free Software Foundation; either
> > +   version 2.1 of the License, or (at your option) any later version.
> > +
> > +   The GNU C Library is distributed in the hope that it will be useful,
> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> > +   Lesser General Public License for more details.
> > +
> > +   You should have received a copy of the GNU Lesser General Public
> > +   License along with the GNU C Library; if not, see
> > +   <https://www.gnu.org/licenses/>.  */
> > +
> > +#if __WORDSIZE == 32
> > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
> > +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
> > +struct __semid_ds32 {
> > +  struct ipc_perm sem_perm;              /* operation permission struct */
> > +  __syscall_ulong_t   sem_otime;         /* last semop() time */
> > +  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
> > +  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
> > +  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
> > +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
> > +  __syscall_ulong_t   __glibc_reserved3;
> > +  __syscall_ulong_t   __glibc_reserved4;
> > +};
> > +#endif
>
> Ok.
>
> > diff --git a/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h
> > new file mode 100644
> > index 0000000000..f65c9fc877
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h
> > @@ -0,0 +1,32 @@
> > +/* x86 implementation of the semaphore struct __semid_ds32.
> > +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
> > +   This file is part of the GNU C Library.
> > +
> > +   The GNU C Library is free software; you can redistribute it and/or
> > +   modify it under the terms of the GNU Lesser General Public
> > +   License as published by the Free Software Foundation; either
> > +   version 2.1 of the License, or (at your option) any later version.
> > +
> > +   The GNU C Library is distributed in the hope that it will be useful,
> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> > +   Lesser General Public License for more details.
> > +
> > +   You should have received a copy of the GNU Lesser General Public
> > +   License along with the GNU C Library; if not, see
> > +   <https://www.gnu.org/licenses/>.  */
> > +
> > +#ifdef __i386__
> > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
> > +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
> > +struct __semid_ds32 {
> > +  struct ipc_perm sem_perm;              /* operation permission struct */
> > +  __syscall_ulong_t   sem_otime;         /* last semop() time */
> > +  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
> > +  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
> > +  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
> > +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
> > +  __syscall_ulong_t   __glibc_reserved3;
> > +  __syscall_ulong_t   __glibc_reserved4;
> > +};
> > +#endif
> >
>
> Ok.
>
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v6 3/3] sysv: linux: Pass 64-bit version of semctl syscall
  2020-04-29 23:24     ` Alistair Francis
@ 2020-04-30 15:06       ` Adhemerval Zanella
  2020-04-30 21:25         ` Alistair Francis
  0 siblings, 1 reply; 8+ messages in thread
From: Adhemerval Zanella @ 2020-04-30 15:06 UTC (permalink / raw)
  To: Alistair Francis; +Cc: GNU C Library, Alistair Francis, Arnd Bergmann



On 29/04/2020 20:24, Alistair Francis wrote:
> On Wed, Apr 29, 2020 at 2:09 PM Adhemerval Zanella
> <adhemerval.zanella@linaro.org> wrote:
>>
>>
>>
>> On 28/04/2020 19:05, Alistair Francis via Libc-alpha wrote:
>>> The semctl_syscall() function passes a union semun to the kernel. The
>>> union includes struct semid_ds as a member. On 32-bit architectures the
>>> Linux kernel provides a *_high version of the 32-bit sem_otime and
>>> sem_ctime values. These can be combined to get a 64-bit version of the
>>> time.
>>>
>>> This patch adjusts the struct semid_ds to support the *_high versions
>>> of sem_otime and sem_ctime. For 32-bit systems with a 64-bit time_t
>>> this can be used to get a 64-bit time from the two 32-bit values.
>>>
>>> Due to alignment differences between 64-bit and 32-bit variables we
>>> also need to set nsems to ensure it's correct.
>>
>> I think this approach might trigger an issue on semid_ds definition for
>> time64 that I only noticed now.
>>
>> Since the idea of semctl is not use a different entrypoint neither to add
>> aditional flag when issuing the syscall (either semctl or ipc), with this
>> change we need to assure that __TIMESIZE == 32 sem_otime alignment matches
>> __TIMESIZE == 64 one.
> 
> I don't follow. We don't assume that sem_otime has the same allignment
> for __TIMESIZE == 32 and 64. In fact for RV32 they are not alligned
> the same.
> 
>>
>> However for semid_ds and msqid_ds time_t members can't not properly aligned
>> to be expanded to 64-bit (shmid_ds has a shm_segsz field before the
>> timestamp fields) due to the ipc_perm header consisting of 9 32-bit words
>> except on parisc/powerpc/sparc.  The alignment difference will make
>> semctl once programs states build against a semid_ds with time_t
>> being an 64-bit type.
> 
> I am missing something here as well, as that is exactly what RV32 is
> testing and the glibc tests are passing (and a LInux rootFS boots).

The issue is for architectures that might select the __TIMESIZE at build
time, so two different semid_ds structure might be used with semctl.
For instance, on arm with current scheme:

For __TIMESIZE == 32:
  sizeof (struct ipc_perm):              36
  sizeof (struct semid_ds):              72
  offsetof (struct semid_ds, sem_perm):  0
  offsetof (struct semid_ds, sem_otime): 40
  offsetof (struct semid_ds, sem_ctime): 48
  offsetof (struct semid_ds, sem_nsems): 56

For __TIMESIZE == 64:
  sizeof (struct ipc_perm):              36
  sizeof (struct semid_ds):              64
  offsetof (struct semid_ds, sem_perm):  0
  offsetof (struct semid_ds, sem_otime): 36
  offsetof (struct semid_ds, sem_ctime): 44
  offsetof (struct semid_ds, sem_nsems): 52

The syscall itself will use the expected structure, however the code:

  if (ret >= 0 && restore)
    {
      arg.buf = orig;
      arg.buf->sem_perm  = tmp.sem_perm;
      arg.buf->sem_otime = tmp.sem_otime
                           | ((time_t) tmp.sem_otime_high << 32);
      arg.buf->sem_ctime = tmp.sem_ctime
                           | ((time_t) tmp.sem_ctime_high << 32);
      arg.buf->sem_nsems = tmp.sem_nsems;

will write down the timestamps on wrong place for time64 timestamps.

This is not an issue for 32-bit architectures that does not have
support for 32-bit time_t (as RV32).

> 
>>
>> So we have 2 options here:
>>
>>   1. Keep the semid_ds layout as the kernel expected one and add the
>>      newer time64 timestamps at the *end*, and redefine the command
>>      arguments that passes a struct semid_ds to use
>>      (IPC_STAT, SEM_STAT, SEM_STAT_ANY) to indicate that the semid_ds
>>      is a time64 one.  The IPC_64 bit might be a feasible hack since
>>      kernel won't use on possible new commands.

This solution would require to redefine IPC_STAT, SEM_STAT, SEM_STAT_ANY to
a different value for when building for __TIMESIZE==64 on ABIs that support
its selection.  The easiest way would to parametrize the ipc commands
that handle per architecture:

   /* On each ABI that supports __TIMESIZE==32.  */
   #if __TIMESIZE == 64
   # define __IPC_CMD_TIME_64 0x100  /* Same as __IPC_64.  */
   #else
   # define __IPC_CMD_TIME_64 0x0
   #endif
   #define __IPC_TIME_64 1

If fro architecture only support __TIMESIZE64 (default):

   #define __IPC_CMD_TIME64 0x0
   #define __IPC_TIME_64    0

Then on Linux ipc.h:

   #define IPC_STAT         (2 | __IPC_CMD_TIME_64)

Same for sem.h:

   #define SEM_STAT        (18 | __IPC_CMD_TIME_64)
   #define SEM_STAT_ANY    (20 | __IPC_CMD_TIME_64)

Then on semctl.c (totally untested):

---
union semun
{ 
  int val;                      /* value for SETVAL */
#if __IPC_TIME_64
  struct __semid_ds32 *buf32;
#endif
  struct semid_ds *buf;         /* buffer for IPC_STAT & IPC_SET */
  unsigned short int *array;    /* array for GETALL & SETALL */
  struct seminfo *__buf;        /* buffer for IPC_INFO */
};

int
__new_semctl (int semid, int semnum, int cmd, ...)
{
  /* POSIX states ipc_perm mode should have type of mode_t.  */
  _Static_assert (sizeof ((struct semid_ds){0}.sem_perm.mode)
                  == sizeof (mode_t),
                  "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");

  union semun arg = { 0 };
  va_list ap;

  /* Get the argument only if required.  Ignore the __IPC_STAT_64.  */
  switch (cmd & ~__IPC_CMD_TIME_64)
    {
    case SETVAL:                        /* arg.val */
    case GETALL:                        /* arg.array */
    case SETALL:
    case IPC_STAT & ~__IPC_CMD_TIME_64: /* arg.buf */
    case IPC_SET:
    case SEM_STAT & ~__IPC_CMD_TIME_64:
    case IPC_INFO:                      /* arg.__buf */
    case SEM_INFO:
      va_start (ap, cmd);
      arg = va_arg (ap, union semun);
      va_end (ap);
      break;
    }

#ifdef __IPC_TIME_64
  struct __semid_ds32 tmp32;
  struct __semid_ds64 *orig64;
  if (cmd & __IPC_STAT_64)
    {
       tmp32 = (struct __semid_ds32) { 0 };
       orig64 = (struct __semid_ds64 *) arg.buf;
       arg.buf32 = tmp32;
    }
#endif

#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
  struct semid_ds tmpds;
  if (cmd == IPC_SET)
    {
      tmpds = *arg.buf;
      tmpds.sem_perm.mode *= 0x10000U;
      arg.buf = &tmpds;
    }
#endif

  int ret = semctl_syscall (semid, semnum, cmd & ~__IPC_CMD_TIME_64, arg);
  if (ret < 0)
    return ret;

  switch (cmd & ~__IPC_CMD_TIME_64)
    {
    case IPC_STAT:
    case SEM_STAT:
    case SEM_STAT_ANY:
#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
# if __IPC_TIME_64
      arg.buf32->sem_perm.mode >>= 16;
# else
      arg.buf->sem_perm.mode >>= 16;
# endif
#else
      /* Old Linux kernel versions might not clear the mode padding.  */
      if (sizeof ((struct semid_ds){0}.sem_perm.mode)
          !  = sizeof (__kernel_mode_t))
# if __IPC_TIME_64
        arg.buf32->sem_perm.mode &= 0xFFFF;
# else
        arg.buf->sem_perm.mode &= 0xFFFF;
# endif
#endif
    }

#ifdef __IPC_TIME_64
  if (cmd & & ~__IPC_CMD_TIME_64)
    {
      orig64->sem_perm = tmp32.sem_perm;
      orig64->sem_otime = tmp32.sem_otime
			  | ((__time64_t) tmp32.sem_otime_high << 32);
      orig64->sem_ctime = tmp32.sem_ctime
			  | ((__time64_t) tmp32.sem_ctime_high << 32);
      orig64->sem_nsems = tmp32.sem_nsems;
      arg.buf = (struct semid_ds *) orig64;
    }
#endif

  return ret;
}
---

So basically:

  1. If an ABI issues 'semctl (semid, semnum, IPC_STAT, ...)' with 
     IPC_STAT without _IPC_CMD_TIME_64, the provided semid_ds buffe
     will be used directly on the syscall.  This is the case for
     64-bit architectures and 32-bit architecture without
     __TIMESIZE==32 support (RV32 for instance).

  2. If an ABI issues 'semctl (semid, semnum, IPC_STAT, ...)' with
     IPC_STAT with _IPC_CMD_TIME_64 then __TIMESIZE==64 is implied.
     A temporary __semid_ds32 will be used to issue the syscall and its
     contents will be copied to users semid_ds buffer (which is also
     implied to be the __TIMESIZE==64).

There is the requeriment to use define __semid_ds64 that uses __time64_t
explicitly for architecture that support __TIMESIZE==32.

(The handling of __ASSUME_SYSVIPC_BROKEN_MODE_T and the kernel issue
regarding sem_perm.mode clearing could be improved/simplified).

>>
>>   2. Add a new semctl64 to handle the time64 one semid_ds.
>>
>>> ---
>>>  .../unix/sysv/linux/hppa/struct__semid_ds32.h | 32 +++++++++++++
>>>  .../unix/sysv/linux/mips/struct__semid_ds32.h | 30 ++++++++++++
>>>  .../sysv/linux/powerpc/struct__semid_ds32.h   | 32 +++++++++++++
>>>  sysdeps/unix/sysv/linux/semctl.c              | 47 +++++++++++++++++--
>>>  .../sysv/linux/sparc/struct__semid_ds32.h     | 32 +++++++++++++
>>>  sysdeps/unix/sysv/linux/struct__semid_ds32.h  | 32 +++++++++++++
>>>  .../unix/sysv/linux/x86/struct__semid_ds32.h  | 32 +++++++++++++
>>>  7 files changed, 233 insertions(+), 4 deletions(-)
>>>  create mode 100644 sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h
>>>  create mode 100644 sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h
>>>  create mode 100644 sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h
>>>  create mode 100644 sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h
>>>  create mode 100644 sysdeps/unix/sysv/linux/struct__semid_ds32.h
>>>  create mode 100644 sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h
>>>
>>> diff --git a/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h
>>> new file mode 100644
>>> index 0000000000..9eceaaff2d
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h
>>> @@ -0,0 +1,32 @@
>>> +/* HPPA implementation of the semaphore struct __semid_ds32.
>>> +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
>>> +   This file is part of the GNU C Library.
>>> +
>>> +   The GNU C Library is free software; you can redistribute it and/or
>>> +   modify it under the terms of the GNU Lesser General Public
>>> +   License as published by the Free Software Foundation; either
>>> +   version 2.1 of the License, or (at your option) any later version.
>>> +
>>> +   The GNU C Library is distributed in the hope that it will be useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> +   Lesser General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU Lesser General Public
>>> +   License along with the GNU C Library; if not, see
>>> +   <https://www.gnu.org/licenses/>.  */
>>> +
>>> +#if __WORDSIZE == 32
>>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
>>> +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
>>> +struct __semid_ds32 {
>>> +  struct ipc_perm sem_perm;              /* operation permission struct */
>>> +  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
>>> +  __syscall_ulong_t   sem_otime;         /* last semop() time */
>>> +  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
>>> +  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
>>> +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
>>> +  __syscall_ulong_t   __glibc_reserved3;
>>> +  __syscall_ulong_t   __glibc_reserved4;
>>> +};
>>> +#endif
>>
>> No need to define it for __WORDSIZE == 32, the ABI just supports it
>> anyway.
> 
> Ok, I have removed these.
> 
>>
>>> diff --git a/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h
>>> new file mode 100644
>>> index 0000000000..2e3e2fc562
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h
>>> @@ -0,0 +1,30 @@
>>> +/* MIPS implementation of the semaphore struct __semid_ds32.
>>> +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
>>> +   This file is part of the GNU C Library.
>>> +
>>> +   The GNU C Library is free software; you can redistribute it and/or
>>> +   modify it under the terms of the GNU Lesser General Public
>>> +   License as published by the Free Software Foundation; either
>>> +   version 2.1 of the License, or (at your option) any later version.
>>> +
>>> +   The GNU C Library is distributed in the hope that it will be useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> +   Lesser General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU Lesser General Public
>>> +   License along with the GNU C Library; if not, see
>>> +   <https://www.gnu.org/licenses/>.  */
>>> +
>>> +#if __WORDSIZE == 32
>>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
>>> +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
>>> +struct __semid_ds32 {
>>> +  struct ipc_perm sem_perm;              /* operation permission struct */
>>> +  __syscall_ulong_t   sem_otime;         /* last semop time */
>>> +  __syscall_ulong_t   sem_ctime;         /* last change time */
>>> +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
>>> +  __syscall_ulong_t   sem_otime_high;
>>> +  __syscall_ulong_t   sem_ctime_high;
>>> +};
>>> +#endif
>>
>> Ok, it cover mips64-n32 as well.
>>
>>> diff --git a/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h
>>> new file mode 100644
>>> index 0000000000..f509db5a02
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h
>>> @@ -0,0 +1,32 @@
>>> +/* PowerPC implementation of the semaphore struct __semid_ds32.
>>> +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
>>> +   This file is part of the GNU C Library.
>>> +
>>> +   The GNU C Library is free software; you can redistribute it and/or
>>> +   modify it under the terms of the GNU Lesser General Public
>>> +   License as published by the Free Software Foundation; either
>>> +   version 2.1 of the License, or (at your option) any later version.
>>> +
>>> +   The GNU C Library is distributed in the hope that it will be useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> +   Lesser General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU Lesser General Public
>>> +   License along with the GNU C Library; if not, see
>>> +   <https://www.gnu.org/licenses/>.  */
>>> +
>>> +#if __WORDSIZE == 32
>>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
>>> +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
>>> +struct __semid_ds32 {
>>> +  struct ipc_perm sem_perm;              /* operation permission struct */
>>> +  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
>>> +  __syscall_ulong_t   sem_otime;         /* last semop() time */
>>> +  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
>>> +  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
>>> +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
>>> +  __syscall_ulong_t   __glibc_reserved3;
>>> +  __syscall_ulong_t   __glibc_reserved4;
>>> +};
>>> +#endif
>>
>> Ok.
>>
>>> diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c
>>> index 30571af49f..0634cc1abe 100644
>>> --- a/sysdeps/unix/sysv/linux/semctl.c
>>> +++ b/sysdeps/unix/sysv/linux/semctl.c
>>> @@ -22,8 +22,13 @@
>>>  #include <sysdep.h>
>>>  #include <shlib-compat.h>
>>>  #include <errno.h>
>>> +#include <struct__semid_ds32.h>
>>>  #include <linux/posix_types.h>  /* For __kernel_mode_t.  */
>>>
>>> +#define IPC_TIME64 \
>>> + (__WORDSIZE == 32 && __TIMESIZE == 64 \
>>> +     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
>>
>> I think it would be better to move this definition to the common
>> ipc_priv.h header since it will most likely be used on msgctl
>> and shmctl y2038 support as well.
> 
> Done.
> 
>>
>>> +
>>>  /* Define a `union semun' suitable for Linux here.  */
>>>  union semun
>>>  {
>>> @@ -44,13 +49,47 @@ union semun
>>>  static int
>>>  semctl_syscall (int semid, int semnum, int cmd, union semun arg)
>>>  {
>>> +  int ret;
>>> +#if IPC_TIME64
>>
>> I think we shoul add a comment stating why we need a auxiliary buffer
>> for STAT/STAT_ANY operations.  Something like:
>>
>>    A temporary buffer is used to avoid both an issue where the export
>>    semid_ds might not have follow kernel expected layout (due
>>    sem_{o,c}time alignment in 64-bit time case) and the issue where
>>    some kernel version might not clear the high bits when returning
>>    then sem_{o,c}time information.
> 
> Added
> 
>>
>>> +  struct __semid_ds32 tmp;
>>> +  struct semid_ds *orig;
>>> +  bool restore = false;
>>> +  if (cmd == IPC_STAT || cmd == SEM_STAT || cmd == SEM_STAT_ANY)
>>> +    {
>>> +      tmp = (struct __semid_ds32) {
>>> +        .sem_perm  = arg.buf->sem_perm,
>>> +        .sem_otime = arg.buf->sem_otime,
>>> +        .sem_ctime = arg.buf->sem_ctime,
>>> +        .sem_nsems = arg.buf->sem_nsems,
>>> +      };
>>
>> We need to fully initialize the temporary struct to avoid a kernel
>> issue fixed in 4693916846269d633a3664586650dbfac2c5562f (4.14) where
>> kernel does not clear the timestamps high bits.
> 
> Added.
> 
>>
>>> +      orig = arg.buf;
>>> +      arg.buf = (struct semid_ds*)&tmp;
>>
>> Space before &tmp.
> 
> Added.
> 
>>
>>> +      restore = true;
>>> +    }
>>> +#endif
>>> +
>>>  #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
>>> -  return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64,
>>> -                           arg.array);
>>> +  ret = INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64,
>>> +                             arg.array);
>>>  #else
>>> -  return INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64,
>>> -                           SEMCTL_ARG_ADDRESS (arg));
>>> +  ret = INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64,
>>> +                             SEMCTL_ARG_ADDRESS (arg));
>>>  #endif
>>
>> Ok.
>>
>>> +
>>> +#if IPC_TIME64
>>> +  if (ret >= 0 && restore)
>>> +    {
>>> +      arg.buf = orig;
>>> +      arg.buf->sem_perm  = tmp.sem_perm;
>>> +      arg.buf->sem_otime = tmp.sem_otime
>>> +                           | ((time_t) tmp.sem_otime_high << 32);
>>> +      arg.buf->sem_ctime = tmp.sem_ctime
>>> +                           | ((time_t) tmp.sem_ctime_high << 32);
>>> +      arg.buf->sem_nsems = tmp.sem_nsems;
>>
>> I think it would be better to use __time64_t explicit here.
> 
> Done.
> 
> Alistair
> 
>>
>>> +    }
>>> +#endif
>>> +
>>> +    return ret;
>>>  }
>>>
>>>  int
>>> diff --git a/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h
>>> new file mode 100644
>>> index 0000000000..f641825d37
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h
>>> @@ -0,0 +1,32 @@
>>> +/* Sparc implementation of the semaphore struct __semid_ds32.
>>> +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
>>> +   This file is part of the GNU C Library.
>>> +
>>> +   The GNU C Library is free software; you can redistribute it and/or
>>> +   modify it under the terms of the GNU Lesser General Public
>>> +   License as published by the Free Software Foundation; either
>>> +   version 2.1 of the License, or (at your option) any later version.
>>> +
>>> +   The GNU C Library is distributed in the hope that it will be useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> +   Lesser General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU Lesser General Public
>>> +   License along with the GNU C Library; if not, see
>>> +   <https://www.gnu.org/licenses/>.  */
>>> +
>>> +#if __WORDSIZE == 32
>>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
>>> +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
>>> +struct __semid_ds32 {
>>> +  struct ipc_perm sem_perm;              /* operation permission struct */
>>> +  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
>>> +  __syscall_ulong_t   sem_otime;         /* last semop() time */
>>> +  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
>>> +  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
>>> +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
>>> +  __syscall_ulong_t   __glibc_reserved3;
>>> +  __syscall_ulong_t   __glibc_reserved4;
>>> +};
>>> +#endif
>>
>> Ok.
>>
>>> diff --git a/sysdeps/unix/sysv/linux/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/struct__semid_ds32.h
>>> new file mode 100644
>>> index 0000000000..51ff83206d
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/struct__semid_ds32.h
>>> @@ -0,0 +1,32 @@
>>> +/* Generic implementation of the semaphore struct __semid_ds32.
>>> +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
>>> +   This file is part of the GNU C Library.
>>> +
>>> +   The GNU C Library is free software; you can redistribute it and/or
>>> +   modify it under the terms of the GNU Lesser General Public
>>> +   License as published by the Free Software Foundation; either
>>> +   version 2.1 of the License, or (at your option) any later version.
>>> +
>>> +   The GNU C Library is distributed in the hope that it will be useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> +   Lesser General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU Lesser General Public
>>> +   License along with the GNU C Library; if not, see
>>> +   <https://www.gnu.org/licenses/>.  */
>>> +
>>> +#if __WORDSIZE == 32
>>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
>>> +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
>>> +struct __semid_ds32 {
>>> +  struct ipc_perm sem_perm;              /* operation permission struct */
>>> +  __syscall_ulong_t   sem_otime;         /* last semop() time */
>>> +  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
>>> +  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
>>> +  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
>>> +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
>>> +  __syscall_ulong_t   __glibc_reserved3;
>>> +  __syscall_ulong_t   __glibc_reserved4;
>>> +};
>>> +#endif
>>
>> Ok.
>>
>>> diff --git a/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h
>>> new file mode 100644
>>> index 0000000000..f65c9fc877
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h
>>> @@ -0,0 +1,32 @@
>>> +/* x86 implementation of the semaphore struct __semid_ds32.
>>> +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
>>> +   This file is part of the GNU C Library.
>>> +
>>> +   The GNU C Library is free software; you can redistribute it and/or
>>> +   modify it under the terms of the GNU Lesser General Public
>>> +   License as published by the Free Software Foundation; either
>>> +   version 2.1 of the License, or (at your option) any later version.
>>> +
>>> +   The GNU C Library is distributed in the hope that it will be useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> +   Lesser General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU Lesser General Public
>>> +   License along with the GNU C Library; if not, see
>>> +   <https://www.gnu.org/licenses/>.  */
>>> +
>>> +#ifdef __i386__
>>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
>>> +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
>>> +struct __semid_ds32 {
>>> +  struct ipc_perm sem_perm;              /* operation permission struct */
>>> +  __syscall_ulong_t   sem_otime;         /* last semop() time */
>>> +  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
>>> +  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
>>> +  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
>>> +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
>>> +  __syscall_ulong_t   __glibc_reserved3;
>>> +  __syscall_ulong_t   __glibc_reserved4;
>>> +};
>>> +#endif
>>>
>>
>> Ok.
>>
>>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v6 3/3] sysv: linux: Pass 64-bit version of semctl syscall
  2020-04-30 15:06       ` Adhemerval Zanella
@ 2020-04-30 21:25         ` Alistair Francis
  0 siblings, 0 replies; 8+ messages in thread
From: Alistair Francis @ 2020-04-30 21:25 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: GNU C Library, Alistair Francis, Arnd Bergmann

On Thu, Apr 30, 2020 at 8:06 AM Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
>
>
>
> On 29/04/2020 20:24, Alistair Francis wrote:
> > On Wed, Apr 29, 2020 at 2:09 PM Adhemerval Zanella
> > <adhemerval.zanella@linaro.org> wrote:
> >>
> >>
> >>
> >> On 28/04/2020 19:05, Alistair Francis via Libc-alpha wrote:
> >>> The semctl_syscall() function passes a union semun to the kernel. The
> >>> union includes struct semid_ds as a member. On 32-bit architectures the
> >>> Linux kernel provides a *_high version of the 32-bit sem_otime and
> >>> sem_ctime values. These can be combined to get a 64-bit version of the
> >>> time.
> >>>
> >>> This patch adjusts the struct semid_ds to support the *_high versions
> >>> of sem_otime and sem_ctime. For 32-bit systems with a 64-bit time_t
> >>> this can be used to get a 64-bit time from the two 32-bit values.
> >>>
> >>> Due to alignment differences between 64-bit and 32-bit variables we
> >>> also need to set nsems to ensure it's correct.
> >>
> >> I think this approach might trigger an issue on semid_ds definition for
> >> time64 that I only noticed now.
> >>
> >> Since the idea of semctl is not use a different entrypoint neither to add
> >> aditional flag when issuing the syscall (either semctl or ipc), with this
> >> change we need to assure that __TIMESIZE == 32 sem_otime alignment matches
> >> __TIMESIZE == 64 one.
> >
> > I don't follow. We don't assume that sem_otime has the same allignment
> > for __TIMESIZE == 32 and 64. In fact for RV32 they are not alligned
> > the same.
> >
> >>
> >> However for semid_ds and msqid_ds time_t members can't not properly aligned
> >> to be expanded to 64-bit (shmid_ds has a shm_segsz field before the
> >> timestamp fields) due to the ipc_perm header consisting of 9 32-bit words
> >> except on parisc/powerpc/sparc.  The alignment difference will make
> >> semctl once programs states build against a semid_ds with time_t
> >> being an 64-bit type.
> >
> > I am missing something here as well, as that is exactly what RV32 is
> > testing and the glibc tests are passing (and a LInux rootFS boots).
>
> The issue is for architectures that might select the __TIMESIZE at build
> time, so two different semid_ds structure might be used with semctl.
> For instance, on arm with current scheme:
>
> For __TIMESIZE == 32:
>   sizeof (struct ipc_perm):              36
>   sizeof (struct semid_ds):              72
>   offsetof (struct semid_ds, sem_perm):  0
>   offsetof (struct semid_ds, sem_otime): 40
>   offsetof (struct semid_ds, sem_ctime): 48
>   offsetof (struct semid_ds, sem_nsems): 56
>
> For __TIMESIZE == 64:
>   sizeof (struct ipc_perm):              36
>   sizeof (struct semid_ds):              64
>   offsetof (struct semid_ds, sem_perm):  0
>   offsetof (struct semid_ds, sem_otime): 36
>   offsetof (struct semid_ds, sem_ctime): 44
>   offsetof (struct semid_ds, sem_nsems): 52
>
> The syscall itself will use the expected structure, however the code:
>
>   if (ret >= 0 && restore)
>     {
>       arg.buf = orig;
>       arg.buf->sem_perm  = tmp.sem_perm;
>       arg.buf->sem_otime = tmp.sem_otime
>                            | ((time_t) tmp.sem_otime_high << 32);
>       arg.buf->sem_ctime = tmp.sem_ctime
>                            | ((time_t) tmp.sem_ctime_high << 32);
>       arg.buf->sem_nsems = tmp.sem_nsems;
>
> will write down the timestamps on wrong place for time64 timestamps.

Ok, I think I understand now.

>
> This is not an issue for 32-bit architectures that does not have
> support for 32-bit time_t (as RV32).
>
> >
> >>
> >> So we have 2 options here:
> >>
> >>   1. Keep the semid_ds layout as the kernel expected one and add the
> >>      newer time64 timestamps at the *end*, and redefine the command
> >>      arguments that passes a struct semid_ds to use
> >>      (IPC_STAT, SEM_STAT, SEM_STAT_ANY) to indicate that the semid_ds
> >>      is a time64 one.  The IPC_64 bit might be a feasible hack since
> >>      kernel won't use on possible new commands.
>
> This solution would require to redefine IPC_STAT, SEM_STAT, SEM_STAT_ANY to
> a different value for when building for __TIMESIZE==64 on ABIs that support
> its selection.  The easiest way would to parametrize the ipc commands
> that handle per architecture:
>
>    /* On each ABI that supports __TIMESIZE==32.  */
>    #if __TIMESIZE == 64
>    # define __IPC_CMD_TIME_64 0x100  /* Same as __IPC_64.  */
>    #else
>    # define __IPC_CMD_TIME_64 0x0
>    #endif
>    #define __IPC_TIME_64 1

So this should be for every __WORDSIZE ==32 except RV32?

I'm not sure of a good place to put this though

>
> If fro architecture only support __TIMESIZE64 (default):
>
>    #define __IPC_CMD_TIME64 0x0
>    #define __IPC_TIME_64    0

For all __WORDSIZE == 64 and RV32.

I have this in ipc_priv.h (before the include sys/ipc.h) but I'm not
sure if that will work, testing now.

>
> Then on Linux ipc.h:
>
>    #define IPC_STAT         (2 | __IPC_CMD_TIME_64)

Done.

>
> Same for sem.h:
>
>    #define SEM_STAT        (18 | __IPC_CMD_TIME_64)
>    #define SEM_STAT_ANY    (20 | __IPC_CMD_TIME_64)

Done.

>
> Then on semctl.c (totally untested):
>
> ---
> union semun
> {
>   int val;                      /* value for SETVAL */
> #if __IPC_TIME_64
>   struct __semid_ds32 *buf32;
> #endif
>   struct semid_ds *buf;         /* buffer for IPC_STAT & IPC_SET */
>   unsigned short int *array;    /* array for GETALL & SETALL */
>   struct seminfo *__buf;        /* buffer for IPC_INFO */
> };
>
> int
> __new_semctl (int semid, int semnum, int cmd, ...)
> {
>   /* POSIX states ipc_perm mode should have type of mode_t.  */
>   _Static_assert (sizeof ((struct semid_ds){0}.sem_perm.mode)
>                   == sizeof (mode_t),
>                   "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");
>
>   union semun arg = { 0 };
>   va_list ap;
>
>   /* Get the argument only if required.  Ignore the __IPC_STAT_64.  */
>   switch (cmd & ~__IPC_CMD_TIME_64)
>     {
>     case SETVAL:                        /* arg.val */
>     case GETALL:                        /* arg.array */
>     case SETALL:
>     case IPC_STAT & ~__IPC_CMD_TIME_64: /* arg.buf */
>     case IPC_SET:
>     case SEM_STAT & ~__IPC_CMD_TIME_64:
>     case IPC_INFO:                      /* arg.__buf */
>     case SEM_INFO:
>       va_start (ap, cmd);
>       arg = va_arg (ap, union semun);
>       va_end (ap);
>       break;
>     }
>
> #ifdef __IPC_TIME_64
>   struct __semid_ds32 tmp32;
>   struct __semid_ds64 *orig64;
>   if (cmd & __IPC_STAT_64)
>     {
>        tmp32 = (struct __semid_ds32) { 0 };
>        orig64 = (struct __semid_ds64 *) arg.buf;
>        arg.buf32 = tmp32;
>     }
> #endif
>
> #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
>   struct semid_ds tmpds;
>   if (cmd == IPC_SET)
>     {
>       tmpds = *arg.buf;
>       tmpds.sem_perm.mode *= 0x10000U;
>       arg.buf = &tmpds;
>     }
> #endif
>
>   int ret = semctl_syscall (semid, semnum, cmd & ~__IPC_CMD_TIME_64, arg);
>   if (ret < 0)
>     return ret;
>
>   switch (cmd & ~__IPC_CMD_TIME_64)
>     {
>     case IPC_STAT:
>     case SEM_STAT:
>     case SEM_STAT_ANY:
> #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> # if __IPC_TIME_64
>       arg.buf32->sem_perm.mode >>= 16;
> # else
>       arg.buf->sem_perm.mode >>= 16;
> # endif
> #else
>       /* Old Linux kernel versions might not clear the mode padding.  */
>       if (sizeof ((struct semid_ds){0}.sem_perm.mode)
>           !  = sizeof (__kernel_mode_t))
> # if __IPC_TIME_64
>         arg.buf32->sem_perm.mode &= 0xFFFF;
> # else
>         arg.buf->sem_perm.mode &= 0xFFFF;
> # endif
> #endif
>     }
>
> #ifdef __IPC_TIME_64
>   if (cmd & & ~__IPC_CMD_TIME_64)
>     {
>       orig64->sem_perm = tmp32.sem_perm;
>       orig64->sem_otime = tmp32.sem_otime
>                           | ((__time64_t) tmp32.sem_otime_high << 32);
>       orig64->sem_ctime = tmp32.sem_ctime
>                           | ((__time64_t) tmp32.sem_ctime_high << 32);
>       orig64->sem_nsems = tmp32.sem_nsems;
>       arg.buf = (struct semid_ds *) orig64;
>     }
> #endif
>
>   return ret;
> }

Ok, compile testing now.

Alistair

> ---
>
> So basically:
>
>   1. If an ABI issues 'semctl (semid, semnum, IPC_STAT, ...)' with
>      IPC_STAT without _IPC_CMD_TIME_64, the provided semid_ds buffe
>      will be used directly on the syscall.  This is the case for
>      64-bit architectures and 32-bit architecture without
>      __TIMESIZE==32 support (RV32 for instance).
>
>   2. If an ABI issues 'semctl (semid, semnum, IPC_STAT, ...)' with
>      IPC_STAT with _IPC_CMD_TIME_64 then __TIMESIZE==64 is implied.
>      A temporary __semid_ds32 will be used to issue the syscall and its
>      contents will be copied to users semid_ds buffer (which is also
>      implied to be the __TIMESIZE==64).
>
> There is the requeriment to use define __semid_ds64 that uses __time64_t
> explicitly for architecture that support __TIMESIZE==32.
>
> (The handling of __ASSUME_SYSVIPC_BROKEN_MODE_T and the kernel issue
> regarding sem_perm.mode clearing could be improved/simplified).
>
> >>
> >>   2. Add a new semctl64 to handle the time64 one semid_ds.
> >>
> >>> ---
> >>>  .../unix/sysv/linux/hppa/struct__semid_ds32.h | 32 +++++++++++++
> >>>  .../unix/sysv/linux/mips/struct__semid_ds32.h | 30 ++++++++++++
> >>>  .../sysv/linux/powerpc/struct__semid_ds32.h   | 32 +++++++++++++
> >>>  sysdeps/unix/sysv/linux/semctl.c              | 47 +++++++++++++++++--
> >>>  .../sysv/linux/sparc/struct__semid_ds32.h     | 32 +++++++++++++
> >>>  sysdeps/unix/sysv/linux/struct__semid_ds32.h  | 32 +++++++++++++
> >>>  .../unix/sysv/linux/x86/struct__semid_ds32.h  | 32 +++++++++++++
> >>>  7 files changed, 233 insertions(+), 4 deletions(-)
> >>>  create mode 100644 sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h
> >>>  create mode 100644 sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h
> >>>  create mode 100644 sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h
> >>>  create mode 100644 sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h
> >>>  create mode 100644 sysdeps/unix/sysv/linux/struct__semid_ds32.h
> >>>  create mode 100644 sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h
> >>>
> >>> diff --git a/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h
> >>> new file mode 100644
> >>> index 0000000000..9eceaaff2d
> >>> --- /dev/null
> >>> +++ b/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h
> >>> @@ -0,0 +1,32 @@
> >>> +/* HPPA implementation of the semaphore struct __semid_ds32.
> >>> +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
> >>> +   This file is part of the GNU C Library.
> >>> +
> >>> +   The GNU C Library is free software; you can redistribute it and/or
> >>> +   modify it under the terms of the GNU Lesser General Public
> >>> +   License as published by the Free Software Foundation; either
> >>> +   version 2.1 of the License, or (at your option) any later version.
> >>> +
> >>> +   The GNU C Library is distributed in the hope that it will be useful,
> >>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> >>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> >>> +   Lesser General Public License for more details.
> >>> +
> >>> +   You should have received a copy of the GNU Lesser General Public
> >>> +   License along with the GNU C Library; if not, see
> >>> +   <https://www.gnu.org/licenses/>.  */
> >>> +
> >>> +#if __WORDSIZE == 32
> >>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
> >>> +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
> >>> +struct __semid_ds32 {
> >>> +  struct ipc_perm sem_perm;              /* operation permission struct */
> >>> +  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
> >>> +  __syscall_ulong_t   sem_otime;         /* last semop() time */
> >>> +  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
> >>> +  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
> >>> +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
> >>> +  __syscall_ulong_t   __glibc_reserved3;
> >>> +  __syscall_ulong_t   __glibc_reserved4;
> >>> +};
> >>> +#endif
> >>
> >> No need to define it for __WORDSIZE == 32, the ABI just supports it
> >> anyway.
> >
> > Ok, I have removed these.
> >
> >>
> >>> diff --git a/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h
> >>> new file mode 100644
> >>> index 0000000000..2e3e2fc562
> >>> --- /dev/null
> >>> +++ b/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h
> >>> @@ -0,0 +1,30 @@
> >>> +/* MIPS implementation of the semaphore struct __semid_ds32.
> >>> +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
> >>> +   This file is part of the GNU C Library.
> >>> +
> >>> +   The GNU C Library is free software; you can redistribute it and/or
> >>> +   modify it under the terms of the GNU Lesser General Public
> >>> +   License as published by the Free Software Foundation; either
> >>> +   version 2.1 of the License, or (at your option) any later version.
> >>> +
> >>> +   The GNU C Library is distributed in the hope that it will be useful,
> >>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> >>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> >>> +   Lesser General Public License for more details.
> >>> +
> >>> +   You should have received a copy of the GNU Lesser General Public
> >>> +   License along with the GNU C Library; if not, see
> >>> +   <https://www.gnu.org/licenses/>.  */
> >>> +
> >>> +#if __WORDSIZE == 32
> >>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
> >>> +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
> >>> +struct __semid_ds32 {
> >>> +  struct ipc_perm sem_perm;              /* operation permission struct */
> >>> +  __syscall_ulong_t   sem_otime;         /* last semop time */
> >>> +  __syscall_ulong_t   sem_ctime;         /* last change time */
> >>> +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
> >>> +  __syscall_ulong_t   sem_otime_high;
> >>> +  __syscall_ulong_t   sem_ctime_high;
> >>> +};
> >>> +#endif
> >>
> >> Ok, it cover mips64-n32 as well.
> >>
> >>> diff --git a/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h
> >>> new file mode 100644
> >>> index 0000000000..f509db5a02
> >>> --- /dev/null
> >>> +++ b/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h
> >>> @@ -0,0 +1,32 @@
> >>> +/* PowerPC implementation of the semaphore struct __semid_ds32.
> >>> +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
> >>> +   This file is part of the GNU C Library.
> >>> +
> >>> +   The GNU C Library is free software; you can redistribute it and/or
> >>> +   modify it under the terms of the GNU Lesser General Public
> >>> +   License as published by the Free Software Foundation; either
> >>> +   version 2.1 of the License, or (at your option) any later version.
> >>> +
> >>> +   The GNU C Library is distributed in the hope that it will be useful,
> >>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> >>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> >>> +   Lesser General Public License for more details.
> >>> +
> >>> +   You should have received a copy of the GNU Lesser General Public
> >>> +   License along with the GNU C Library; if not, see
> >>> +   <https://www.gnu.org/licenses/>.  */
> >>> +
> >>> +#if __WORDSIZE == 32
> >>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
> >>> +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
> >>> +struct __semid_ds32 {
> >>> +  struct ipc_perm sem_perm;              /* operation permission struct */
> >>> +  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
> >>> +  __syscall_ulong_t   sem_otime;         /* last semop() time */
> >>> +  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
> >>> +  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
> >>> +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
> >>> +  __syscall_ulong_t   __glibc_reserved3;
> >>> +  __syscall_ulong_t   __glibc_reserved4;
> >>> +};
> >>> +#endif
> >>
> >> Ok.
> >>
> >>> diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c
> >>> index 30571af49f..0634cc1abe 100644
> >>> --- a/sysdeps/unix/sysv/linux/semctl.c
> >>> +++ b/sysdeps/unix/sysv/linux/semctl.c
> >>> @@ -22,8 +22,13 @@
> >>>  #include <sysdep.h>
> >>>  #include <shlib-compat.h>
> >>>  #include <errno.h>
> >>> +#include <struct__semid_ds32.h>
> >>>  #include <linux/posix_types.h>  /* For __kernel_mode_t.  */
> >>>
> >>> +#define IPC_TIME64 \
> >>> + (__WORDSIZE == 32 && __TIMESIZE == 64 \
> >>> +     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
> >>
> >> I think it would be better to move this definition to the common
> >> ipc_priv.h header since it will most likely be used on msgctl
> >> and shmctl y2038 support as well.
> >
> > Done.
> >
> >>
> >>> +
> >>>  /* Define a `union semun' suitable for Linux here.  */
> >>>  union semun
> >>>  {
> >>> @@ -44,13 +49,47 @@ union semun
> >>>  static int
> >>>  semctl_syscall (int semid, int semnum, int cmd, union semun arg)
> >>>  {
> >>> +  int ret;
> >>> +#if IPC_TIME64
> >>
> >> I think we shoul add a comment stating why we need a auxiliary buffer
> >> for STAT/STAT_ANY operations.  Something like:
> >>
> >>    A temporary buffer is used to avoid both an issue where the export
> >>    semid_ds might not have follow kernel expected layout (due
> >>    sem_{o,c}time alignment in 64-bit time case) and the issue where
> >>    some kernel version might not clear the high bits when returning
> >>    then sem_{o,c}time information.
> >
> > Added
> >
> >>
> >>> +  struct __semid_ds32 tmp;
> >>> +  struct semid_ds *orig;
> >>> +  bool restore = false;
> >>> +  if (cmd == IPC_STAT || cmd == SEM_STAT || cmd == SEM_STAT_ANY)
> >>> +    {
> >>> +      tmp = (struct __semid_ds32) {
> >>> +        .sem_perm  = arg.buf->sem_perm,
> >>> +        .sem_otime = arg.buf->sem_otime,
> >>> +        .sem_ctime = arg.buf->sem_ctime,
> >>> +        .sem_nsems = arg.buf->sem_nsems,
> >>> +      };
> >>
> >> We need to fully initialize the temporary struct to avoid a kernel
> >> issue fixed in 4693916846269d633a3664586650dbfac2c5562f (4.14) where
> >> kernel does not clear the timestamps high bits.
> >
> > Added.
> >
> >>
> >>> +      orig = arg.buf;
> >>> +      arg.buf = (struct semid_ds*)&tmp;
> >>
> >> Space before &tmp.
> >
> > Added.
> >
> >>
> >>> +      restore = true;
> >>> +    }
> >>> +#endif
> >>> +
> >>>  #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
> >>> -  return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64,
> >>> -                           arg.array);
> >>> +  ret = INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64,
> >>> +                             arg.array);
> >>>  #else
> >>> -  return INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64,
> >>> -                           SEMCTL_ARG_ADDRESS (arg));
> >>> +  ret = INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64,
> >>> +                             SEMCTL_ARG_ADDRESS (arg));
> >>>  #endif
> >>
> >> Ok.
> >>
> >>> +
> >>> +#if IPC_TIME64
> >>> +  if (ret >= 0 && restore)
> >>> +    {
> >>> +      arg.buf = orig;
> >>> +      arg.buf->sem_perm  = tmp.sem_perm;
> >>> +      arg.buf->sem_otime = tmp.sem_otime
> >>> +                           | ((time_t) tmp.sem_otime_high << 32);
> >>> +      arg.buf->sem_ctime = tmp.sem_ctime
> >>> +                           | ((time_t) tmp.sem_ctime_high << 32);
> >>> +      arg.buf->sem_nsems = tmp.sem_nsems;
> >>
> >> I think it would be better to use __time64_t explicit here.
> >
> > Done.
> >
> > Alistair
> >
> >>
> >>> +    }
> >>> +#endif
> >>> +
> >>> +    return ret;
> >>>  }
> >>>
> >>>  int
> >>> diff --git a/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h
> >>> new file mode 100644
> >>> index 0000000000..f641825d37
> >>> --- /dev/null
> >>> +++ b/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h
> >>> @@ -0,0 +1,32 @@
> >>> +/* Sparc implementation of the semaphore struct __semid_ds32.
> >>> +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
> >>> +   This file is part of the GNU C Library.
> >>> +
> >>> +   The GNU C Library is free software; you can redistribute it and/or
> >>> +   modify it under the terms of the GNU Lesser General Public
> >>> +   License as published by the Free Software Foundation; either
> >>> +   version 2.1 of the License, or (at your option) any later version.
> >>> +
> >>> +   The GNU C Library is distributed in the hope that it will be useful,
> >>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> >>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> >>> +   Lesser General Public License for more details.
> >>> +
> >>> +   You should have received a copy of the GNU Lesser General Public
> >>> +   License along with the GNU C Library; if not, see
> >>> +   <https://www.gnu.org/licenses/>.  */
> >>> +
> >>> +#if __WORDSIZE == 32
> >>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
> >>> +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
> >>> +struct __semid_ds32 {
> >>> +  struct ipc_perm sem_perm;              /* operation permission struct */
> >>> +  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
> >>> +  __syscall_ulong_t   sem_otime;         /* last semop() time */
> >>> +  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
> >>> +  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
> >>> +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
> >>> +  __syscall_ulong_t   __glibc_reserved3;
> >>> +  __syscall_ulong_t   __glibc_reserved4;
> >>> +};
> >>> +#endif
> >>
> >> Ok.
> >>
> >>> diff --git a/sysdeps/unix/sysv/linux/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/struct__semid_ds32.h
> >>> new file mode 100644
> >>> index 0000000000..51ff83206d
> >>> --- /dev/null
> >>> +++ b/sysdeps/unix/sysv/linux/struct__semid_ds32.h
> >>> @@ -0,0 +1,32 @@
> >>> +/* Generic implementation of the semaphore struct __semid_ds32.
> >>> +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
> >>> +   This file is part of the GNU C Library.
> >>> +
> >>> +   The GNU C Library is free software; you can redistribute it and/or
> >>> +   modify it under the terms of the GNU Lesser General Public
> >>> +   License as published by the Free Software Foundation; either
> >>> +   version 2.1 of the License, or (at your option) any later version.
> >>> +
> >>> +   The GNU C Library is distributed in the hope that it will be useful,
> >>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> >>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> >>> +   Lesser General Public License for more details.
> >>> +
> >>> +   You should have received a copy of the GNU Lesser General Public
> >>> +   License along with the GNU C Library; if not, see
> >>> +   <https://www.gnu.org/licenses/>.  */
> >>> +
> >>> +#if __WORDSIZE == 32
> >>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
> >>> +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
> >>> +struct __semid_ds32 {
> >>> +  struct ipc_perm sem_perm;              /* operation permission struct */
> >>> +  __syscall_ulong_t   sem_otime;         /* last semop() time */
> >>> +  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
> >>> +  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
> >>> +  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
> >>> +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
> >>> +  __syscall_ulong_t   __glibc_reserved3;
> >>> +  __syscall_ulong_t   __glibc_reserved4;
> >>> +};
> >>> +#endif
> >>
> >> Ok.
> >>
> >>> diff --git a/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h
> >>> new file mode 100644
> >>> index 0000000000..f65c9fc877
> >>> --- /dev/null
> >>> +++ b/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h
> >>> @@ -0,0 +1,32 @@
> >>> +/* x86 implementation of the semaphore struct __semid_ds32.
> >>> +   Copyright (C) 1995-2020 Free Software Foundation, Inc.
> >>> +   This file is part of the GNU C Library.
> >>> +
> >>> +   The GNU C Library is free software; you can redistribute it and/or
> >>> +   modify it under the terms of the GNU Lesser General Public
> >>> +   License as published by the Free Software Foundation; either
> >>> +   version 2.1 of the License, or (at your option) any later version.
> >>> +
> >>> +   The GNU C Library is distributed in the hope that it will be useful,
> >>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> >>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> >>> +   Lesser General Public License for more details.
> >>> +
> >>> +   You should have received a copy of the GNU Lesser General Public
> >>> +   License along with the GNU C Library; if not, see
> >>> +   <https://www.gnu.org/licenses/>.  */
> >>> +
> >>> +#ifdef __i386__
> >>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
> >>> +   the kernel to use {o,c}time{_high} values to support a 64-bit time_t.  */
> >>> +struct __semid_ds32 {
> >>> +  struct ipc_perm sem_perm;              /* operation permission struct */
> >>> +  __syscall_ulong_t   sem_otime;         /* last semop() time */
> >>> +  __syscall_ulong_t   sem_otime_high;    /* last semop() time high */
> >>> +  __syscall_ulong_t   sem_ctime;         /* last time changed by semctl() */
> >>> +  __syscall_ulong_t   sem_ctime_high;    /* last time changed by semctl() high */
> >>> +  __syscall_ulong_t   sem_nsems;         /* number of semaphores in set */
> >>> +  __syscall_ulong_t   __glibc_reserved3;
> >>> +  __syscall_ulong_t   __glibc_reserved4;
> >>> +};
> >>> +#endif
> >>>
> >>
> >> Ok.
> >>
> >>

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2020-04-30 21:33 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-28 22:05 [PATCH v6 0/3] Support y2038 semctl_syscall() Alistair Francis
2020-04-28 22:05 ` [PATCH v6 1/3] bits/sem.h: Split out struct semid_ds Alistair Francis
2020-04-28 22:05 ` [PATCH v6 2/3] semctl: Remove the sem-pad.h file Alistair Francis
2020-04-28 22:05 ` [PATCH v6 3/3] sysv: linux: Pass 64-bit version of semctl syscall Alistair Francis
2020-04-29 21:09   ` Adhemerval Zanella
2020-04-29 23:24     ` Alistair Francis
2020-04-30 15:06       ` Adhemerval Zanella
2020-04-30 21:25         ` Alistair Francis

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).