public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 1/7] sysv: linux: Add 64-bit time_t variant for semctl
@ 2020-06-30 19:24 Adhemerval Zanella
  2020-06-30 19:24 ` [PATCH 2/7] sysvipc: Split out linux struct semid_ds Adhemerval Zanella
                   ` (7 more replies)
  0 siblings, 8 replies; 41+ messages in thread
From: Adhemerval Zanella @ 2020-06-30 19:24 UTC (permalink / raw)
  To: libc-alpha; +Cc: stepan, Alistair Francis

Different than others 64-bit time_t syscalls, the SysIPC interface
does not provide a new set of syscall for y2038 safeness.  Instead it
uses ununsed fields in semid_ds structure the return the high bits for
the timestamps.

To provide a y2038 safe interface a new symbol __semctl64 is added
and __semctl is change to call it instead (it adds some extra buffer
copy for the 32 bit time_t implementation).

Two two new structures are added:

  1. kernel_semid64_ds: used internally only on 32-bit architectures
     to issue the syscall.  A handful architectures (hppa, i386, mips,
     powerpc32, sparc32) requires specific implementation due its
     specific kernel ABI.

  2. semid_ds64: this is only for __TIMESIZE != 64 to use along with
     the 64-bit semctl.  It is different than the kernel one because
     the exported 64-bit time_t might require different alignment
     depending of the architecture ABI.

So the resulting implementation does:

  1. For 64-bit architectures it assumes semid_ds already contains
     64-bit time_t fields it will result in just the __semctl symbol
     using the __semctl64 code.  The semid_ds argument is passed as-is
     to the syscall.

  2. For 32-bit architectures with default 64-bit time_t (newer ABIs
     such riscv32 or arc), it will also result in only one exported
     symbol but with the required high/low handling.

     It might be possible to optimize it further to avoid the
     kernel_semid64_ds to semun transformation if the exported ABI
     for the architectures matches the expected kernel ABI, but the
     implementation is already complex enough and don't think this
     should be a hotspot in any case.

  3. Finally for 32-bit architecture with both 32-bit and 64-bit time_t
     support we follow the already set way to provide one symbol with
     64-bit time_t support and implement the 32-bit time_t support on
     basis of the 64-bit one.

     The default 32-bit symbol will allocate and copy the semid_ds
     over multiple buffers, but this should be deprecated in favor
     of the __semctl64 anyway.

Checked on i686-linux-gnu and x86_64-linux-gnu.  I also did some sniff
tests on powerpc, powerpc64, mips, mips64, armhf, sparcv9, and
sparc64.
---
 include/sys/sem.h                             |   7 +
 .../sysv/linux/bits/types/struct_semid64_ds.h |  33 +++
 .../sysv/linux/bits/types/struct_semid_ds.h   |  21 +-
 .../linux/hppa/bits/types/struct_semid_ds.h   |   6 +-
 .../linux/hppa/struct_kernel_semid64_ds.h     |  12 +
 .../linux/i386/struct_kernel_semid64_ds.h     |  12 +
 sysdeps/unix/sysv/linux/ipc_priv.h            |  10 +
 .../linux/mips/bits/types/struct_semid_ds.h   |   4 +-
 .../linux/mips/struct_kernel_semid64_ds.h     |  10 +
 .../powerpc/bits/types/struct_semid_ds.h      |   4 +-
 .../powerpc32/struct_kernel_semid64_ds.h      |  12 +
 sysdeps/unix/sysv/linux/semctl.c              | 261 +++++++++++++++---
 .../linux/sparc/bits/types/struct_semid_ds.h  |   4 +-
 .../sparc/sparc32/struct_kernel_semid64_ds.h  |  12 +
 .../sysv/linux/struct_kernel_semid64_ds.h     |  12 +
 .../linux/x86/bits/types/struct_semid_ds.h    |   4 +-
 16 files changed, 359 insertions(+), 65 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_semid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/hppa/struct_kernel_semid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/i386/struct_kernel_semid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/mips/struct_kernel_semid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_semid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_semid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/struct_kernel_semid64_ds.h

diff --git a/include/sys/sem.h b/include/sys/sem.h
index 69fdf1f752..a9151e057d 100644
--- a/include/sys/sem.h
+++ b/include/sys/sem.h
@@ -5,5 +5,12 @@
 
 __typeof__ (semtimedop) __semtimedop attribute_hidden;
 
+#if __TIMESIZE == 64
+# define __semctl64 __semctl
+#else
+extern int __semctl64 (int semid, int semnum, int cmd, ...);
+libc_hidden_proto (__semctl64);
+#endif
+
 # endif
 #endif
diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_semid64_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_semid64_ds.h
new file mode 100644
index 0000000000..bda9eb4469
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/bits/types/struct_semid64_ds.h
@@ -0,0 +1,33 @@
+/* Generic implementation of the semaphore struct semid64_ds.
+   Copyright (C) 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 __TIMESIZE == 64
+# define __semid64_ds semid_ds
+#else
+struct __semid64_ds
+{
+  struct ipc_perm sem_perm;		/* operation permission struct */
+  __time64_t sem_otime;			/* last semop() time */
+  __time64_t sem_ctime;			/* last time changed by semctl() */
+  __syscall_ulong_t sem_nsems;		/* number of semaphores in set */
+};
+#endif
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 4222e6a59f..bc26d8be08 100644
--- a/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h
+++ b/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h
@@ -21,26 +21,19 @@
 #endif
 
 /* Data structure describing a set of semaphores.  */
-#if __TIMESIZE == 32
 struct semid_ds
 {
   struct ipc_perm sem_perm;        /* operation permission struct */
+#if __TIMESIZE == 32
   __time_t sem_otime;              /* last semop() time */
-  __syscall_ulong_t __glibc_reserved1;
+  __syscall_ulong_t __sem_otime_high;
   __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;
-};
+  __syscall_ulong_t __sem_ctime_high;
 #else
-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 */
+  __time_t sem_otime;
+  __time_t sem_ctime;
+#endif
+  __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/hppa/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_semid_ds.h
index d4c50b5ef8..68f9eca24c 100644
--- a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_semid_ds.h
+++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_semid_ds.h
@@ -21,16 +21,14 @@
 #endif
 
 /* 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;
+  __syscall_ulong_t __sem_otime_high;
   __time_t sem_otime;         /* last semop() time */
-  __syscall_ulong_t __glibc_reserved2;
+  __syscall_ulong_t __sem_ctime_high;
   __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/hppa/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/hppa/struct_kernel_semid64_ds.h
new file mode 100644
index 0000000000..2871030d0d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/hppa/struct_kernel_semid64_ds.h
@@ -0,0 +1,12 @@
+/* Analogous to kernel struct semid64_ds used on semctl.  */
+struct kernel_semid64_ds
+{
+  struct ipc_perm sem_perm;
+  unsigned long sem_otime_high;
+  unsigned long sem_otime;
+  unsigned long sem_ctime_high;
+  unsigned long sem_ctime;
+  unsigned long sem_nsems;
+  unsigned long __ununsed1;
+  unsigned long __ununsed2;
+};
diff --git a/sysdeps/unix/sysv/linux/i386/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/i386/struct_kernel_semid64_ds.h
new file mode 100644
index 0000000000..bab9cf63ba
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/struct_kernel_semid64_ds.h
@@ -0,0 +1,12 @@
+/* Analogous to kernel struct semid64_ds used on semctl.  */
+struct kernel_semid64_ds
+{
+  struct ipc_perm sem_perm;
+  unsigned long sem_otime;
+  unsigned long sem_otime_high;
+  unsigned long sem_ctime;
+  unsigned long sem_ctime_high;
+  __syscall_ulong_t sem_nsems;
+  __syscall_ulong_t __unused3;
+  __syscall_ulong_t __unused4;
+};
diff --git a/sysdeps/unix/sysv/linux/ipc_priv.h b/sysdeps/unix/sysv/linux/ipc_priv.h
index 15a6e683a4..93a6e5cb24 100644
--- a/sysdeps/unix/sysv/linux/ipc_priv.h
+++ b/sysdeps/unix/sysv/linux/ipc_priv.h
@@ -53,4 +53,14 @@ struct __old_ipc_perm
 #define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
   (__nsops), 0, (__sops), (__timeout)
 
+/* Linux SysV ipc does not provide new syscalls for 64-bit time support on
+   32-bit architectures, but rather split the timestamps on previous unused
+   fields.  */
+#if (__WORDSIZE == 32 \
+     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
+# define __IPC_TIME64 1
+#else
+# define __IPC_TIME64 0
+#endif
+
 #include <ipc_ops.h>
diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h
index 8954209a29..eec4a18cae 100644
--- a/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h
+++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h
@@ -27,6 +27,6 @@ struct semid_ds
   __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;
+  __syscall_ulong_t __sem_otime_high;
+  __syscall_ulong_t __sem_ctime_high;
 };
diff --git a/sysdeps/unix/sysv/linux/mips/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/mips/struct_kernel_semid64_ds.h
new file mode 100644
index 0000000000..76a9d83ea5
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/struct_kernel_semid64_ds.h
@@ -0,0 +1,10 @@
+/* Analogous to kernel struct semid64_ds used on semctl.  */
+struct kernel_semid64_ds
+{
+  struct ipc_perm sem_perm;
+  unsigned long sem_otime;
+  unsigned long sem_ctime;
+  unsigned long sem_nsems;
+  unsigned long sem_otime_high;
+  unsigned long sem_ctime_high;
+};
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
index 300a9b98e9..d382d93c52 100644
--- a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_semid_ds.h
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_semid_ds.h
@@ -25,9 +25,9 @@ struct semid_ds
 {
   struct ipc_perm sem_perm;   /* operation permission struct */
 #if __TIMESIZE == 32
-  __syscall_ulong_t __glibc_reserved1;
+  __syscall_ulong_t __sem_otime_high;
   __time_t sem_otime;         /* last semop() time */
-  __syscall_ulong_t __glibc_reserved2;
+  __syscall_ulong_t __sem_ctime_high;
   __time_t sem_ctime;        /* last time changed by semctl() */
 #else
   __time_t sem_otime;         /* last semop() time */
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_semid64_ds.h
new file mode 100644
index 0000000000..7fa4ef6424
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_semid64_ds.h
@@ -0,0 +1,12 @@
+/* Analogous to kernel struct semid64_ds used on semctl.  */
+struct kernel_semid64_ds
+{
+  struct ipc_perm sem_perm;
+  unsigned long sem_otime_high;
+  unsigned long sem_otime;
+  unsigned long sem_ctime_high;
+  unsigned long sem_ctime;
+  unsigned long sem_nsems;
+  unsigned long __unused3;
+  unsigned long __unused4;
+};
diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c
index 30571af49f..3a06270242 100644
--- a/sysdeps/unix/sysv/linux/semctl.c
+++ b/sysdeps/unix/sysv/linux/semctl.c
@@ -21,10 +21,13 @@
 #include <ipc_priv.h>
 #include <sysdep.h>
 #include <shlib-compat.h>
-#include <errno.h>
-#include <linux/posix_types.h>  /* For __kernel_mode_t.  */
+#include <bits/types/struct_semid64_ds.h>  /* For __semid64_ds.  */
+#include <linux/posix_types.h>             /* For __kernel_mode_t.  */
 
-/* Define a `union semun' suitable for Linux here.  */
+/* The struct used to issue the syscall.  For architecture that assume
+   64-bit time as default (!__ASSUME_TIME64_SYSCALLS) the syscall will
+   split the resulting 64-bit sem_{o,c}time in two fields (__sem_{o,c}time
+   and __sem_{o,c}time_hi).  */
 union semun
 {
   int val;			/* value for SETVAL */
@@ -33,16 +36,89 @@ union semun
   struct seminfo *__buf;	/* buffer for IPC_INFO */
 };
 
-#ifndef DEFAULT_VERSION
-# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
-#  define DEFAULT_VERSION GLIBC_2_2
+#if __IPC_TIME64 == 0
+# define semun64 semun
+typedef union semun semctl_arg_t;
+#else
+# include <struct_kernel_semid64_ds.h>
+
+union ksemun64
+{
+  int val;
+  struct kernel_semid64_ds *buf;
+  unsigned short int *array;
+  struct seminfo *__buf;
+};
+
+# if __TIMESIZE == 64
+#  define semun64 semun
 # else
-#  define DEFAULT_VERSION GLIBC_2_31
+/* The struct used when __semctl64 is called.  */
+union semun64
+{
+  int val;
+  struct __semid64_ds *buf;
+  unsigned short int *array;
+  struct seminfo *__buf;
+};
 # endif
+
+static void
+semid64_to_ksemid64 (const struct __semid64_ds *semid64,
+		     struct kernel_semid64_ds *ksemid)
+{
+  ksemid->sem_perm       = semid64->sem_perm;
+  ksemid->sem_otime      = semid64->sem_otime;
+  ksemid->sem_otime_high = semid64->sem_otime >> 32;
+  ksemid->sem_ctime      = semid64->sem_ctime;
+  ksemid->sem_ctime_high = semid64->sem_ctime >> 32;
+  ksemid->sem_nsems      = semid64->sem_nsems;
+}
+
+static void
+ksemid64_to_semid64 (const struct kernel_semid64_ds *ksemid,
+		     struct __semid64_ds *semid64)
+{
+  semid64->sem_perm  = ksemid->sem_perm;
+  semid64->sem_otime = ksemid->sem_otime
+		       | ((__time64_t) ksemid->sem_otime_high << 32);
+  semid64->sem_ctime = ksemid->sem_ctime
+		       | ((__time64_t) ksemid->sem_ctime_high << 32);
+  semid64->sem_nsems = ksemid->sem_nsems;
+}
+
+static union ksemun64
+semun64_to_ksemun64 (int cmd, union semun64 semun64,
+		     struct kernel_semid64_ds *buf)
+{
+  union ksemun64 r = { 0 };
+  switch (cmd)
+    {
+    case SETVAL:
+      r.val = semun64.val;
+      break;
+    case GETALL:
+    case SETALL:
+      r.array = semun64.array;
+      break;
+    case IPC_STAT:
+    case IPC_SET:
+      r.buf = buf;
+      semid64_to_ksemid64 (semun64.buf, r.buf);
+      break;
+    case IPC_INFO:
+    case SEM_INFO:
+      r.__buf = semun64.__buf;
+      break;
+    }
+  return r;
+}
+
+typedef union ksemun64 semctl_arg_t;
 #endif
 
 static int
-semctl_syscall (int semid, int semnum, int cmd, union semun arg)
+semctl_syscall (int semid, int semnum, int cmd, semctl_arg_t arg)
 {
 #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
   return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64,
@@ -53,15 +129,15 @@ semctl_syscall (int semid, int semnum, int cmd, union semun arg)
 #endif
 }
 
+/* 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)");
+
 int
-__new_semctl (int semid, int semnum, int cmd, ...)
+__semctl64 (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 };
+  union semun64 arg64 = { 0 };
   va_list ap;
 
   /* Get the argument only if required.  */
@@ -76,44 +152,151 @@ __new_semctl (int semid, int semnum, int cmd, ...)
     case IPC_INFO:      /* arg.__buf */
     case SEM_INFO:
       va_start (ap, cmd);
-      arg = va_arg (ap, union semun);
+      arg64 = va_arg (ap, union semun64);
       va_end (ap);
       break;
     }
 
-#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;
-    }
+#if __IPC_TIME64
+  struct kernel_semid64_ds ksemid;
+  union ksemun64 ksemun = semun64_to_ksemun64 (cmd, arg64, &ksemid);
+  union ksemun64 arg = ksemun;
+#else
+  union semun arg = arg64;
 #endif
 
   int ret = semctl_syscall (semid, semnum, cmd, arg);
+  if (ret < 0)
+    return ret;
 
-  if (ret >= 0)
+  switch (cmd)
     {
-      switch (cmd)
-	{
-        case IPC_STAT:
-        case SEM_STAT:
-        case SEM_STAT_ANY:
+    case IPC_STAT:
+    case SEM_STAT:
+    case SEM_STAT_ANY:
 #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
-          arg.buf->sem_perm.mode >>= 16;
+      arg.buf->sem_perm.mode >>= 16;
 #else
-	  /* Old Linux kernel versions might not clear the mode padding.  */
-	  if (sizeof ((struct semid_ds){0}.sem_perm.mode)
-	      != sizeof (__kernel_mode_t))
-	    arg.buf->sem_perm.mode &= 0xFFFF;
+      /* Old Linux kernel versions might not clear the mode padding.  */
+      if (sizeof ((struct semid_ds){0}.sem_perm.mode)
+	  != sizeof (__kernel_mode_t))
+	arg.buf->sem_perm.mode &= 0xFFFF;
 #endif
-	}
+
+#if __IPC_TIME64
+      ksemid64_to_semid64 (arg.buf, arg64.buf);
+#endif
+    }
+
+  return ret;
+}
+#if __TIMESIZE != 64
+libc_hidden_def (__semctl64)
+
+
+/* The 64-bit time_t semid_ds version might have a different layout and
+   internal field alignment.  */
+static void
+semid64_ds_to_semid_ds (struct semid_ds *ds, const struct __semid64_ds *ds64)
+{
+  ds->sem_perm = ds64->sem_perm;
+  ds->sem_otime = ds64->sem_otime;
+  ds->sem_ctime = ds64->sem_ctime;
+  ds->sem_nsems = ds64->sem_nsems;
+}
+
+static void
+semid_ds_to_semid64_ds (struct __semid64_ds *ds64, const struct semid_ds *ds)
+{
+  ds64->sem_perm = ds->sem_perm;
+  ds64->sem_otime = ds->sem_otime
+		    | ((__time64_t) ds->__sem_otime_high << 32);
+  ds64->sem_ctime = ds->sem_ctime
+		    | ((__time64_t) ds->__sem_ctime_high << 32);
+  ds64->sem_nsems = ds->sem_nsems;
+}
+
+static union semun64
+semun_to_semun64 (int cmd, union semun semun, struct __semid64_ds *semid64)
+{
+  union semun64 r = { 0 };
+  switch (cmd)
+    {
+    case SETVAL:
+      r.val = semun.val;
+      break;
+    case GETALL:
+    case SETALL:
+      r.array = semun.array;
+      break;
+    case IPC_STAT:
+    case IPC_SET:
+      r.buf = semid64;
+      semid_ds_to_semid64_ds (r.buf, semun.buf);
+# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
+      if (cmd == IPC_SET)
+	r.buf->sem_perm.mode *= 0x10000U;
+# endif
+      break;
+    case IPC_INFO:
+    case SEM_INFO:
+      r.__buf = semun.__buf;
+      break;
+    }
+  return r;
+}
+
+int
+__semctl (int semid, int semnum, int cmd, ...)
+{
+  union semun arg = { 0 };
+
+  va_list ap;
+
+  /* Get the argument only if required.  */
+  switch (cmd)
+    {
+    case SETVAL:        /* arg.val */
+    case GETALL:        /* arg.array */
+    case SETALL:
+    case IPC_STAT:      /* arg.buf */
+    case IPC_SET:
+    case SEM_STAT:
+    case IPC_INFO:      /* arg.__buf */
+    case SEM_INFO:
+      va_start (ap, cmd);
+      arg = va_arg (ap, union semun);
+      va_end (ap);
+      break;
+    }
+
+  struct __semid64_ds semid64;
+  union semun64 arg64 = semun_to_semun64 (cmd, arg, &semid64);
+
+  int ret = __semctl64 (semid, semnum, cmd, arg64);
+  if (ret < 0)
+    return ret;
+
+  switch (cmd)
+    {
+    case IPC_STAT:
+    case SEM_STAT:
+    case SEM_STAT_ANY:
+      semid64_ds_to_semid_ds (arg.buf, arg64.buf);
     }
 
   return ret;
 }
-versioned_symbol (libc, __new_semctl, semctl, DEFAULT_VERSION);
+#endif
+
+#ifndef DEFAULT_VERSION
+# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
+#  define DEFAULT_VERSION GLIBC_2_2
+# else
+#  define DEFAULT_VERSION GLIBC_2_31
+# endif
+#endif
+versioned_symbol (libc, __semctl, semctl, DEFAULT_VERSION);
 
 #if defined __ASSUME_SYSVIPC_BROKEN_MODE_T \
     && SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_31)
@@ -121,7 +304,7 @@ int
 attribute_compat_text_section
 __semctl_mode16 (int semid, int semnum, int cmd, ...)
 {
-  union semun arg = { 0 };
+  semctl_arg_t arg = { 0 };
   va_list ap;
 
   /* Get the argument only if required.  */
@@ -136,7 +319,7 @@ __semctl_mode16 (int semid, int semnum, int cmd, ...)
     case IPC_INFO:      /* arg.__buf */
     case SEM_INFO:
       va_start (ap, cmd);
-      arg = va_arg (ap, union semun);
+      arg = va_arg (ap, semctl_arg_t);
       va_end (ap);
       break;
     }
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
index 46fcd79fb6..0110c1a940 100644
--- a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_semid_ds.h
+++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_semid_ds.h
@@ -25,9 +25,9 @@ struct semid_ds
 {
   struct ipc_perm sem_perm;   /* operation permission struct */
 #if __TIMESIZE == 32
-  __syscall_ulong_t __glibc_reserved1;
+  __syscall_ulong_t __sem_otime_high;
   __time_t sem_otime;         /* last semop() time */
-  __syscall_ulong_t __glibc_reserved2;
+  __syscall_ulong_t __sem_ctime_high;
   __time_t sem_ctime;        /* last time changed by semctl() */
 #else
   __time_t sem_otime;         /* last semop() time */
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_semid64_ds.h
new file mode 100644
index 0000000000..8c4697f9ab
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_semid64_ds.h
@@ -0,0 +1,12 @@
+/* Analogous to kernel struct semid64_ds used on semctl.  */
+struct kernel_semid64_ds
+{
+  struct ipc_perm sem_perm;
+  unsigned long sem_otime_high;
+  unsigned long sem_otime;
+  unsigned long sem_ctime_high;
+  unsigned long sem_ctime;
+  unsigned long sem_nsems;
+  unsigned long __unused1;
+  unsigned long __unused2;
+};
diff --git a/sysdeps/unix/sysv/linux/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/struct_kernel_semid64_ds.h
new file mode 100644
index 0000000000..f9edf0f76f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/struct_kernel_semid64_ds.h
@@ -0,0 +1,12 @@
+/* Analogous to kernel struct semid64_ds used on semctl.  */
+struct kernel_semid64_ds
+{
+  struct ipc_perm sem_perm;
+  unsigned long sem_otime;
+  unsigned long sem_otime_high;
+  unsigned long sem_ctime;
+  unsigned long sem_ctime_high;
+  unsigned long sem_nsems;
+  unsigned long __unused1;
+  unsigned long __unused2;
+};
diff --git a/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h
index f7ec89d115..c3f2fde9fd 100644
--- a/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h
+++ b/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h
@@ -25,9 +25,9 @@ struct semid_ds
 {
   struct ipc_perm sem_perm;   /* operation permission struct */
   __time_t sem_otime;  /* last semop() time */
-  __syscall_ulong_t __glibc_reserved1;
+  __syscall_ulong_t __sem_otime_high;
   __time_t sem_ctime;  /* last time changed by semctl() */
-  __syscall_ulong_t __glibc_reserved2;
+  __syscall_ulong_t __sem_ctime_high;
   __syscall_ulong_t sem_nsems;    /* number of semaphores in set */
   __syscall_ulong_t __glibc_reserved3;
   __syscall_ulong_t __glibc_reserved4;
-- 
2.25.1


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

* [PATCH 2/7] sysvipc: Split out linux struct semid_ds
  2020-06-30 19:24 [PATCH 1/7] sysv: linux: Add 64-bit time_t variant for semctl Adhemerval Zanella
@ 2020-06-30 19:24 ` Adhemerval Zanella
  2020-07-02 21:20   ` Alistair Francis
  2020-07-07 19:01   ` Carlos O'Donell
  2020-06-30 19:24 ` [PATCH 3/7] sysvipc: Remove the linux msq-pad.h file Adhemerval Zanella
                   ` (6 subsequent siblings)
  7 siblings, 2 replies; 41+ messages in thread
From: Adhemerval Zanella @ 2020-06-30 19:24 UTC (permalink / raw)
  To: libc-alpha; +Cc: stepan, Alistair Francis

This will allow us to have architectures specify their own version.

Not semantic changes expected.  Checked with a build against the
all affected ABIs.
---
 sysdeps/unix/sysv/linux/Makefile              |  1 +
 sysdeps/unix/sysv/linux/bits/msq.h            | 39 +++-----------
 .../sysv/linux/bits/types/struct_msqid_ds.h   | 51 +++++++++++++++++++
 3 files changed, 58 insertions(+), 33 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h

diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index e02065dc8d..70e2d9e044 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -92,6 +92,7 @@ sysdep_headers += sys/mount.h sys/acct.h \
 		  bits/termios-c_lflag.h bits/termios-tcflow.h \
 		  bits/termios-misc.h \
 		  bits/types/struct_semid_ds.h \
+		  bits/types/struct_msqid_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/msq.h b/sysdeps/unix/sysv/linux/bits/msq.h
index cc4ebae0f0..6ce6408ebc 100644
--- a/sysdeps/unix/sysv/linux/bits/msq.h
+++ b/sysdeps/unix/sysv/linux/bits/msq.h
@@ -20,7 +20,12 @@
 #endif
 
 #include <bits/types.h>
-#include <bits/msq-pad.h>
+
+/* Types used in the MSQID_DS structure definition.  */
+typedef __syscall_ulong_t msgqnum_t;
+typedef __syscall_ulong_t msglen_t;
+
+#include <bits/types/struct_msqid_ds.h>
 
 /* Define options for message queue functions.  */
 #define MSG_NOERROR	010000	/* no error if message is too big */
@@ -29,38 +34,6 @@
 # define MSG_COPY	040000	/* copy (not remove) all queue messages */
 #endif
 
-/* Types used in the structure definition.  */
-typedef __syscall_ulong_t msgqnum_t;
-typedef __syscall_ulong_t msglen_t;
-
-#if __MSQ_PAD_BEFORE_TIME
-# define __MSQ_PAD_TIME(NAME, RES)				\
-  unsigned long int __glibc_reserved ## RES; __time_t NAME
-#elif __MSQ_PAD_AFTER_TIME
-# define __MSQ_PAD_TIME(NAME, RES)				\
-  __time_t NAME; unsigned long int __glibc_reserved ## RES
-#else
-# define __MSQ_PAD_TIME(NAME, RES)		\
-  __time_t NAME
-#endif
-
-/* Structure of record for one message inside the kernel.
-   The type `struct msg' is opaque.  */
-struct msqid_ds
-{
-  struct ipc_perm msg_perm;	/* structure describing operation permission */
-  __MSQ_PAD_TIME (msg_stime, 1);	/* time of last msgsnd command */
-  __MSQ_PAD_TIME (msg_rtime, 2);	/* time of last msgrcv command */
-  __MSQ_PAD_TIME (msg_ctime, 3);	/* time of last change */
-  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
-  msgqnum_t msg_qnum;		/* number of messages currently on queue */
-  msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
-  __pid_t msg_lspid;		/* pid of last msgsnd() */
-  __pid_t msg_lrpid;		/* pid of last msgrcv() */
-  __syscall_ulong_t __glibc_reserved4;
-  __syscall_ulong_t __glibc_reserved5;
-};
-
 #ifdef __USE_MISC
 
 # define msg_cbytes	__msg_cbytes
diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
new file mode 100644
index 0000000000..bfc56f6ac1
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
@@ -0,0 +1,51 @@
+/* Generic implementation of the SysV message struct msqid_ds.
+   Copyright (C) 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_MSG_H
+# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
+#endif
+
+#include <bits/msq-pad.h>
+
+#if __MSQ_PAD_BEFORE_TIME
+# define __MSQ_PAD_TIME(NAME, RES)				\
+  unsigned long int __glibc_reserved ## RES; __time_t NAME
+#elif __MSQ_PAD_AFTER_TIME
+# define __MSQ_PAD_TIME(NAME, RES)				\
+  __time_t NAME; unsigned long int __glibc_reserved ## RES
+#else
+# define __MSQ_PAD_TIME(NAME, RES)		\
+  __time_t NAME
+#endif
+
+/* Structure of record for one message inside the kernel.
+   The type `struct msg' is opaque.  */
+struct msqid_ds
+{
+  struct ipc_perm msg_perm;	/* structure describing operation permission */
+  __MSQ_PAD_TIME (msg_stime, 1);	/* time of last msgsnd command */
+  __MSQ_PAD_TIME (msg_rtime, 2);	/* time of last msgrcv command */
+  __MSQ_PAD_TIME (msg_ctime, 3);	/* time of last change */
+  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
+  msgqnum_t msg_qnum;		/* number of messages currently on queue */
+  msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
+  __pid_t msg_lspid;		/* pid of last msgsnd() */
+  __pid_t msg_lrpid;		/* pid of last msgrcv() */
+  __syscall_ulong_t __glibc_reserved4;
+  __syscall_ulong_t __glibc_reserved5;
+};
-- 
2.25.1


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

* [PATCH 3/7] sysvipc: Remove the linux msq-pad.h file
  2020-06-30 19:24 [PATCH 1/7] sysv: linux: Add 64-bit time_t variant for semctl Adhemerval Zanella
  2020-06-30 19:24 ` [PATCH 2/7] sysvipc: Split out linux struct semid_ds Adhemerval Zanella
@ 2020-06-30 19:24 ` Adhemerval Zanella
  2020-07-02 21:26   ` Alistair Francis
  2020-07-07 19:05   ` Carlos O'Donell
  2020-06-30 19:24 ` [PATCH 4/7] sysv: linux: Add 64-bit time_t variant for msgctl Adhemerval Zanella
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 41+ messages in thread
From: Adhemerval Zanella @ 2020-06-30 19:24 UTC (permalink / raw)
  To: libc-alpha; +Cc: stepan, Alistair Francis

Each architecture overrides the struct msqid_ds which its required
kernel ABI one.

Checked on x86_64-linux-gnu and some bases sysvipc tests on hppa,
mips, mipsle, mips64, mips64le, sparc64, sparcv9, powerpc64le,
powerpc64, and powerpc.
---
 sysdeps/unix/sysv/linux/Makefile              |  2 +-
 sysdeps/unix/sysv/linux/bits/msq-pad.h        | 31 ----------
 .../sysv/linux/bits/types/struct_msqid_ds.h   | 28 ++++------
 sysdeps/unix/sysv/linux/hppa/bits/msq-pad.h   | 26 ---------
 .../linux/hppa/bits/types/struct_msqid_ds.h   | 47 ++++++++++++++++
 sysdeps/unix/sysv/linux/mips/bits/msq-pad.h   | 31 ----------
 .../linux/mips/bits/types/struct_msqid_ds.h   | 56 +++++++++++++++++++
 .../unix/sysv/linux/powerpc/bits/msq-pad.h    | 26 ---------
 .../powerpc/bits/types/struct_msqid_ds.h      | 47 ++++++++++++++++
 sysdeps/unix/sysv/linux/sparc/bits/msq-pad.h  | 26 ---------
 .../linux/sparc/bits/types/struct_msqid_ds.h  | 47 ++++++++++++++++
 11 files changed, 210 insertions(+), 157 deletions(-)
 delete mode 100644 sysdeps/unix/sysv/linux/bits/msq-pad.h
 delete mode 100644 sysdeps/unix/sysv/linux/hppa/bits/msq-pad.h
 create mode 100644 sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
 delete mode 100644 sysdeps/unix/sysv/linux/mips/bits/msq-pad.h
 create mode 100644 sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
 delete mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/msq-pad.h
 create mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
 delete mode 100644 sysdeps/unix/sysv/linux/sparc/bits/msq-pad.h
 create mode 100644 sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h

diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index 70e2d9e044..505087e617 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -85,7 +85,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/shmlba.h bits/shm-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/msq-pad.h b/sysdeps/unix/sysv/linux/bits/msq-pad.h
deleted file mode 100644
index e4ffd39f27..0000000000
--- a/sysdeps/unix/sysv/linux/bits/msq-pad.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Define where padding goes in struct msqid_ds.  Generic 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_MSG_H
-# error "Never use <bits/msq-pad.h> directly; include <sys/msg.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.  */
-
-#define __MSQ_PAD_AFTER_TIME (__TIMESIZE == 32)
-#define __MSQ_PAD_BEFORE_TIME 0
diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
index bfc56f6ac1..32173a7b60 100644
--- a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
+++ b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
@@ -20,27 +20,23 @@
 # error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
 #endif
 
-#include <bits/msq-pad.h>
-
-#if __MSQ_PAD_BEFORE_TIME
-# define __MSQ_PAD_TIME(NAME, RES)				\
-  unsigned long int __glibc_reserved ## RES; __time_t NAME
-#elif __MSQ_PAD_AFTER_TIME
-# define __MSQ_PAD_TIME(NAME, RES)				\
-  __time_t NAME; unsigned long int __glibc_reserved ## RES
-#else
-# define __MSQ_PAD_TIME(NAME, RES)		\
-  __time_t NAME
-#endif
-
 /* Structure of record for one message inside the kernel.
    The type `struct msg' is opaque.  */
 struct msqid_ds
 {
   struct ipc_perm msg_perm;	/* structure describing operation permission */
-  __MSQ_PAD_TIME (msg_stime, 1);	/* time of last msgsnd command */
-  __MSQ_PAD_TIME (msg_rtime, 2);	/* time of last msgrcv command */
-  __MSQ_PAD_TIME (msg_ctime, 3);	/* time of last change */
+#if __TIMESIZE == 32
+  __time_t msg_stime;		/* time of last msgsnd command */
+  unsigned long int __glibc_reserved1;
+  __time_t msg_rtime;		/* time of last msgsnd command */
+  unsigned long int __glibc_reserved2;
+  __time_t msg_ctime;		/* time of last change */
+  unsigned long int __glibc_reserved3;
+#else
+  __time_t msg_stime;		/* time of last msgsnd command */
+  __time_t msg_rtime;		/* time of last msgsnd command */
+  __time_t msg_ctime;		/* time of last change */
+#endif
   __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
   msgqnum_t msg_qnum;		/* number of messages currently on queue */
   msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
diff --git a/sysdeps/unix/sysv/linux/hppa/bits/msq-pad.h b/sysdeps/unix/sysv/linux/hppa/bits/msq-pad.h
deleted file mode 100644
index 6986585ae7..0000000000
--- a/sysdeps/unix/sysv/linux/hppa/bits/msq-pad.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Define where padding goes in struct msqid_ds.  HPPA 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_MSG_H
-# error "Never use <bits/msq-pad.h> directly; include <sys/msg.h> instead."
-#endif
-
-#include <bits/timesize.h>
-
-#define __MSQ_PAD_AFTER_TIME 0
-#define __MSQ_PAD_BEFORE_TIME (__TIMESIZE == 32)
diff --git a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
new file mode 100644
index 0000000000..3cf70e36c4
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
@@ -0,0 +1,47 @@
+/* Linux/HPPA implementation of the SysV message struct msqid_ds.
+   Copyright (C) 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_MSG_H
+# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
+#endif
+
+/* Structure of record for one message inside the kernel.
+   The type `struct msg' is opaque.  */
+struct msqid_ds
+{
+  struct ipc_perm msg_perm;	/* structure describing operation permission */
+#if __TIMESIZE == 32
+  unsigned long int __glibc_reserved1;
+  __time_t msg_stime;		/* time of last msgsnd command */
+  unsigned long int __glibc_reserved2;
+  __time_t msg_rtime;		/* time of last msgsnd command */
+  unsigned long int __glibc_reserved3;
+  __time_t msg_ctime;		/* time of last change */
+#else
+  __time_t msg_stime;		/* time of last msgsnd command */
+  __time_t msg_rtime;		/* time of last msgsnd command */
+  __time_t msg_ctime;		/* time of last change */
+#endif
+  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
+  msgqnum_t msg_qnum;		/* number of messages currently on queue */
+  msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
+  __pid_t msg_lspid;		/* pid of last msgsnd() */
+  __pid_t msg_lrpid;		/* pid of last msgrcv() */
+  __syscall_ulong_t __glibc_reserved4;
+  __syscall_ulong_t __glibc_reserved5;
+};
diff --git a/sysdeps/unix/sysv/linux/mips/bits/msq-pad.h b/sysdeps/unix/sysv/linux/mips/bits/msq-pad.h
deleted file mode 100644
index 8e28c5abe1..0000000000
--- a/sysdeps/unix/sysv/linux/mips/bits/msq-pad.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Define where padding goes in struct msqid_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_MSG_H
-# error "Never use <bits/msq-pad.h> directly; include <sys/msg.h> instead."
-#endif
-
-#include <bits/timesize.h>
-
-#ifdef __MIPSEL__
-# define __MSQ_PAD_AFTER_TIME (__TIMESIZE == 32)
-# define __MSQ_PAD_BEFORE_TIME 0
-#else
-# define __MSQ_PAD_AFTER_TIME 0
-# define __MSQ_PAD_BEFORE_TIME (__TIMESIZE == 32)
-#endif
diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
new file mode 100644
index 0000000000..85fdeef274
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
@@ -0,0 +1,56 @@
+/* Linux/PowerPC implementation of the SysV message struct msqid_ds.
+   Copyright (C) 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_MSG_H
+# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
+#endif
+
+/* Structure of record for one message inside the kernel.
+   The type `struct msg' is opaque.  */
+struct msqid_ds
+{
+  struct ipc_perm msg_perm;	/* structure describing operation permission */
+#if __TIMESIZE == 32
+# ifdef __MIPSEL__
+  __time_t msg_stime;		/* time of last msgsnd command */
+  unsigned long int __glibc_reserved1;
+  __time_t msg_rtime;		/* time of last msgsnd command */
+  unsigned long int __glibc_reserved2;
+  __time_t msg_ctime;		/* time of last change */
+  unsigned long int __glibc_reserved3;
+# else
+  unsigned long int __glibc_reserved1;
+  __time_t msg_stime;		/* time of last msgsnd command */
+  unsigned long int __glibc_reserved2;
+  __time_t msg_rtime;		/* time of last msgsnd command */
+  unsigned long int __glibc_reserved3;
+  __time_t msg_ctime;		/* time of last change */
+# endif
+#else
+  __time_t msg_stime;		/* time of last msgsnd command */
+  __time_t msg_rtime;		/* time of last msgsnd command */
+  __time_t msg_ctime;		/* time of last change */
+#endif
+  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
+  msgqnum_t msg_qnum;		/* number of messages currently on queue */
+  msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
+  __pid_t msg_lspid;		/* pid of last msgsnd() */
+  __pid_t msg_lrpid;		/* pid of last msgrcv() */
+  __syscall_ulong_t __glibc_reserved4;
+  __syscall_ulong_t __glibc_reserved5;
+};
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/msq-pad.h b/sysdeps/unix/sysv/linux/powerpc/bits/msq-pad.h
deleted file mode 100644
index e2b9310800..0000000000
--- a/sysdeps/unix/sysv/linux/powerpc/bits/msq-pad.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Define where padding goes in struct msqid_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_MSG_H
-# error "Never use <bits/msq-pad.h> directly; include <sys/msg.h> instead."
-#endif
-
-#include <bits/timesize.h>
-
-#define __MSQ_PAD_AFTER_TIME 0
-#define __MSQ_PAD_BEFORE_TIME (__TIMESIZE == 32)
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
new file mode 100644
index 0000000000..4ae2fbcbdc
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
@@ -0,0 +1,47 @@
+/* Linux/PowerPC implementation of the SysV message struct msqid_ds.
+   Copyright (C) 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_MSG_H
+# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
+#endif
+
+/* Structure of record for one message inside the kernel.
+   The type `struct msg' is opaque.  */
+struct msqid_ds
+{
+  struct ipc_perm msg_perm;	/* structure describing operation permission */
+#if __TIMESIZE == 32
+  unsigned long int __glibc_reserved1;
+  __time_t msg_stime;		/* time of last msgsnd command */
+  unsigned long int __glibc_reserved2;
+  __time_t msg_rtime;		/* time of last msgsnd command */
+  unsigned long int __glibc_reserved3;
+  __time_t msg_ctime;		/* time of last change */
+#else
+  __time_t msg_stime;		/* time of last msgsnd command */
+  __time_t msg_rtime;		/* time of last msgsnd command */
+  __time_t msg_ctime;		/* time of last change */
+#endif
+  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
+  msgqnum_t msg_qnum;		/* number of messages currently on queue */
+  msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
+  __pid_t msg_lspid;		/* pid of last msgsnd() */
+  __pid_t msg_lrpid;		/* pid of last msgrcv() */
+  __syscall_ulong_t __glibc_reserved4;
+  __syscall_ulong_t __glibc_reserved5;
+};
diff --git a/sysdeps/unix/sysv/linux/sparc/bits/msq-pad.h b/sysdeps/unix/sysv/linux/sparc/bits/msq-pad.h
deleted file mode 100644
index 99fdf8c8f0..0000000000
--- a/sysdeps/unix/sysv/linux/sparc/bits/msq-pad.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Define where padding goes in struct msqid_ds.  SPARC 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_MSG_H
-# error "Never use <bits/msq-pad.h> directly; include <sys/msg.h> instead."
-#endif
-
-#include <bits/timesize.h>
-
-#define __MSQ_PAD_AFTER_TIME 0
-#define __MSQ_PAD_BEFORE_TIME (__TIMESIZE == 32)
diff --git a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
new file mode 100644
index 0000000000..71980839c7
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
@@ -0,0 +1,47 @@
+/* Linux/SPARC implementation of the SysV message struct msqid_ds.
+   Copyright (C) 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_MSG_H
+# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
+#endif
+
+/* Structure of record for one message inside the kernel.
+   The type `struct msg' is opaque.  */
+struct msqid_ds
+{
+  struct ipc_perm msg_perm;	/* structure describing operation permission */
+#if __TIMESIZE == 32
+  unsigned long int __glibc_reserved1;
+  __time_t msg_stime;		/* time of last msgsnd command */
+  unsigned long int __glibc_reserved2;
+  __time_t msg_rtime;		/* time of last msgsnd command */
+  unsigned long int __glibc_reserved3;
+  __time_t msg_ctime;		/* time of last change */
+#else
+  __time_t msg_stime;		/* time of last msgsnd command */
+  __time_t msg_rtime;		/* time of last msgsnd command */
+  __time_t msg_ctime;		/* time of last change */
+#endif
+  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
+  msgqnum_t msg_qnum;		/* number of messages currently on queue */
+  msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
+  __pid_t msg_lspid;		/* pid of last msgsnd() */
+  __pid_t msg_lrpid;		/* pid of last msgrcv() */
+  __syscall_ulong_t __glibc_reserved4;
+  __syscall_ulong_t __glibc_reserved5;
+};
-- 
2.25.1


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

* [PATCH 4/7] sysv: linux: Add 64-bit time_t variant for msgctl
  2020-06-30 19:24 [PATCH 1/7] sysv: linux: Add 64-bit time_t variant for semctl Adhemerval Zanella
  2020-06-30 19:24 ` [PATCH 2/7] sysvipc: Split out linux struct semid_ds Adhemerval Zanella
  2020-06-30 19:24 ` [PATCH 3/7] sysvipc: Remove the linux msq-pad.h file Adhemerval Zanella
@ 2020-06-30 19:24 ` Adhemerval Zanella
  2020-07-02 21:39   ` Alistair Francis
  2020-07-07 19:51   ` Carlos O'Donell
  2020-06-30 19:24 ` [PATCH 5/7] sysvipc: Split out linux struct shmid_ds Adhemerval Zanella
                   ` (4 subsequent siblings)
  7 siblings, 2 replies; 41+ messages in thread
From: Adhemerval Zanella @ 2020-06-30 19:24 UTC (permalink / raw)
  To: libc-alpha; +Cc: stepan, Alistair Francis

To provide a y2038 safe interface a new symbol __msgctl64 is added
and __msgctl is change to call it instead (it adds some extra buffer
copy for the 32 bit time_t implementation).

Two two new structures are added:

  1. kernel_msqid64_ds: used internally only on 32-bit architectures
     to issue the syscall.  A handful architectures (hppa, i386, mips,
     powerpc32, and sparc32) requires specific implementation due its
     specific kernel ABI.

  2. msqid_ds64: this is only for __TIMESIZE != 64 to use along with
     the 64-bit semctl.  It is different than the kernel one because
     the exported 64-bit time_t might require different alignment
     depending of the architecture ABI.

So the resulting implementation does:

  1. For 64-bit architectures it assumes msqid_ds already contains
     64-bit time_t fields it will result in just the __msgctl symbol
     using the __msgctl64 code.  The msgid_ds argument is passed as-is
     to the syscall.

  2. For 32-bit architectures with default 64-bit time_t (newer ABIs
     such riscv32 or arc), it will also result in only one exported
     symbol but with the required high/low time handling.

  3. Finally for 32-bit architecture with both 32-bit and 64-bit time_t
     support we follow the already set way to provide one symbol with
     64-bit time_t support and implement the 32-bit time_t support on
     basis of the 64-bit one.

     The default 32-bit symbol will allocate and copy the msqid_ds
     over multiple buffers, but this should be deprecated in favor
     of the __msgctl64 anyway.

Checked on i686-linux-gnu and x86_64-linux-gnu.  I also did some sniff
tests on powerpc, powerpc64, mips, mips64, armhf, sparcv9, and
sparc64.
---
 include/sys/msg.h                             |  10 +
 .../sysv/linux/bits/types/struct_msqid64_ds.h |  38 ++++
 .../sysv/linux/bits/types/struct_msqid_ds.h   |   6 +-
 .../linux/hppa/bits/types/struct_msqid_ds.h   |   6 +-
 .../linux/hppa/struct_kernel_msqid64_ds.h     |  18 ++
 .../linux/i386/struct_kernel_msqid64_ds.h     |  18 ++
 .../linux/mips/bits/types/struct_msqid_ds.h   |  12 +-
 .../linux/mips/struct_kernel_msqid64_ds.h     |  33 ++++
 sysdeps/unix/sysv/linux/msgctl.c              | 179 ++++++++++++++----
 .../powerpc/bits/types/struct_msqid_ds.h      |   6 +-
 .../powerpc32/struct_kernel_msqid64_ds.h      |  18 ++
 sysdeps/unix/sysv/linux/semctl.c              |  27 +--
 .../linux/sparc/bits/types/struct_msqid_ds.h  |   6 +-
 .../sparc/sparc32/struct_kernel_msqid64_ds.h  |  18 ++
 .../sysv/linux/struct_kernel_msqid64_ds.h     |  19 ++
 15 files changed, 350 insertions(+), 64 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h

diff --git a/include/sys/msg.h b/include/sys/msg.h
index 43ec5b9472..522903f818 100644
--- a/include/sys/msg.h
+++ b/include/sys/msg.h
@@ -6,6 +6,16 @@ extern ssize_t __libc_msgrcv (int msqid, void *msgp, size_t msgsz,
 			      long int msgtyp, int msgflg);
 extern int __libc_msgsnd (int msqid, const void *msgp, size_t msgsz,
 			  int msgflg);
+
+# include <bits/types/struct_msqid64_ds.h>
+
+# if __TIMESIZE == 64
+#  define __msgctl64 __msgctl
+# else
+extern int __msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf);
+libc_hidden_proto (__msgctl64);
+# endif
+
 #endif
 
 #endif
diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h
new file mode 100644
index 0000000000..3536c8ea62
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h
@@ -0,0 +1,38 @@
+/* Generic implementation of the SysV message struct msqid64_ds.
+   Copyright (C) 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_MSG_H
+# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
+#endif
+
+#if __TIMESIZE == 64
+# define __msqid64_ds msqid_ds
+#else
+struct __msqid64_ds
+{
+  struct ipc_perm msg_perm;	/* structure describing operation permission */
+  __time64_t msg_stime;		/* time of last msgsnd command */
+  __time64_t msg_rtime;		/* time of last msgsnd command */
+  __time64_t msg_ctime;		/* time of last change */
+  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
+  msgqnum_t msg_qnum;		/* number of messages currently on queue */
+  msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
+  __pid_t msg_lspid;		/* pid of last msgsnd() */
+  __pid_t msg_lrpid;		/* pid of last msgrcv() */
+};
+#endif
diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
index 32173a7b60..43b38175ad 100644
--- a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
+++ b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
@@ -27,11 +27,11 @@ struct msqid_ds
   struct ipc_perm msg_perm;	/* structure describing operation permission */
 #if __TIMESIZE == 32
   __time_t msg_stime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved1;
+  unsigned long int __msg_stime_high;
   __time_t msg_rtime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved2;
+  unsigned long int __msg_rtime_high;
   __time_t msg_ctime;		/* time of last change */
-  unsigned long int __glibc_reserved3;
+  unsigned long int __msg_ctime_high;
 #else
   __time_t msg_stime;		/* time of last msgsnd command */
   __time_t msg_rtime;		/* time of last msgsnd command */
diff --git a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
index 3cf70e36c4..16eac46941 100644
--- a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
+++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
@@ -26,11 +26,11 @@ struct msqid_ds
 {
   struct ipc_perm msg_perm;	/* structure describing operation permission */
 #if __TIMESIZE == 32
-  unsigned long int __glibc_reserved1;
+  unsigned long int __msg_stime_high;
   __time_t msg_stime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved2;
+  unsigned long int __msg_rtime_high;
   __time_t msg_rtime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved3;
+  unsigned long int __msg_ctime_high;
   __time_t msg_ctime;		/* time of last change */
 #else
   __time_t msg_stime;		/* time of last msgsnd command */
diff --git a/sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h
new file mode 100644
index 0000000000..69a63ee27a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h
@@ -0,0 +1,18 @@
+/* Analogous to kernel struct msqid64_ds used on msgctl.  */
+struct kernel_msqid64_ds
+{
+  struct ipc_perm msg_perm;
+  unsigned long msg_stime_high;
+  unsigned long msg_stime;
+  unsigned long msg_rtime_high;
+  unsigned long msg_rtime;
+  unsigned long msg_ctime_high;
+  unsigned long msg_ctime;
+  unsigned long msg_cbytes;
+  unsigned long msg_qnum;
+  unsigned long msg_qbytes;
+  __pid_t msg_lspid;
+  __pid_t msg_lrpid;
+  unsigned long __unused1;
+  unsigned long __unused2;
+};
diff --git a/sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h
new file mode 100644
index 0000000000..65b940567b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h
@@ -0,0 +1,18 @@
+/* Analogous to kernel struct compat_msqid64_ds used on msgctl.  */
+struct kernel_msqid64_ds
+{
+  struct ipc_perm msg_perm;
+  unsigned long msg_stime;
+  unsigned long msg_stime_high;
+  unsigned long msg_rtime;
+  unsigned long msg_rtime_high;
+  unsigned long msg_ctime;
+  unsigned long msg_ctime_high;
+  unsigned long msg_cbytes;
+  unsigned long msg_qnum;
+  unsigned long msg_qbytes;
+  __pid_t msg_lspid;
+  __pid_t msg_lrpid;
+  unsigned long __unused1;
+  unsigned long __unused2;
+};
diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
index 85fdeef274..9ff010c763 100644
--- a/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
+++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
@@ -28,17 +28,17 @@ struct msqid_ds
 #if __TIMESIZE == 32
 # ifdef __MIPSEL__
   __time_t msg_stime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved1;
+  unsigned long int __msg_stime_high;
   __time_t msg_rtime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved2;
+  unsigned long int __msg_rtime_high;
   __time_t msg_ctime;		/* time of last change */
-  unsigned long int __glibc_reserved3;
+  unsigned long int __msg_ctime_high;
 # else
-  unsigned long int __glibc_reserved1;
+  unsigned long int __msg_stime_high;
   __time_t msg_stime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved2;
+  unsigned long int __msg_rtime_high;
   __time_t msg_rtime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved3;
+  unsigned long int __msg_ctime_high;
   __time_t msg_ctime;		/* time of last change */
 # endif
 #else
diff --git a/sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h
new file mode 100644
index 0000000000..9cfd5a0dfe
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h
@@ -0,0 +1,33 @@
+/* Analogous to kernel struct msqid64_ds used on msgctl.  */
+struct kernel_msqid64_ds
+{
+  struct ipc_perm msg_perm;
+#if __TIMESIZE == 32
+# ifdef __MIPSEL__
+  unsigned long int msg_stime;
+  unsigned long int msg_stime_high;
+  unsigned long int msg_rtime;
+  unsigned long int msg_rtime_high;
+  unsigned long int msg_ctime;
+  unsigned long int msg_ctime_high;
+# else
+  unsigned long int msg_stime_high;
+  unsigned long int msg_stime;
+  unsigned long int msg_rtime_high;
+  unsigned long int msg_rtime;
+  unsigned long int msg_ctime_high;
+  unsigned long int msg_ctime;
+# endif
+#else
+  unsigned long int msg_stime;
+  unsigned long int msg_rtime;
+  unsigned long int msg_ctime;
+#endif
+  unsigned long int msg_cbytes;
+  unsigned long int msg_qnum;
+  unsigned long int msg_qbytes;
+  __pid_t msg_lspid;
+  __pid_t msg_lrpid;
+  unsigned long int __unused1;
+  unsigned long int __unused2;
+};
diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c
index fd46aec1a0..a7f7651280 100644
--- a/sysdeps/unix/sysv/linux/msgctl.c
+++ b/sysdeps/unix/sysv/linux/msgctl.c
@@ -23,16 +23,55 @@
 #include <errno.h>
 #include <linux/posix_types.h>  /* For __kernel_mode_t.  */
 
-#ifndef DEFAULT_VERSION
-# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
-#  define DEFAULT_VERSION GLIBC_2_2
-# else
-#  define DEFAULT_VERSION GLIBC_2_31
-# endif
+/* POSIX states ipc_perm mode should have type of mode_t.  */
+_Static_assert (sizeof ((struct msqid_ds){0}.msg_perm.mode)
+		== sizeof (mode_t),
+		"sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");
+
+#if __IPC_TIME64 == 0
+typedef struct msqid_ds msgctl_arg_t;
+#else
+# include <struct_kernel_msqid64_ds.h>
+
+static void
+msqid64_to_kmsqid64 (const struct __msqid64_ds *msqid64,
+		     struct kernel_msqid64_ds *kmsqid)
+{
+  kmsqid->msg_perm       = msqid64->msg_perm;
+  kmsqid->msg_stime      = msqid64->msg_stime;
+  kmsqid->msg_stime_high = msqid64->msg_stime >> 32;
+  kmsqid->msg_rtime      = msqid64->msg_rtime;
+  kmsqid->msg_rtime_high = msqid64->msg_rtime >> 32;
+  kmsqid->msg_ctime      = msqid64->msg_ctime;
+  kmsqid->msg_ctime_high = msqid64->msg_ctime >> 32;
+  kmsqid->msg_qnum       = msqid64->msg_qnum;
+  kmsqid->msg_qbytes     = msqid64->msg_qbytes;
+  kmsqid->msg_lspid      = msqid64->msg_lspid;
+  kmsqid->msg_lrpid      = msqid64->msg_lrpid;
+}
+
+static void
+kmsqid64_to_msqid64 (const struct kernel_msqid64_ds *kmsqid,
+		     struct __msqid64_ds *msqid64)
+{
+  msqid64->msg_perm   = kmsqid->msg_perm;
+  msqid64->msg_stime  = kmsqid->msg_stime
+		        | ((__time64_t) kmsqid->msg_stime_high << 32);
+  msqid64->msg_rtime  = kmsqid->msg_rtime
+		        | ((__time64_t) kmsqid->msg_rtime_high << 32);
+  msqid64->msg_ctime  = kmsqid->msg_ctime
+		        | ((__time64_t) kmsqid->msg_ctime_high << 32);
+  msqid64->msg_qnum   = kmsqid->msg_qnum;
+  msqid64->msg_qbytes = kmsqid->msg_qbytes;
+  msqid64->msg_lspid  = kmsqid->msg_lspid;
+  msqid64->msg_lrpid  = kmsqid->msg_lrpid;
+}
+
+typedef struct kernel_msqid64_ds msgctl_arg_t;
 #endif
 
 static int
-msgctl_syscall (int msqid, int cmd, struct msqid_ds *buf)
+msgctl_syscall (int msqid, int cmd, msgctl_arg_t *buf)
 {
 #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
   return INLINE_SYSCALL_CALL (msgctl, msqid, cmd | __IPC_64, buf);
@@ -43,46 +82,118 @@ msgctl_syscall (int msqid, int cmd, struct msqid_ds *buf)
 }
 
 int
-__new_msgctl (int msqid, int cmd, struct msqid_ds *buf)
+__msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf)
 {
-  /* POSIX states ipc_perm mode should have type of mode_t.  */
-  _Static_assert (sizeof ((struct msqid_ds){0}.msg_perm.mode)
-		  == sizeof (mode_t),
-		  "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");
-
-#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
-  struct msqid_ds tmpds;
-  if (cmd == IPC_SET)
+#if __IPC_TIME64
+  struct kernel_msqid64_ds ksemid, *arg = NULL;
+  if (buf != NULL)
     {
-      tmpds = *buf;
-      tmpds.msg_perm.mode *= 0x10000U;
-      buf = &tmpds;
+      msqid64_to_kmsqid64 (buf, &ksemid);
+      arg = &ksemid;
     }
+# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
+  if (cmd == IPC_SET)
+    arg->msg_perm.mode *= 0x10000U;
+# endif
+#else
+  msgctl_arg_t *arg = buf;
 #endif
 
-  int ret = msgctl_syscall (msqid, cmd, buf);
+  int ret = msgctl_syscall (msqid, cmd, arg);
+  if (ret < 0)
+    return ret;
 
-  if (ret >= 0)
+  switch (cmd)
     {
-      switch (cmd)
-	{
-	case IPC_STAT:
-	case MSG_STAT:
-	case MSG_STAT_ANY:
+    case IPC_STAT:
+    case MSG_STAT:
+    case MSG_STAT_ANY:
 #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
-	  buf->msg_perm.mode >>= 16;
+      arg->msg_perm.mode >>= 16;
 #else
-	  /* Old Linux kernel versions might not clear the mode padding.  */
-	  if (sizeof ((struct msqid_ds){0}.msg_perm.mode)
-	      != sizeof (__kernel_mode_t))
-	    buf->msg_perm.mode &= 0xFFFF;
+      /* Old Linux kernel versions might not clear the mode padding.  */
+      if (sizeof ((struct msqid_ds){0}.msg_perm.mode)
+          != sizeof (__kernel_mode_t))
+	arg->msg_perm.mode &= 0xFFFF;
+#endif
+
+#if __IPC_TIME64
+      kmsqid64_to_msqid64 (arg, buf);
 #endif
-	}
     }
 
   return ret;
 }
-versioned_symbol (libc, __new_msgctl, msgctl, DEFAULT_VERSION);
+#if __TIMESIZE != 64
+libc_hidden_def (__msgctl64)
+
+static void
+msqid_to_msqid64 (struct __msqid64_ds *mq64, const struct msqid_ds *mq)
+{
+  mq64->msg_perm   = mq->msg_perm;
+  mq64->msg_stime  = mq->msg_stime
+		     | ((__time64_t) mq->__msg_stime_high << 32);
+  mq64->msg_rtime  = mq->msg_rtime
+		     | ((__time64_t) mq->__msg_rtime_high << 32);
+  mq64->msg_ctime  = mq->msg_ctime
+		     | ((__time64_t) mq->__msg_ctime_high << 32);
+  mq64->msg_qnum   = mq->msg_qnum;
+  mq64->msg_qbytes = mq->msg_qbytes;
+  mq64->msg_lspid  = mq->msg_lspid;
+  mq64->msg_lrpid  = mq->msg_lrpid;
+}
+
+static void
+msqid64_to_msqid (struct msqid_ds *mq, const struct __msqid64_ds *mq64)
+{
+  mq->msg_perm         = mq64->msg_perm;
+  mq->msg_stime        = mq64->msg_stime;
+  mq->__msg_stime_high = 0;
+  mq->msg_rtime        = mq64->msg_rtime;
+  mq->__msg_rtime_high = 0;
+  mq->msg_ctime        = mq64->msg_ctime;
+  mq->__msg_ctime_high = 0;
+  mq->msg_qnum         = mq64->msg_qnum;
+  mq->msg_qbytes       = mq64->msg_qbytes;
+  mq->msg_lspid        = mq64->msg_lspid;
+  mq->msg_lrpid        = mq64->msg_lrpid;
+}
+
+int
+__msgctl (int msqid, int cmd, struct msqid_ds *buf)
+{
+  struct __msqid64_ds msqid64, *buf64 = NULL;
+  if (buf != NULL)
+    {
+      msqid_to_msqid64 (&msqid64, buf);
+      buf64 = &msqid64;
+    }
+
+  int ret = __msgctl64 (msqid, cmd, buf64);
+  if (ret < 0)
+    return ret;
+
+  switch (cmd)
+    {
+    case IPC_STAT:
+    case MSG_STAT:
+    case MSG_STAT_ANY:
+      if (buf64 != NULL)
+        msqid64_to_msqid (buf, buf64);
+    }
+
+  return ret;
+}
+#endif
+
+#ifndef DEFAULT_VERSION
+# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
+#  define DEFAULT_VERSION GLIBC_2_2
+# else
+#  define DEFAULT_VERSION GLIBC_2_31
+# endif
+#endif
+versioned_symbol (libc, __msgctl, msgctl, DEFAULT_VERSION);
 
 #if defined __ASSUME_SYSVIPC_BROKEN_MODE_T \
     && SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_31)
@@ -90,7 +201,7 @@ int
 attribute_compat_text_section
 __msgctl_mode16 (int msqid, int cmd, struct msqid_ds *buf)
 {
-  return msgctl_syscall (msqid, cmd, buf);
+  return msgctl_syscall (msqid, cmd, (msgctl_arg_t *) buf);
 }
 compat_symbol (libc, __msgctl_mode16, msgctl, GLIBC_2_2);
 #endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
index 4ae2fbcbdc..35cc51f733 100644
--- a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
@@ -26,11 +26,11 @@ struct msqid_ds
 {
   struct ipc_perm msg_perm;	/* structure describing operation permission */
 #if __TIMESIZE == 32
-  unsigned long int __glibc_reserved1;
+  unsigned long int __msg_stime_high;
   __time_t msg_stime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved2;
+  unsigned long int __msg_rtime_high;
   __time_t msg_rtime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved3;
+  unsigned long int __msg_ctime_high;
   __time_t msg_ctime;		/* time of last change */
 #else
   __time_t msg_stime;		/* time of last msgsnd command */
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h
new file mode 100644
index 0000000000..69a63ee27a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h
@@ -0,0 +1,18 @@
+/* Analogous to kernel struct msqid64_ds used on msgctl.  */
+struct kernel_msqid64_ds
+{
+  struct ipc_perm msg_perm;
+  unsigned long msg_stime_high;
+  unsigned long msg_stime;
+  unsigned long msg_rtime_high;
+  unsigned long msg_rtime;
+  unsigned long msg_ctime_high;
+  unsigned long msg_ctime;
+  unsigned long msg_cbytes;
+  unsigned long msg_qnum;
+  unsigned long msg_qbytes;
+  __pid_t msg_lspid;
+  __pid_t msg_lrpid;
+  unsigned long __unused1;
+  unsigned long __unused2;
+};
diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c
index 3a06270242..7467d2566e 100644
--- a/sysdeps/unix/sysv/linux/semctl.c
+++ b/sysdeps/unix/sysv/linux/semctl.c
@@ -196,19 +196,11 @@ libc_hidden_def (__semctl64)
 
 /* The 64-bit time_t semid_ds version might have a different layout and
    internal field alignment.  */
-static void
-semid64_ds_to_semid_ds (struct semid_ds *ds, const struct __semid64_ds *ds64)
-{
-  ds->sem_perm = ds64->sem_perm;
-  ds->sem_otime = ds64->sem_otime;
-  ds->sem_ctime = ds64->sem_ctime;
-  ds->sem_nsems = ds64->sem_nsems;
-}
 
 static void
-semid_ds_to_semid64_ds (struct __semid64_ds *ds64, const struct semid_ds *ds)
+semid_to_semid64 (struct __semid64_ds *ds64, const struct semid_ds *ds)
 {
-  ds64->sem_perm = ds->sem_perm;
+  ds64->sem_perm  = ds->sem_perm;
   ds64->sem_otime = ds->sem_otime
 		    | ((__time64_t) ds->__sem_otime_high << 32);
   ds64->sem_ctime = ds->sem_ctime
@@ -216,6 +208,17 @@ semid_ds_to_semid64_ds (struct __semid64_ds *ds64, const struct semid_ds *ds)
   ds64->sem_nsems = ds->sem_nsems;
 }
 
+static void
+semid64_to_semid (struct semid_ds *ds, const struct __semid64_ds *ds64)
+{
+  ds->sem_perm         = ds64->sem_perm;
+  ds->sem_otime        = ds64->sem_otime;
+  ds->__sem_otime_high = 0;
+  ds->sem_ctime        = ds64->sem_ctime;
+  ds->__sem_ctime_high = 0;
+  ds->sem_nsems        = ds64->sem_nsems;
+}
+
 static union semun64
 semun_to_semun64 (int cmd, union semun semun, struct __semid64_ds *semid64)
 {
@@ -232,7 +235,7 @@ semun_to_semun64 (int cmd, union semun semun, struct __semid64_ds *semid64)
     case IPC_STAT:
     case IPC_SET:
       r.buf = semid64;
-      semid_ds_to_semid64_ds (r.buf, semun.buf);
+      semid_to_semid64 (r.buf, semun.buf);
 # ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
       if (cmd == IPC_SET)
 	r.buf->sem_perm.mode *= 0x10000U;
@@ -282,7 +285,7 @@ __semctl (int semid, int semnum, int cmd, ...)
     case IPC_STAT:
     case SEM_STAT:
     case SEM_STAT_ANY:
-      semid64_ds_to_semid_ds (arg.buf, arg64.buf);
+      semid64_to_semid (arg.buf, arg64.buf);
     }
 
   return ret;
diff --git a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
index 71980839c7..502c23d91e 100644
--- a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
+++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
@@ -26,11 +26,11 @@ struct msqid_ds
 {
   struct ipc_perm msg_perm;	/* structure describing operation permission */
 #if __TIMESIZE == 32
-  unsigned long int __glibc_reserved1;
+  unsigned long int __msg_stime_high;
   __time_t msg_stime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved2;
+  unsigned long int __msg_rtime_high;
   __time_t msg_rtime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved3;
+  unsigned long int __msg_ctime_high;
   __time_t msg_ctime;		/* time of last change */
 #else
   __time_t msg_stime;		/* time of last msgsnd command */
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h
new file mode 100644
index 0000000000..69a63ee27a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h
@@ -0,0 +1,18 @@
+/* Analogous to kernel struct msqid64_ds used on msgctl.  */
+struct kernel_msqid64_ds
+{
+  struct ipc_perm msg_perm;
+  unsigned long msg_stime_high;
+  unsigned long msg_stime;
+  unsigned long msg_rtime_high;
+  unsigned long msg_rtime;
+  unsigned long msg_ctime_high;
+  unsigned long msg_ctime;
+  unsigned long msg_cbytes;
+  unsigned long msg_qnum;
+  unsigned long msg_qbytes;
+  __pid_t msg_lspid;
+  __pid_t msg_lrpid;
+  unsigned long __unused1;
+  unsigned long __unused2;
+};
diff --git a/sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h
new file mode 100644
index 0000000000..a676e34a5a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h
@@ -0,0 +1,19 @@
+/* Analogous to kernel struct msqid64_ds used on msgctl.  It is only used
+   for 32-bit architectures on 64-bit time_t msgctl64 implementation.  */
+struct kernel_msqid64_ds
+{
+  struct ipc_perm msg_perm;
+  unsigned long int msg_stime;
+  unsigned long int msg_stime_high;
+  unsigned long int msg_rtime;
+  unsigned long int msg_rtime_high;
+  unsigned long int msg_ctime;
+  unsigned long int msg_ctime_high;
+  unsigned long int msg_cbytes;
+  unsigned long int msg_qnum;
+  unsigned long int  msg_qbytes;
+  __pid_t msg_lspid;
+  __pid_t msg_lrpid; 
+  unsigned long int __unused4;
+  unsigned long int __unused5;
+};
-- 
2.25.1


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

* [PATCH 5/7] sysvipc: Split out linux struct shmid_ds
  2020-06-30 19:24 [PATCH 1/7] sysv: linux: Add 64-bit time_t variant for semctl Adhemerval Zanella
                   ` (2 preceding siblings ...)
  2020-06-30 19:24 ` [PATCH 4/7] sysv: linux: Add 64-bit time_t variant for msgctl Adhemerval Zanella
@ 2020-06-30 19:24 ` Adhemerval Zanella
  2020-07-02 21:40   ` Alistair Francis
  2020-07-07 19:52   ` Carlos O'Donell
  2020-06-30 19:24 ` [PATCH 6/7] sysvipc: Remove the linux shm-pad.h file Adhemerval Zanella
                   ` (3 subsequent siblings)
  7 siblings, 2 replies; 41+ messages in thread
From: Adhemerval Zanella @ 2020-06-30 19:24 UTC (permalink / raw)
  To: libc-alpha; +Cc: stepan, Alistair Francis

This will allow us to have architectures specify their own version.

Not semantic changes expected.  Checked with a build against the
all affected ABIs.
---
 sysdeps/unix/sysv/linux/Makefile              |  1 +
 sysdeps/unix/sysv/linux/bits/shm.h            | 34 +----------
 .../sysv/linux/bits/types/struct_shmid_ds.h   | 57 +++++++++++++++++++
 3 files changed, 59 insertions(+), 33 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h

diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index 505087e617..bdd187af73 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -93,6 +93,7 @@ sysdep_headers += sys/mount.h sys/acct.h \
 		  bits/termios-misc.h \
 		  bits/types/struct_semid_ds.h \
 		  bits/types/struct_msqid_ds.h \
+		  bits/types/struct_shmid_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/shm.h b/sysdeps/unix/sysv/linux/bits/shm.h
index 113c05ee89..9ef6aeaf92 100644
--- a/sysdeps/unix/sysv/linux/bits/shm.h
+++ b/sysdeps/unix/sysv/linux/bits/shm.h
@@ -43,39 +43,7 @@ __BEGIN_DECLS
 /* Type to count number of attaches.  */
 typedef __syscall_ulong_t shmatt_t;
 
-#if __SHM_PAD_BEFORE_TIME
-# define __SHM_PAD_TIME(NAME, RES)				\
-  unsigned long int __glibc_reserved ## RES; __time_t NAME
-#elif __SHM_PAD_AFTER_TIME
-# define __SHM_PAD_TIME(NAME, RES)				\
-  __time_t NAME; unsigned long int __glibc_reserved ## RES
-#else
-# define __SHM_PAD_TIME(NAME, RES)		\
-  __time_t NAME
-#endif
-
-/* Data structure describing a shared memory segment.  */
-struct shmid_ds
-  {
-    struct ipc_perm shm_perm;		/* operation permission struct */
-#if !__SHM_SEGSZ_AFTER_TIME
-    size_t shm_segsz;			/* size of segment in bytes */
-#endif
-    __SHM_PAD_TIME (shm_atime, 1);	/* time of last shmat() */
-    __SHM_PAD_TIME (shm_dtime, 2);	/* time of last shmdt() */
-    __SHM_PAD_TIME (shm_ctime, 3);	/* time of last change by shmctl() */
-#if __SHM_PAD_BETWEEN_TIME_AND_SEGSZ
-    unsigned long int __glibc_reserved4;
-#endif
-#if __SHM_SEGSZ_AFTER_TIME
-    size_t shm_segsz;			/* size of segment in bytes */
-#endif
-    __pid_t shm_cpid;			/* pid of creator */
-    __pid_t shm_lpid;			/* pid of last shmop */
-    shmatt_t shm_nattch;		/* number of current attaches */
-    __syscall_ulong_t __glibc_reserved5;
-    __syscall_ulong_t __glibc_reserved6;
-  };
+#include <bits/types/struct_shmid_ds.h>
 
 #ifdef __USE_MISC
 
diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
new file mode 100644
index 0000000000..938bbedfcd
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
@@ -0,0 +1,57 @@
+/* Generic implementation of the shared memory struct shmid_ds.
+   Copyright (C) 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_SHM_H
+# error "Never include <bits/types/struct_shmid_ds.h> directly; use <sys/shm.h> instead."
+#endif
+
+#include <bits/shm-pad.h>
+
+#if __SHM_PAD_BEFORE_TIME
+# define __SHM_PAD_TIME(NAME, RES)				\
+  unsigned long int __glibc_reserved ## RES; __time_t NAME
+#elif __SHM_PAD_AFTER_TIME
+# define __SHM_PAD_TIME(NAME, RES)				\
+  __time_t NAME; unsigned long int __glibc_reserved ## RES
+#else
+# define __SHM_PAD_TIME(NAME, RES)		\
+  __time_t NAME
+#endif
+
+/* Data structure describing a shared memory segment.  */
+struct shmid_ds
+  {
+    struct ipc_perm shm_perm;		/* operation permission struct */
+#if !__SHM_SEGSZ_AFTER_TIME
+    size_t shm_segsz;			/* size of segment in bytes */
+#endif
+    __SHM_PAD_TIME (shm_atime, 1);	/* time of last shmat() */
+    __SHM_PAD_TIME (shm_dtime, 2);	/* time of last shmdt() */
+    __SHM_PAD_TIME (shm_ctime, 3);	/* time of last change by shmctl() */
+#if __SHM_PAD_BETWEEN_TIME_AND_SEGSZ
+    unsigned long int __glibc_reserved4;
+#endif
+#if __SHM_SEGSZ_AFTER_TIME
+    size_t shm_segsz;			/* size of segment in bytes */
+#endif
+    __pid_t shm_cpid;			/* pid of creator */
+    __pid_t shm_lpid;			/* pid of last shmop */
+    shmatt_t shm_nattch;		/* number of current attaches */
+    __syscall_ulong_t __glibc_reserved5;
+    __syscall_ulong_t __glibc_reserved6;
+  };
-- 
2.25.1


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

* [PATCH 6/7] sysvipc: Remove the linux shm-pad.h file
  2020-06-30 19:24 [PATCH 1/7] sysv: linux: Add 64-bit time_t variant for semctl Adhemerval Zanella
                   ` (3 preceding siblings ...)
  2020-06-30 19:24 ` [PATCH 5/7] sysvipc: Split out linux struct shmid_ds Adhemerval Zanella
@ 2020-06-30 19:24 ` Adhemerval Zanella
  2020-07-07 19:57   ` Carlos O'Donell
  2020-06-30 19:24 ` [PATCH 7/7] sysv: linux: Add 64-bit time_t variant for shmctl Adhemerval Zanella
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 41+ messages in thread
From: Adhemerval Zanella @ 2020-06-30 19:24 UTC (permalink / raw)
  To: libc-alpha; +Cc: stepan, Alistair Francis

Each architecture overrides the struct msqid_ds which its required
kernel ABI one.

Checked on x86_64-linux-gnu and some bases sysvipc tests on hppa,
mips, mipsle, mips64, mips64le, sparc64, sparcv9, powerpc64le,
powerpc64, and powerpc.
---
 sysdeps/unix/sysv/linux/Makefile              |  2 +-
 sysdeps/unix/sysv/linux/bits/shm-pad.h        | 37 --------------
 sysdeps/unix/sysv/linux/bits/shm.h            |  1 -
 .../sysv/linux/bits/types/struct_shmid_ds.h   | 34 +++++--------
 sysdeps/unix/sysv/linux/hppa/bits/shm-pad.h   | 28 -----------
 .../linux/hppa/bits/types/struct_shmid_ds.h   | 46 +++++++++++++++++
 sysdeps/unix/sysv/linux/mips/bits/shm-pad.h   | 26 ----------
 .../linux/mips/bits/types/struct_shmid_ds.h   | 49 +++++++++++++++++++
 .../unix/sysv/linux/powerpc/bits/shm-pad.h    | 28 -----------
 .../powerpc/bits/types/struct_shmid_ds.h      | 46 +++++++++++++++++
 sysdeps/unix/sysv/linux/sparc/bits/shm-pad.h  | 28 -----------
 .../linux/sparc/bits/types/struct_shmid_ds.h  | 45 +++++++++++++++++
 12 files changed, 198 insertions(+), 172 deletions(-)
 delete mode 100644 sysdeps/unix/sysv/linux/bits/shm-pad.h
 delete mode 100644 sysdeps/unix/sysv/linux/hppa/bits/shm-pad.h
 create mode 100644 sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
 delete mode 100644 sysdeps/unix/sysv/linux/mips/bits/shm-pad.h
 create mode 100644 sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
 delete mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/shm-pad.h
 create mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
 delete mode 100644 sysdeps/unix/sysv/linux/sparc/bits/shm-pad.h
 create mode 100644 sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h

diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index bdd187af73..fd0c313041 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -85,7 +85,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/shmlba.h bits/shm-pad.h \
+		  bits/shmlba.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/shm-pad.h b/sysdeps/unix/sysv/linux/bits/shm-pad.h
deleted file mode 100644
index 565e0e344b..0000000000
--- a/sysdeps/unix/sysv/linux/bits/shm-pad.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Define where padding goes in struct shmid_ds.  Generic 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_SHM_H
-# error "Never use <bits/shm-pad.h> directly; include <sys/shm.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.  Furthermore, some
-   architectures place shm_segsz after the time fields rather than
-   before them, with or without padding there.  This must match the
-   layout used for struct shmid64_ds in <asm/shmbuf.h>, as glibc does
-   not do layout conversions for this structure.  */
-
-#define __SHM_PAD_AFTER_TIME (__TIMESIZE == 32)
-#define __SHM_PAD_BEFORE_TIME 0
-#define __SHM_SEGSZ_AFTER_TIME 0
-#define __SHM_PAD_BETWEEN_TIME_AND_SEGSZ 0
diff --git a/sysdeps/unix/sysv/linux/bits/shm.h b/sysdeps/unix/sysv/linux/bits/shm.h
index 9ef6aeaf92..f6aefa17f2 100644
--- a/sysdeps/unix/sysv/linux/bits/shm.h
+++ b/sysdeps/unix/sysv/linux/bits/shm.h
@@ -22,7 +22,6 @@
 #include <bits/types.h>
 #include <bits/wordsize.h>
 #include <bits/shmlba.h>
-#include <bits/shm-pad.h>
 
 /* Permission flag for shmget.  */
 #define SHM_R		0400		/* or S_IRUGO from <linux/stat.h> */
diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
index 938bbedfcd..61ed4a08c3 100644
--- a/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
+++ b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
@@ -20,34 +20,22 @@
 # error "Never include <bits/types/struct_shmid_ds.h> directly; use <sys/shm.h> instead."
 #endif
 
-#include <bits/shm-pad.h>
-
-#if __SHM_PAD_BEFORE_TIME
-# define __SHM_PAD_TIME(NAME, RES)				\
-  unsigned long int __glibc_reserved ## RES; __time_t NAME
-#elif __SHM_PAD_AFTER_TIME
-# define __SHM_PAD_TIME(NAME, RES)				\
-  __time_t NAME; unsigned long int __glibc_reserved ## RES
-#else
-# define __SHM_PAD_TIME(NAME, RES)		\
-  __time_t NAME
-#endif
-
 /* Data structure describing a shared memory segment.  */
 struct shmid_ds
   {
     struct ipc_perm shm_perm;		/* operation permission struct */
-#if !__SHM_SEGSZ_AFTER_TIME
-    size_t shm_segsz;			/* size of segment in bytes */
-#endif
-    __SHM_PAD_TIME (shm_atime, 1);	/* time of last shmat() */
-    __SHM_PAD_TIME (shm_dtime, 2);	/* time of last shmdt() */
-    __SHM_PAD_TIME (shm_ctime, 3);	/* time of last change by shmctl() */
-#if __SHM_PAD_BETWEEN_TIME_AND_SEGSZ
-    unsigned long int __glibc_reserved4;
-#endif
-#if __SHM_SEGSZ_AFTER_TIME
     size_t shm_segsz;			/* size of segment in bytes */
+#if __TIMESIZE == 32
+    __time_t shm_atime;			/* time of last shmat() */
+    unsigned long int __glibc_reserved1;
+    __time_t shm_dtime;			/* time of last shmdt() */
+    unsigned long int __glibc_reserved2;
+    __time_t shm_ctime;			/* time of last change by shmctl() */
+    unsigned long int __glibc_reserved3;
+#else
+    __time_t shm_atime;			/* time of last shmat() */
+    __time_t shm_dtime;			/* time of last shmdt() */
+    __time_t shm_ctime;			/* time of last change by shmctl() */
 #endif
     __pid_t shm_cpid;			/* pid of creator */
     __pid_t shm_lpid;			/* pid of last shmop */
diff --git a/sysdeps/unix/sysv/linux/hppa/bits/shm-pad.h b/sysdeps/unix/sysv/linux/hppa/bits/shm-pad.h
deleted file mode 100644
index d0811fe543..0000000000
--- a/sysdeps/unix/sysv/linux/hppa/bits/shm-pad.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Define where padding goes in struct shmid_ds.  HPPA 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_SHM_H
-# error "Never use <bits/shm-pad.h> directly; include <sys/shm.h> instead."
-#endif
-
-#include <bits/timesize.h>
-
-#define __SHM_PAD_AFTER_TIME 0
-#define __SHM_PAD_BEFORE_TIME (__TIMESIZE == 32)
-#define __SHM_SEGSZ_AFTER_TIME 1
-#define __SHM_PAD_BETWEEN_TIME_AND_SEGSZ (__TIMESIZE == 32)
diff --git a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
new file mode 100644
index 0000000000..1ebf222eac
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
@@ -0,0 +1,46 @@
+/* Linux/HPPA implementation of the shared memory struct shmid_ds.
+   Copyright (C) 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_SHM_H
+# error "Never include <bits/types/struct_shmid_ds.h> directly; use <sys/shm.h> instead."
+#endif
+
+/* Data structure describing a shared memory segment.  */
+struct shmid_ds
+  {
+    struct ipc_perm shm_perm;		/* operation permission struct */
+#if __TIMESIZE == 32
+    unsigned long int __glibc_reserved1;
+    __time_t shm_atime;			/* time of last shmat() */
+    unsigned long int __glibc_reserved2;
+    __time_t shm_dtime;			/* time of last shmdt() */
+    unsigned long int __glibc_reserved3;
+    __time_t shm_ctime;			/* time of last change by shmctl() */
+    unsigned long int __glibc_reserved4;
+#else
+    __time_t shm_atime;			/* time of last shmat() */
+    __time_t shm_dtime;			/* time of last shmdt() */
+    __time_t shm_ctime;			/* time of last change by shmctl() */
+#endif
+    size_t shm_segsz;			/* size of segment in bytes */
+    __pid_t shm_cpid;			/* pid of creator */
+    __pid_t shm_lpid;			/* pid of last shmop */
+    shmatt_t shm_nattch;		/* number of current attaches */
+    __syscall_ulong_t __glibc_reserved5;
+    __syscall_ulong_t __glibc_reserved6;
+  };
diff --git a/sysdeps/unix/sysv/linux/mips/bits/shm-pad.h b/sysdeps/unix/sysv/linux/mips/bits/shm-pad.h
deleted file mode 100644
index 5a475a64f9..0000000000
--- a/sysdeps/unix/sysv/linux/mips/bits/shm-pad.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Define where padding goes in struct shmid_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_SHM_H
-# error "Never use <bits/shm-pad.h> directly; include <sys/shm.h> instead."
-#endif
-
-#define __SHM_PAD_AFTER_TIME 0
-#define __SHM_PAD_BEFORE_TIME 0
-#define __SHM_SEGSZ_AFTER_TIME 0
-#define __SHM_PAD_BETWEEN_TIME_AND_SEGSZ 0
diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
new file mode 100644
index 0000000000..8e13928980
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
@@ -0,0 +1,49 @@
+/* Linux/MIPS implementation of the shared memory struct shmid_ds.
+   Copyright (C) 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_SHM_H
+# error "Never include <bits/types/struct_shmid_ds.h> directly; use <sys/shm.h> instead."
+#endif
+
+/* Data structure describing a shared memory segment.  */
+struct shmid_ds
+  {
+    struct ipc_perm shm_perm;		/* operation permission struct */
+    size_t shm_segsz;			/* size of segment in bytes */
+#if __TIMESIZE == 32
+    __time_t shm_atime;			/* time of last shmat() */
+    __time_t shm_dtime;			/* time of last shmdt() */
+    __time_t shm_ctime;			/* time of last change by shmctl() */
+#else
+    __time_t shm_atime;			/* time of last shmat() */
+    __time_t shm_dtime;			/* time of last shmdt() */
+    __time_t shm_ctime;			/* time of last change by shmctl() */
+#endif
+    __pid_t shm_cpid;			/* pid of creator */
+    __pid_t shm_lpid;			/* pid of last shmop */
+    shmatt_t shm_nattch;		/* number of current attaches */
+#if __TIMESIZE == 32
+    unsigned short int __glibc_reserved1;
+    unsigned short int __glibc_reserved2;
+    unsigned short int __glibc_reserved3;
+    unsigned short int __glibc_reserved4;
+#else
+    __syscall_ulong_t __glibc_reserved5;
+    __syscall_ulong_t __glibc_reserved6;
+#endif
+  };
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/shm-pad.h b/sysdeps/unix/sysv/linux/powerpc/bits/shm-pad.h
deleted file mode 100644
index 34cbdb2a0d..0000000000
--- a/sysdeps/unix/sysv/linux/powerpc/bits/shm-pad.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Define where padding goes in struct shmid_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_SHM_H
-# error "Never use <bits/shm-pad.h> directly; include <sys/shm.h> instead."
-#endif
-
-#include <bits/timesize.h>
-
-#define __SHM_PAD_AFTER_TIME 0
-#define __SHM_PAD_BEFORE_TIME (__TIMESIZE == 32)
-#define __SHM_SEGSZ_AFTER_TIME 1
-#define __SHM_PAD_BETWEEN_TIME_AND_SEGSZ (__TIMESIZE == 32)
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
new file mode 100644
index 0000000000..b0816fb16a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
@@ -0,0 +1,46 @@
+/* Linux/PowerPC implementation of the shared memory struct shmid_ds.
+   Copyright (C) 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_SHM_H
+# error "Never include <bits/types/struct_shmid_ds.h> directly; use <sys/shm.h> instead."
+#endif
+
+/* Data structure describing a shared memory segment.  */
+struct shmid_ds
+  {
+    struct ipc_perm shm_perm;		/* operation permission struct */
+#if __TIMESIZE == 32
+    unsigned long int __glibc_reserved1;
+    __time_t shm_atime;			/* time of last shmat() */
+    unsigned long int __glibc_reserved2;
+    __time_t shm_dtime;			/* time of last shmdt() */
+    unsigned long int __glibc_reserved3;
+    __time_t shm_ctime;			/* time of last change by shmctl() */
+    unsigned long int __glibc_reserved4;
+#else
+    __time_t shm_atime;			/* time of last shmat() */
+    __time_t shm_dtime;			/* time of last shmdt() */
+    __time_t shm_ctime;			/* time of last change by shmctl() */
+#endif
+    size_t shm_segsz;			/* size of segment in bytes */
+    __pid_t shm_cpid;			/* pid of creator */
+    __pid_t shm_lpid;			/* pid of last shmop */
+    shmatt_t shm_nattch;		/* number of current attaches */
+    __syscall_ulong_t __glibc_reserved5;
+    __syscall_ulong_t __glibc_reserved6;
+  };
diff --git a/sysdeps/unix/sysv/linux/sparc/bits/shm-pad.h b/sysdeps/unix/sysv/linux/sparc/bits/shm-pad.h
deleted file mode 100644
index cd0b1fe543..0000000000
--- a/sysdeps/unix/sysv/linux/sparc/bits/shm-pad.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Define where padding goes in struct shmid_ds.  SPARC 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_SHM_H
-# error "Never use <bits/shm-pad.h> directly; include <sys/shm.h> instead."
-#endif
-
-#include <bits/timesize.h>
-
-#define __SHM_PAD_AFTER_TIME 0
-#define __SHM_PAD_BEFORE_TIME (__TIMESIZE == 32)
-#define __SHM_SEGSZ_AFTER_TIME 1
-#define __SHM_PAD_BETWEEN_TIME_AND_SEGSZ 0
diff --git a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h
new file mode 100644
index 0000000000..d5fb61d374
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h
@@ -0,0 +1,45 @@
+/* Linux/SPARC implementation of the shared memory struct shmid_ds.
+   Copyright (C) 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_SHM_H
+# error "Never include <bits/types/struct_shmid_ds.h> directly; use <sys/shm.h> instead."
+#endif
+
+/* Data structure describing a shared memory segment.  */
+struct shmid_ds
+  {
+    struct ipc_perm shm_perm;		/* operation permission struct */
+#if __TIMESIZE == 32
+    unsigned long int __glibc_reserved1;
+    __time_t shm_atime;			/* time of last shmat() */
+    unsigned long int __glibc_reserved2;
+    __time_t shm_dtime;			/* time of last shmdt() */
+    unsigned long int __glibc_reserved3;
+    __time_t shm_ctime;			/* time of last change by shmctl() */
+#else
+    __time_t shm_atime;			/* time of last shmat() */
+    __time_t shm_dtime;			/* time of last shmdt() */
+    __time_t shm_ctime;			/* time of last change by shmctl() */
+#endif
+    size_t shm_segsz;			/* size of segment in bytes */
+    __pid_t shm_cpid;			/* pid of creator */
+    __pid_t shm_lpid;			/* pid of last shmop */
+    shmatt_t shm_nattch;		/* number of current attaches */
+    __syscall_ulong_t __glibc_reserved5;
+    __syscall_ulong_t __glibc_reserved6;
+  };
-- 
2.25.1


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

* [PATCH 7/7] sysv: linux: Add 64-bit time_t variant for shmctl
  2020-06-30 19:24 [PATCH 1/7] sysv: linux: Add 64-bit time_t variant for semctl Adhemerval Zanella
                   ` (4 preceding siblings ...)
  2020-06-30 19:24 ` [PATCH 6/7] sysvipc: Remove the linux shm-pad.h file Adhemerval Zanella
@ 2020-06-30 19:24 ` Adhemerval Zanella
  2020-07-01  2:28   ` Alistair Francis
  2020-07-07 21:33   ` Carlos O'Donell
  2020-07-02 19:01 ` [PATCH 1/7] sysv: linux: Add 64-bit time_t variant for semctl Alistair Francis
  2020-07-07  3:32 ` Carlos O'Donell
  7 siblings, 2 replies; 41+ messages in thread
From: Adhemerval Zanella @ 2020-06-30 19:24 UTC (permalink / raw)
  To: libc-alpha; +Cc: stepan, Alistair Francis

To provide a y2038 safe interface a new symbol __shmctl64 is added
and __shmctl is change to call it instead (it adds some extra buffer
copy for the 32 bit time_t implementation).

Two two new structures are added:

  1. kernel_shmid64_ds: used internally only on 32-bit architectures
     to issue the syscall.  A handful architectures (hppa, i386, mips,
     powerpc32, and sparc32) requires specific implementation due its
     specific kernel ABI.

  2. shmid_ds64: this is only for __TIMESIZE != 64 to use along with
     the 64-bit semctl.  It is different than the kernel one because
     the exported 64-bit time_t might require different alignment
     depending of the architecture ABI.

So the resulting implementation does:

  1. For 64-bit architectures it assumes shmid_ds already contains
     64-bit time_t fields it will result in just the __shmctl symbol
     using the __shmctl64 code.  The shmid_ds argument is passed as-is
     to the syscall.

  2. For 32-bit architectures with default 64-bit time_t (newer ABIs
     such riscv32 or arc), it will also result in only one exported
     symbol but with the required high/low time handling.

  3. Finally for 32-bit architecture with both 32-bit and 64-bit time_t
     support we follow the already set way to provide one symbol with
     64-bit time_t support and implement the 32-bit time_t support on
     basis of the 64-bit one.

     The default 32-bit symbol will allocate and copy the shmid_ds
     over multiple buffers, but this should be deprecated in favor
     of the __shmctl64 anyway.

Checked on i686-linux-gnu and x86_64-linux-gnu.  I also did some sniff
tests on powerpc, powerpc64, mips, mips64, armhf, sparcv9, and
sparc64.
---
 include/sys/shm.h                             |  16 ++
 .../sysv/linux/bits/types/struct_shmid64_ds.h |  37 ++++
 .../sysv/linux/bits/types/struct_shmid_ds.h   |   6 +-
 .../linux/hppa/bits/types/struct_shmid_ds.h   |   6 +-
 .../linux/hppa/struct_kernel_shmid64_ds.h     |  18 ++
 .../linux/i386/struct_kernel_shmid64_ds.h     |  17 ++
 .../linux/mips/bits/types/struct_shmid_ds.h   |   6 +-
 .../linux/mips/struct_kernel_shmid64_ds.h     |  27 +++
 .../powerpc/bits/types/struct_shmid_ds.h      |   6 +-
 .../linux/powerpc/struct_kernel_shmid64_ds.h  |  24 +++
 sysdeps/unix/sysv/linux/shmctl.c              | 180 ++++++++++++++----
 .../linux/sparc/bits/types/struct_shmid_ds.h  |   6 +-
 .../linux/sparc/struct_kernel_shmid64_ds.h    |  23 +++
 .../sysv/linux/struct_kernel_shmid64_ds.h     |  23 +++
 14 files changed, 346 insertions(+), 49 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h

diff --git a/include/sys/shm.h b/include/sys/shm.h
index 1878fcc5be..530a1cdfc9 100644
--- a/include/sys/shm.h
+++ b/include/sys/shm.h
@@ -1 +1,17 @@
+#ifndef _SYS_SHM_H
 #include <sysvipc/sys/shm.h>
+
+#ifndef _ISOMAC
+
+# include <bits/types/struct_shmid64_ds.h>
+
+# if __TIMESIZE == 64
+#  define __shmctl64 __shmctl
+# else
+extern int __shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf);
+libc_hidden_proto (__shmctl64);
+# endif
+
+#endif /* _ISOMAC  */
+
+#endif /* _SYS_SHM_H  */
diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h
new file mode 100644
index 0000000000..f71e0d28ff
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h
@@ -0,0 +1,37 @@
+/* Generic implementation of the shared memory struct shmid_ds.
+   Copyright (C) 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_SHM_H
+# error "Never include <bits/types/struct_shmid_ds.h> directly; use <sys/shm.h> instead."
+#endif
+
+#if __TIMESIZE == 64
+# define __shmid64_ds shmid_ds
+#else
+struct __shmid64_ds
+{
+  struct ipc_perm shm_perm;	/* operation permission struct */
+  size_t shm_segsz;		/* size of segment in bytes */
+  __time64_t shm_atime;		/* time of last shmat() */
+  __time64_t shm_dtime;		/* time of last shmdt() */
+  __time64_t shm_ctime;		/* time of last change by shmctl() */
+  __pid_t shm_cpid;		/* pid of creator */
+  __pid_t shm_lpid;		/* pid of last shmop */
+  shmatt_t shm_nattch;		/* number of current attaches */
+};
+#endif
diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
index 61ed4a08c3..836a7d50e9 100644
--- a/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
+++ b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
@@ -27,11 +27,11 @@ struct shmid_ds
     size_t shm_segsz;			/* size of segment in bytes */
 #if __TIMESIZE == 32
     __time_t shm_atime;			/* time of last shmat() */
-    unsigned long int __glibc_reserved1;
+    unsigned long int __shm_atime_high;
     __time_t shm_dtime;			/* time of last shmdt() */
-    unsigned long int __glibc_reserved2;
+    unsigned long int __shm_dtime_high;
     __time_t shm_ctime;			/* time of last change by shmctl() */
-    unsigned long int __glibc_reserved3;
+    unsigned long int __shm_ctime_high;
 #else
     __time_t shm_atime;			/* time of last shmat() */
     __time_t shm_dtime;			/* time of last shmdt() */
diff --git a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
index 1ebf222eac..1abed1e149 100644
--- a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
+++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
@@ -25,11 +25,11 @@ struct shmid_ds
   {
     struct ipc_perm shm_perm;		/* operation permission struct */
 #if __TIMESIZE == 32
-    unsigned long int __glibc_reserved1;
+    unsigned long int __shm_atime_high;
     __time_t shm_atime;			/* time of last shmat() */
-    unsigned long int __glibc_reserved2;
+    unsigned long int __shm_dtime_high;
     __time_t shm_dtime;			/* time of last shmdt() */
-    unsigned long int __glibc_reserved3;
+    unsigned long int __shm_ctime_high;
     __time_t shm_ctime;			/* time of last change by shmctl() */
     unsigned long int __glibc_reserved4;
 #else
diff --git a/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h
new file mode 100644
index 0000000000..4d09fc7f62
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h
@@ -0,0 +1,18 @@
+/* Analogous to kernel struct shmid64_ds used on shmctl.  */
+struct kernel_shmid64_ds
+{
+  struct ipc_perm shm_perm;		/* operation permission struct */
+  unsigned long int shm_atime_high;
+  unsigned long int shm_atime;		/* time of last shmat() */
+  unsigned long int shm_dtime_high;
+  unsigned long int shm_dtime;		/* time of last shmdt() */
+  unsigned long int shm_ctime_high;
+  unsigned long int shm_ctime;		/* time of last change by shmctl() */
+  unsigned long int __pad;
+  size_t shm_segsz;			/* size of segment in bytes */
+  __pid_t shm_cpid;			/* pid of creator */
+  __pid_t shm_lpid;			/* pid of last shmop */
+  shmatt_t shm_nattch;		/* number of current attaches */
+  unsigned long int __unused1;
+  unsigned long int __unused2;
+};
diff --git a/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h
new file mode 100644
index 0000000000..6a0a0d9c71
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h
@@ -0,0 +1,17 @@
+/* Analogous to kernel struct compat_shmid64_ds used on shmctl.  */
+struct kernel_shmid64_ds
+{
+  struct ipc_perm shm_perm;
+  size_t shm_segsz;
+  unsigned long int shm_atime;
+  unsigned long int shm_atime_high;
+  unsigned long int shm_dtime;
+  unsigned long int shm_dtime_high;
+  unsigned long int shm_ctime;
+  unsigned long int shm_ctime_high;
+  __pid_t shm_cpid;
+  __pid_t shm_lpid;
+  unsigned long int shm_nattch;
+  unsigned long int __unused4;
+  unsigned long int __unused5;
+};
diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
index 8e13928980..58090e2fcb 100644
--- a/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
+++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
@@ -38,9 +38,9 @@ struct shmid_ds
     __pid_t shm_lpid;			/* pid of last shmop */
     shmatt_t shm_nattch;		/* number of current attaches */
 #if __TIMESIZE == 32
-    unsigned short int __glibc_reserved1;
-    unsigned short int __glibc_reserved2;
-    unsigned short int __glibc_reserved3;
+    unsigned short int __shm_atime_high;
+    unsigned short int __shm_dtime_high;
+    unsigned short int __shm_ctime_high;
     unsigned short int __glibc_reserved4;
 #else
     __syscall_ulong_t __glibc_reserved5;
diff --git a/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h
new file mode 100644
index 0000000000..a4baa5614f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h
@@ -0,0 +1,27 @@
+/* Analogous to kernel struct shmid64_ds used on shmctl.  */
+struct kernel_shmid64_ds
+{
+  struct ipc_perm shm_perm;
+  size_t shm_segsz;
+#if __TIMESIZE == 64
+  long int shm_atime;
+  long int shm_dtime;
+  long int shm_ctime;
+#else
+  unsigned long int shm_atime;
+  unsigned long int shm_dtime;
+  unsigned long int shm_ctime;
+#endif
+  __pid_t shm_cpid;
+  __pid_t shm_lpid;
+  unsigned long int shm_nattch;
+#if __TIMESIZE == 64
+  unsigned long int __unused1;
+  unsigned long int __unused2;
+#else
+  unsigned short int shm_atime_high;
+  unsigned short int shm_dtime_high;
+  unsigned short int shm_ctime_high;
+  unsigned short int __ununsed1;
+#endif
+};
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
index b0816fb16a..39b3e5fd3e 100644
--- a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
@@ -25,11 +25,11 @@ struct shmid_ds
   {
     struct ipc_perm shm_perm;		/* operation permission struct */
 #if __TIMESIZE == 32
-    unsigned long int __glibc_reserved1;
+    unsigned long int __shm_atime_high;
     __time_t shm_atime;			/* time of last shmat() */
-    unsigned long int __glibc_reserved2;
+    unsigned long int __shm_dtime_high;
     __time_t shm_dtime;			/* time of last shmdt() */
-    unsigned long int __glibc_reserved3;
+    unsigned long int __shm_ctime_high;
     __time_t shm_ctime;			/* time of last change by shmctl() */
     unsigned long int __glibc_reserved4;
 #else
diff --git a/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
new file mode 100644
index 0000000000..5533d44dee
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
@@ -0,0 +1,24 @@
+/* Analogous to kernel struct shmid64_ds used on shmctl.  */
+struct kernel_shmid64_ds
+{
+  struct ipc_perm shm_perm;
+#if __TIMESIZE == 64
+  long int shm_atime;
+  long int shm_atime;
+  long int shm_atime;
+#else
+  unsigned long int shm_atime_high;
+  unsigned long int shm_atime;
+  unsigned long int shm_dtime_high;
+  unsigned long int shm_dtime;
+  unsigned long int shm_ctime_high;
+  unsigned long int shm_ctime;
+  unsigned long int __ununsed1;
+#endif
+  size_t shm_segsz;
+  __pid_t shm_cpid;
+  __pid_t shm_lpid;
+  unsigned long int shm_nattch;
+  unsigned long int __unused2;
+  unsigned long int __unused3;
+};
diff --git a/sysdeps/unix/sysv/linux/shmctl.c b/sysdeps/unix/sysv/linux/shmctl.c
index f41b359b8b..aaf3946054 100644
--- a/sysdeps/unix/sysv/linux/shmctl.c
+++ b/sysdeps/unix/sysv/linux/shmctl.c
@@ -24,16 +24,55 @@
 #include <errno.h>
 #include <linux/posix_types.h>  /* For __kernel_mode_t.  */
 
-#ifndef DEFAULT_VERSION
-# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
-#  define DEFAULT_VERSION GLIBC_2_2
-# else
-#  define DEFAULT_VERSION GLIBC_2_31
-# endif
+/* POSIX states ipc_perm mode should have type of mode_t.  */
+_Static_assert (sizeof ((struct shmid_ds){0}.shm_perm.mode)
+		== sizeof (mode_t),
+		"sizeof (shmid_ds.shm_perm.mode) != sizeof (mode_t)");
+
+#if __IPC_TIME64 == 0
+typedef struct shmid_ds shmctl_arg_t;
+#else
+# include <struct_kernel_shmid64_ds.h>
+
+static void
+shmid64_to_kshmid64 (const struct __shmid64_ds *shmid64,
+		     struct kernel_shmid64_ds *kshmid)
+{
+  kshmid->shm_perm       = shmid64->shm_perm;
+  kshmid->shm_segsz      = shmid64->shm_segsz;
+  kshmid->shm_atime      = shmid64->shm_atime;
+  kshmid->shm_atime_high = shmid64->shm_atime >> 32;
+  kshmid->shm_dtime      = shmid64->shm_dtime;
+  kshmid->shm_dtime_high = shmid64->shm_dtime >> 32;
+  kshmid->shm_ctime      = shmid64->shm_ctime;
+  kshmid->shm_ctime_high = shmid64->shm_ctime >> 32;
+  kshmid->shm_cpid       = shmid64->shm_cpid;
+  kshmid->shm_lpid       = shmid64->shm_lpid;
+  kshmid->shm_nattch     = shmid64->shm_nattch;
+}
+
+static void
+kshmid64_to_shmid64 (const struct kernel_shmid64_ds *kshmid,
+		     struct __shmid64_ds *shmid64)
+{
+  shmid64->shm_perm   = kshmid->shm_perm;
+  shmid64->shm_segsz  = kshmid->shm_segsz;
+  shmid64->shm_atime  = kshmid->shm_atime
+		        | ((__time64_t) kshmid->shm_atime_high << 32);
+  shmid64->shm_dtime  = kshmid->shm_dtime
+		        | ((__time64_t) kshmid->shm_dtime_high << 32);
+  shmid64->shm_ctime     = kshmid->shm_ctime
+		        | ((__time64_t) kshmid->shm_ctime_high << 32);
+  shmid64->shm_cpid   = kshmid->shm_cpid;
+  shmid64->shm_lpid   = kshmid->shm_lpid;
+  shmid64->shm_nattch = kshmid->shm_nattch;
+}
+
+typedef struct kernel_shmid64_ds shmctl_arg_t;
 #endif
 
 static int
-shmctl_syscall (int shmid, int cmd, struct shmid_ds *buf)
+shmctl_syscall (int shmid, int cmd, shmctl_arg_t *buf)
 {
 #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
   return INLINE_SYSCALL_CALL (shmctl, shmid, cmd | __IPC_64, buf);
@@ -45,46 +84,119 @@ shmctl_syscall (int shmid, int cmd, struct shmid_ds *buf)
 
 /* Provide operations to control over shared memory segments.  */
 int
-__new_shmctl (int shmid, int cmd, struct shmid_ds *buf)
+__shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf)
 {
-  /* POSIX states ipc_perm mode should have type of mode_t.  */
-  _Static_assert (sizeof ((struct shmid_ds){0}.shm_perm.mode)
-		  == sizeof (mode_t),
-		  "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");
-
-#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
-  struct shmid_ds tmpds;
-  if (cmd == IPC_SET)
+#if __IPC_TIME64
+  struct kernel_shmid64_ds kshmid, *arg = NULL;
+  if (buf != NULL)
     {
-      tmpds = *buf;
-      tmpds.shm_perm.mode *= 0x10000U;
-      buf = &tmpds;
+      shmid64_to_kshmid64 (buf, &kshmid);
+      arg = &kshmid;
     }
+# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
+  if (cmd == IPC_SET)
+      arg->shm_perm.mode *= 0x10000U;
+# endif
+#else
+  shmctl_arg_t *arg = buf;
 #endif
 
-  int ret = shmctl_syscall (shmid, cmd, buf);
+  int ret = shmctl_syscall (shmid, cmd, arg);
+  if (ret < 0)
+    return ret;
 
-  if (ret >= 0)
+  switch (cmd)
     {
-      switch (cmd)
-	{
-        case IPC_STAT:
-        case SHM_STAT:
-        case SHM_STAT_ANY:
+      case IPC_STAT:
+      case SHM_STAT:
+      case SHM_STAT_ANY:
 #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
-          buf->shm_perm.mode >>= 16;
+        arg->shm_perm.mode >>= 16;
 #else
-	  /* Old Linux kernel versions might not clear the mode padding.  */
-	  if (sizeof ((struct shmid_ds){0}.shm_perm.mode)
-	      != sizeof (__kernel_mode_t))
-	    buf->shm_perm.mode &= 0xFFFF;
+      /* Old Linux kernel versions might not clear the mode padding.  */
+      if (sizeof ((struct shmid_ds){0}.shm_perm.mode)
+	  != sizeof (__kernel_mode_t))
+	arg->shm_perm.mode &= 0xFFFF;
+#endif
+
+#if __IPC_TIME64
+      kshmid64_to_shmid64 (arg, buf);
 #endif
-	}
     }
 
   return ret;
 }
-versioned_symbol (libc, __new_shmctl, shmctl, DEFAULT_VERSION);
+#if __TIMESIZE != 64
+libc_hidden_def (__shmctl64)
+
+static void
+shmid_to_shmid64 (struct __shmid64_ds *shm64, const struct shmid_ds *shm)
+{
+  shm64->shm_perm   = shm->shm_perm;
+  shm64->shm_segsz  = shm->shm_segsz;
+  shm64->shm_atime  = shm->shm_atime
+		        | ((__time64_t) shm->__shm_atime_high << 32);
+  shm64->shm_dtime  = shm->shm_dtime
+		        | ((__time64_t) shm->__shm_dtime_high << 32);
+  shm64->shm_ctime     = shm->shm_ctime
+		        | ((__time64_t) shm->__shm_ctime_high << 32);
+  shm64->shm_cpid   = shm->shm_cpid;
+  shm64->shm_lpid   = shm->shm_lpid;
+  shm64->shm_nattch = shm->shm_nattch;
+}
+
+static void
+shmid64_to_shmid (struct shmid_ds *shm, const struct __shmid64_ds *shm64)
+{
+  shm->shm_perm         = shm64->shm_perm;
+  shm->shm_segsz        = shm64->shm_segsz;
+  shm->shm_atime        = shm64->shm_atime;
+  shm->__shm_atime_high = 0;
+  shm->shm_dtime        = shm64->shm_dtime;
+  shm->__shm_dtime_high = 0;
+  shm->shm_ctime        = shm64->shm_ctime;
+  shm->__shm_ctime_high = 0;
+  shm->shm_cpid         = shm64->shm_cpid;
+  shm->shm_lpid         = shm64->shm_lpid;
+  shm->shm_nattch       = shm64->shm_nattch;
+}
+
+int
+__shmctl (int shmid, int cmd, struct shmid_ds *buf)
+{
+  struct __shmid64_ds shmid64, *buf64 = NULL;
+  if (buf != NULL)
+    {
+      shmid_to_shmid64 (&shmid64, buf);
+      buf64 = &shmid64;
+    }
+
+  int ret = __shmctl64 (shmid, cmd, buf64);
+  if (ret < 0)
+    return ret;
+
+  switch (cmd)
+    {
+      case IPC_STAT:
+      case SHM_STAT:
+      case SHM_STAT_ANY:
+	if (buf64 != NULL)
+	  shmid64_to_shmid (buf, buf64);
+    }
+
+  return ret;
+}
+#endif
+
+#ifndef DEFAULT_VERSION
+# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
+#  define DEFAULT_VERSION GLIBC_2_2
+# else
+#  define DEFAULT_VERSION GLIBC_2_31
+# endif
+#endif
+
+versioned_symbol (libc, __shmctl, shmctl, DEFAULT_VERSION);
 
 #if defined __ASSUME_SYSVIPC_BROKEN_MODE_T \
     && SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_31)
@@ -92,7 +204,7 @@ int
 attribute_compat_text_section
 __shmctl_mode16 (int shmid, int cmd, struct shmid_ds *buf)
 {
-  return shmctl_syscall (shmid, cmd, buf);
+  return shmctl_syscall (shmid, cmd, (shmctl_arg_t *) buf);
 }
 compat_symbol (libc, __shmctl_mode16, shmctl, GLIBC_2_2);
 #endif
diff --git a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h
index d5fb61d374..cab3a2686f 100644
--- a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h
+++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h
@@ -25,11 +25,11 @@ struct shmid_ds
   {
     struct ipc_perm shm_perm;		/* operation permission struct */
 #if __TIMESIZE == 32
-    unsigned long int __glibc_reserved1;
+    unsigned long int __shm_atime_high;
     __time_t shm_atime;			/* time of last shmat() */
-    unsigned long int __glibc_reserved2;
+    unsigned long int __shm_dtime_high;
     __time_t shm_dtime;			/* time of last shmdt() */
-    unsigned long int __glibc_reserved3;
+    unsigned long int __shm_ctime_high;
     __time_t shm_ctime;			/* time of last change by shmctl() */
 #else
     __time_t shm_atime;			/* time of last shmat() */
diff --git a/sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h
new file mode 100644
index 0000000000..c9ecd7b1e9
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h
@@ -0,0 +1,23 @@
+/* Analogous to kernel struct shmid64_ds used on shmctl.  */
+struct kernel_shmid64_ds
+{
+  struct ipc_perm shm_perm;
+#if __TIMESIZE == 64
+  long int shm_atime;
+  long int shm_atime;
+  long int shm_atime;
+#else
+  unsigned long int shm_atime_high;
+  unsigned long int shm_atime;
+  unsigned long int shm_dtime_high;
+  unsigned long int shm_dtime;
+  unsigned long int shm_ctime_high;
+  unsigned long int shm_ctime;
+#endif
+  size_t shm_segsz;
+  __pid_t shm_cpid;
+  __pid_t shm_lpid;
+  unsigned long int shm_nattch;
+  unsigned long int __unused1;
+  unsigned long int __unused2;
+};
diff --git a/sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h
new file mode 100644
index 0000000000..395b61e7b2
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h
@@ -0,0 +1,23 @@
+/* Analogous to kernel struct shmid64_ds used on shmctl.  */
+struct kernel_shmid64_ds
+{
+  struct ipc_perm shm_perm;
+  size_t shm_segsz;
+#if __TIMESIZE == 64
+  long int shm_atime;
+  long int shm_atime;
+  long int shm_atime;
+#else
+  unsigned long int shm_atime;
+  unsigned long int shm_atime_high;
+  unsigned long int shm_dtime;
+  unsigned long int shm_dtime_high;
+  unsigned long int shm_ctime;
+  unsigned long int shm_ctime_high;
+#endif
+  __pid_t shm_cpid;
+  __pid_t shm_lpid;
+  unsigned long int shm_nattch;
+  unsigned long int __unused1;
+  unsigned long int __unused2;
+};
-- 
2.25.1


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

* Re: [PATCH 7/7] sysv: linux: Add 64-bit time_t variant for shmctl
  2020-06-30 19:24 ` [PATCH 7/7] sysv: linux: Add 64-bit time_t variant for shmctl Adhemerval Zanella
@ 2020-07-01  2:28   ` Alistair Francis
  2020-07-01 12:19     ` Adhemerval Zanella
  2020-07-07 21:33   ` Carlos O'Donell
  1 sibling, 1 reply; 41+ messages in thread
From: Alistair Francis @ 2020-07-01  2:28 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: GNU C Library, Stepan Golosunov, Alistair Francis

On Tue, Jun 30, 2020 at 12:28 PM Adhemerval Zanella via Libc-alpha
<libc-alpha@sourceware.org> wrote:
>
> To provide a y2038 safe interface a new symbol __shmctl64 is added
> and __shmctl is change to call it instead (it adds some extra buffer
> copy for the 32 bit time_t implementation).
>
> Two two new structures are added:
>
>   1. kernel_shmid64_ds: used internally only on 32-bit architectures
>      to issue the syscall.  A handful architectures (hppa, i386, mips,
>      powerpc32, and sparc32) requires specific implementation due its
>      specific kernel ABI.
>
>   2. shmid_ds64: this is only for __TIMESIZE != 64 to use along with
>      the 64-bit semctl.  It is different than the kernel one because
>      the exported 64-bit time_t might require different alignment
>      depending of the architecture ABI.
>
> So the resulting implementation does:
>
>   1. For 64-bit architectures it assumes shmid_ds already contains
>      64-bit time_t fields it will result in just the __shmctl symbol
>      using the __shmctl64 code.  The shmid_ds argument is passed as-is
>      to the syscall.
>
>   2. For 32-bit architectures with default 64-bit time_t (newer ABIs
>      such riscv32 or arc), it will also result in only one exported
>      symbol but with the required high/low time handling.
>
>   3. Finally for 32-bit architecture with both 32-bit and 64-bit time_t
>      support we follow the already set way to provide one symbol with
>      64-bit time_t support and implement the 32-bit time_t support on
>      basis of the 64-bit one.
>
>      The default 32-bit symbol will allocate and copy the shmid_ds
>      over multiple buffers, but this should be deprecated in favor
>      of the __shmctl64 anyway.
>
> Checked on i686-linux-gnu and x86_64-linux-gnu.  I also did some sniff
> tests on powerpc, powerpc64, mips, mips64, armhf, sparcv9, and
> sparc64.
> ---
>  include/sys/shm.h                             |  16 ++
>  .../sysv/linux/bits/types/struct_shmid64_ds.h |  37 ++++
>  .../sysv/linux/bits/types/struct_shmid_ds.h   |   6 +-
>  .../linux/hppa/bits/types/struct_shmid_ds.h   |   6 +-
>  .../linux/hppa/struct_kernel_shmid64_ds.h     |  18 ++
>  .../linux/i386/struct_kernel_shmid64_ds.h     |  17 ++
>  .../linux/mips/bits/types/struct_shmid_ds.h   |   6 +-
>  .../linux/mips/struct_kernel_shmid64_ds.h     |  27 +++
>  .../powerpc/bits/types/struct_shmid_ds.h      |   6 +-
>  .../linux/powerpc/struct_kernel_shmid64_ds.h  |  24 +++
>  sysdeps/unix/sysv/linux/shmctl.c              | 180 ++++++++++++++----
>  .../linux/sparc/bits/types/struct_shmid_ds.h  |   6 +-
>  .../linux/sparc/struct_kernel_shmid64_ds.h    |  23 +++
>  .../sysv/linux/struct_kernel_shmid64_ds.h     |  23 +++
>  14 files changed, 346 insertions(+), 49 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h
>
> diff --git a/include/sys/shm.h b/include/sys/shm.h
> index 1878fcc5be..530a1cdfc9 100644
> --- a/include/sys/shm.h
> +++ b/include/sys/shm.h
> @@ -1 +1,17 @@
> +#ifndef _SYS_SHM_H
>  #include <sysvipc/sys/shm.h>
> +
> +#ifndef _ISOMAC
> +
> +# include <bits/types/struct_shmid64_ds.h>
> +
> +# if __TIMESIZE == 64
> +#  define __shmctl64 __shmctl
> +# else
> +extern int __shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf);
> +libc_hidden_proto (__shmctl64);
> +# endif
> +
> +#endif /* _ISOMAC  */
> +
> +#endif /* _SYS_SHM_H  */
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h
> new file mode 100644
> index 0000000000..f71e0d28ff
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h
> @@ -0,0 +1,37 @@
> +/* Generic implementation of the shared memory struct shmid_ds.
> +   Copyright (C) 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_SHM_H
> +# error "Never include <bits/types/struct_shmid_ds.h> directly; use <sys/shm.h> instead."
> +#endif
> +
> +#if __TIMESIZE == 64
> +# define __shmid64_ds shmid_ds
> +#else
> +struct __shmid64_ds
> +{
> +  struct ipc_perm shm_perm;    /* operation permission struct */
> +  size_t shm_segsz;            /* size of segment in bytes */
> +  __time64_t shm_atime;                /* time of last shmat() */
> +  __time64_t shm_dtime;                /* time of last shmdt() */
> +  __time64_t shm_ctime;                /* time of last change by shmctl() */
> +  __pid_t shm_cpid;            /* pid of creator */
> +  __pid_t shm_lpid;            /* pid of last shmop */
> +  shmatt_t shm_nattch;         /* number of current attaches */
> +};
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
> index 61ed4a08c3..836a7d50e9 100644
> --- a/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
> @@ -27,11 +27,11 @@ struct shmid_ds
>      size_t shm_segsz;                  /* size of segment in bytes */
>  #if __TIMESIZE == 32
>      __time_t shm_atime;                        /* time of last shmat() */
> -    unsigned long int __glibc_reserved1;
> +    unsigned long int __shm_atime_high;
>      __time_t shm_dtime;                        /* time of last shmdt() */
> -    unsigned long int __glibc_reserved2;
> +    unsigned long int __shm_dtime_high;
>      __time_t shm_ctime;                        /* time of last change by shmctl() */
> -    unsigned long int __glibc_reserved3;
> +    unsigned long int __shm_ctime_high;
>  #else
>      __time_t shm_atime;                        /* time of last shmat() */
>      __time_t shm_dtime;                        /* time of last shmdt() */
> diff --git a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
> index 1ebf222eac..1abed1e149 100644
> --- a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
> +++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
> @@ -25,11 +25,11 @@ struct shmid_ds
>    {
>      struct ipc_perm shm_perm;          /* operation permission struct */
>  #if __TIMESIZE == 32
> -    unsigned long int __glibc_reserved1;
> +    unsigned long int __shm_atime_high;
>      __time_t shm_atime;                        /* time of last shmat() */
> -    unsigned long int __glibc_reserved2;
> +    unsigned long int __shm_dtime_high;
>      __time_t shm_dtime;                        /* time of last shmdt() */
> -    unsigned long int __glibc_reserved3;
> +    unsigned long int __shm_ctime_high;
>      __time_t shm_ctime;                        /* time of last change by shmctl() */
>      unsigned long int __glibc_reserved4;
>  #else
> diff --git a/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h
> new file mode 100644
> index 0000000000..4d09fc7f62
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
> +struct kernel_shmid64_ds
> +{
> +  struct ipc_perm shm_perm;            /* operation permission struct */
> +  unsigned long int shm_atime_high;
> +  unsigned long int shm_atime;         /* time of last shmat() */
> +  unsigned long int shm_dtime_high;
> +  unsigned long int shm_dtime;         /* time of last shmdt() */
> +  unsigned long int shm_ctime_high;
> +  unsigned long int shm_ctime;         /* time of last change by shmctl() */
> +  unsigned long int __pad;
> +  size_t shm_segsz;                    /* size of segment in bytes */
> +  __pid_t shm_cpid;                    /* pid of creator */
> +  __pid_t shm_lpid;                    /* pid of last shmop */
> +  shmatt_t shm_nattch;         /* number of current attaches */
> +  unsigned long int __unused1;
> +  unsigned long int __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h
> new file mode 100644
> index 0000000000..6a0a0d9c71
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h
> @@ -0,0 +1,17 @@
> +/* Analogous to kernel struct compat_shmid64_ds used on shmctl.  */
> +struct kernel_shmid64_ds
> +{
> +  struct ipc_perm shm_perm;
> +  size_t shm_segsz;
> +  unsigned long int shm_atime;
> +  unsigned long int shm_atime_high;
> +  unsigned long int shm_dtime;
> +  unsigned long int shm_dtime_high;
> +  unsigned long int shm_ctime;
> +  unsigned long int shm_ctime_high;
> +  __pid_t shm_cpid;
> +  __pid_t shm_lpid;
> +  unsigned long int shm_nattch;
> +  unsigned long int __unused4;
> +  unsigned long int __unused5;
> +};
> diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
> index 8e13928980..58090e2fcb 100644
> --- a/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
> +++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
> @@ -38,9 +38,9 @@ struct shmid_ds
>      __pid_t shm_lpid;                  /* pid of last shmop */
>      shmatt_t shm_nattch;               /* number of current attaches */
>  #if __TIMESIZE == 32
> -    unsigned short int __glibc_reserved1;
> -    unsigned short int __glibc_reserved2;
> -    unsigned short int __glibc_reserved3;
> +    unsigned short int __shm_atime_high;
> +    unsigned short int __shm_dtime_high;
> +    unsigned short int __shm_ctime_high;
>      unsigned short int __glibc_reserved4;
>  #else
>      __syscall_ulong_t __glibc_reserved5;
> diff --git a/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h
> new file mode 100644
> index 0000000000..a4baa5614f
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h
> @@ -0,0 +1,27 @@
> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
> +struct kernel_shmid64_ds
> +{
> +  struct ipc_perm shm_perm;
> +  size_t shm_segsz;
> +#if __TIMESIZE == 64
> +  long int shm_atime;
> +  long int shm_dtime;
> +  long int shm_ctime;
> +#else
> +  unsigned long int shm_atime;
> +  unsigned long int shm_dtime;
> +  unsigned long int shm_ctime;
> +#endif
> +  __pid_t shm_cpid;
> +  __pid_t shm_lpid;
> +  unsigned long int shm_nattch;
> +#if __TIMESIZE == 64
> +  unsigned long int __unused1;
> +  unsigned long int __unused2;
> +#else
> +  unsigned short int shm_atime_high;
> +  unsigned short int shm_dtime_high;
> +  unsigned short int shm_ctime_high;
> +  unsigned short int __ununsed1;
> +#endif
> +};
> diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
> index b0816fb16a..39b3e5fd3e 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
> +++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
> @@ -25,11 +25,11 @@ struct shmid_ds
>    {
>      struct ipc_perm shm_perm;          /* operation permission struct */
>  #if __TIMESIZE == 32
> -    unsigned long int __glibc_reserved1;
> +    unsigned long int __shm_atime_high;
>      __time_t shm_atime;                        /* time of last shmat() */
> -    unsigned long int __glibc_reserved2;
> +    unsigned long int __shm_dtime_high;
>      __time_t shm_dtime;                        /* time of last shmdt() */
> -    unsigned long int __glibc_reserved3;
> +    unsigned long int __shm_ctime_high;
>      __time_t shm_ctime;                        /* time of last change by shmctl() */
>      unsigned long int __glibc_reserved4;
>  #else
> diff --git a/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
> new file mode 100644
> index 0000000000..5533d44dee
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
> @@ -0,0 +1,24 @@
> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
> +struct kernel_shmid64_ds
> +{
> +  struct ipc_perm shm_perm;
> +#if __TIMESIZE == 64
> +  long int shm_atime;
> +  long int shm_atime;
> +  long int shm_atime;

This fails to compile as all three variables have the same name.

Alistair

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

* Re: [PATCH 7/7] sysv: linux: Add 64-bit time_t variant for shmctl
  2020-07-01  2:28   ` Alistair Francis
@ 2020-07-01 12:19     ` Adhemerval Zanella
  2020-07-01 15:48       ` Alistair Francis
  0 siblings, 1 reply; 41+ messages in thread
From: Adhemerval Zanella @ 2020-07-01 12:19 UTC (permalink / raw)
  To: Alistair Francis; +Cc: GNU C Library, Stepan Golosunov, Alistair Francis



On 30/06/2020 23:28, Alistair Francis wrote:
deps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
>> new file mode 100644
>> index 0000000000..5533d44dee
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
>> @@ -0,0 +1,24 @@
>> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
>> +struct kernel_shmid64_ds
>> +{
>> +  struct ipc_perm shm_perm;
>> +#if __TIMESIZE == 64
>> +  long int shm_atime;
>> +  long int shm_atime;
>> +  long int shm_atime;
> 
> This fails to compile as all three variables have the same name.

In fact this code specifically is not used on powerpc since it will
either use the __TIMESIZE == 32 (powerpc32) or not use this
structure at all (powerpc64{le}).  But it is still an issue I will
revise the patch for such issues and remove it (maybe adding a
#error if it used on powerpc64).

Besides it, does it work for riscv32 (which should use the default
definition)?

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

* Re: [PATCH 7/7] sysv: linux: Add 64-bit time_t variant for shmctl
  2020-07-01 12:19     ` Adhemerval Zanella
@ 2020-07-01 15:48       ` Alistair Francis
  2020-07-01 16:35         ` Adhemerval Zanella
  0 siblings, 1 reply; 41+ messages in thread
From: Alistair Francis @ 2020-07-01 15:48 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: GNU C Library, Stepan Golosunov, Alistair Francis

On Wed, Jul 1, 2020 at 5:19 AM Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
>
>
>
> On 30/06/2020 23:28, Alistair Francis wrote:
> deps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
> >> new file mode 100644
> >> index 0000000000..5533d44dee
> >> --- /dev/null
> >> +++ b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
> >> @@ -0,0 +1,24 @@
> >> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
> >> +struct kernel_shmid64_ds
> >> +{
> >> +  struct ipc_perm shm_perm;
> >> +#if __TIMESIZE == 64
> >> +  long int shm_atime;
> >> +  long int shm_atime;
> >> +  long int shm_atime;
> >
> > This fails to compile as all three variables have the same name.
>
> In fact this code specifically is not used on powerpc since it will
> either use the __TIMESIZE == 32 (powerpc32) or not use this
> structure at all (powerpc64{le}).  But it is still an issue I will
> revise the patch for such issues and remove it (maybe adding a
> #error if it used on powerpc64).

Ah whoops, I commented inline on the wrong file. The generic one
(sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h) also has the same
problem which is why I saw the RISC-V build fail.

>
> Besides it, does it work for riscv32 (which should use the default
> definition)?

This patch doesn't work due to the same name variables in a few places
(one of them being the generic one).

I am testing all the other patches and should know by tonight (about 8
hours still), I'll let you know.

Alistair

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

* Re: [PATCH 7/7] sysv: linux: Add 64-bit time_t variant for shmctl
  2020-07-01 15:48       ` Alistair Francis
@ 2020-07-01 16:35         ` Adhemerval Zanella
  2020-07-01 17:07           ` Adhemerval Zanella
  0 siblings, 1 reply; 41+ messages in thread
From: Adhemerval Zanella @ 2020-07-01 16:35 UTC (permalink / raw)
  To: Alistair Francis; +Cc: GNU C Library, Stepan Golosunov, Alistair Francis



On 01/07/2020 12:48, Alistair Francis wrote:
> On Wed, Jul 1, 2020 at 5:19 AM Adhemerval Zanella
> <adhemerval.zanella@linaro.org> wrote:
>>
>>
>>
>> On 30/06/2020 23:28, Alistair Francis wrote:
>> deps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
>>>> new file mode 100644
>>>> index 0000000000..5533d44dee
>>>> --- /dev/null
>>>> +++ b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
>>>> @@ -0,0 +1,24 @@
>>>> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
>>>> +struct kernel_shmid64_ds
>>>> +{
>>>> +  struct ipc_perm shm_perm;
>>>> +#if __TIMESIZE == 64
>>>> +  long int shm_atime;
>>>> +  long int shm_atime;
>>>> +  long int shm_atime;
>>>
>>> This fails to compile as all three variables have the same name.
>>
>> In fact this code specifically is not used on powerpc since it will
>> either use the __TIMESIZE == 32 (powerpc32) or not use this
>> structure at all (powerpc64{le}).  But it is still an issue I will
>> revise the patch for such issues and remove it (maybe adding a
>> #error if it used on powerpc64).
> 
> Ah whoops, I commented inline on the wrong file. The generic one
> (sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h) also has the same
> problem which is why I saw the RISC-V build fail.
> 
>>
>> Besides it, does it work for riscv32 (which should use the default
>> definition)?
> 
> This patch doesn't work due to the same name variables in a few places
> (one of them being the generic one).
> 

I need to setup an 32-bit ABI with 64-bit time_t to catch these kind of
issues.  

> I am testing all the other patches and should know by tonight (about 8
> hours still), I'll let you know.

Ack, you can also do a sniff test with the sysvipc tests to check if
they are ok.


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

* Re: [PATCH 7/7] sysv: linux: Add 64-bit time_t variant for shmctl
  2020-07-01 16:35         ` Adhemerval Zanella
@ 2020-07-01 17:07           ` Adhemerval Zanella
  2020-07-01 20:59             ` Vineet Gupta
  2020-07-01 23:00             ` Alistair Francis
  0 siblings, 2 replies; 41+ messages in thread
From: Adhemerval Zanella @ 2020-07-01 17:07 UTC (permalink / raw)
  To: Alistair Francis; +Cc: GNU C Library, Stepan Golosunov, Alistair Francis



On 01/07/2020 13:35, Adhemerval Zanella wrote:
> 
> 
> On 01/07/2020 12:48, Alistair Francis wrote:
>> On Wed, Jul 1, 2020 at 5:19 AM Adhemerval Zanella
>> <adhemerval.zanella@linaro.org> wrote:
>>>
>>>
>>>
>>> On 30/06/2020 23:28, Alistair Francis wrote:
>>> deps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
>>>>> new file mode 100644
>>>>> index 0000000000..5533d44dee
>>>>> --- /dev/null
>>>>> +++ b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
>>>>> @@ -0,0 +1,24 @@
>>>>> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
>>>>> +struct kernel_shmid64_ds
>>>>> +{
>>>>> +  struct ipc_perm shm_perm;
>>>>> +#if __TIMESIZE == 64
>>>>> +  long int shm_atime;
>>>>> +  long int shm_atime;
>>>>> +  long int shm_atime;
>>>>
>>>> This fails to compile as all three variables have the same name.
>>>
>>> In fact this code specifically is not used on powerpc since it will
>>> either use the __TIMESIZE == 32 (powerpc32) or not use this
>>> structure at all (powerpc64{le}).  But it is still an issue I will
>>> revise the patch for such issues and remove it (maybe adding a
>>> #error if it used on powerpc64).
>>
>> Ah whoops, I commented inline on the wrong file. The generic one
>> (sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h) also has the same
>> problem which is why I saw the RISC-V build fail.
>>
>>>
>>> Besides it, does it work for riscv32 (which should use the default
>>> definition)?
>>
>> This patch doesn't work due to the same name variables in a few places
>> (one of them being the generic one).
>>
> 
> I need to setup an 32-bit ABI with 64-bit time_t to catch these kind of
> issues.  
> 
>> I am testing all the other patches and should know by tonight (about 8
>> hours still), I'll let you know.
> 
> Ack, you can also do a sniff test with the sysvipc tests to check if
> they are ok.

Ok, the __TIMESIZE should not be used to define the kernel_* struct anyway,
they should be independent of the glibc time ABI selected or defined by
the ABI.

I have updated my personal branch [1] with an updated version and I will
try to check if riscv32 at least built against. If you could also check
it would be helpful.

[1] https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/azanella/semctl-y2038

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

* Re: [PATCH 7/7] sysv: linux: Add 64-bit time_t variant for shmctl
  2020-07-01 17:07           ` Adhemerval Zanella
@ 2020-07-01 20:59             ` Vineet Gupta
  2020-07-01 23:00             ` Alistair Francis
  1 sibling, 0 replies; 41+ messages in thread
From: Vineet Gupta @ 2020-07-01 20:59 UTC (permalink / raw)
  To: Adhemerval Zanella, Alistair Francis
  Cc: Stepan Golosunov, Alistair Francis, GNU C Library, arcml

On 7/1/20 10:07 AM, Adhemerval Zanella via Libc-alpha wrote:
>> Ack, you can also do a sniff test with the sysvipc tests to check if
>> they are ok.
> 
> Ok, the __TIMESIZE should not be used to define the kernel_* struct anyway,
> they should be independent of the glibc time ABI selected or defined by
> the ABI.
> 
> I have updated my personal branch [1] with an updated version and I will
> try to check if riscv32 at least built against. If you could also check
> it would be helpful.
> 
> [1] https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/azanella/semctl-y2038

I've rebased ARC port on this (dropped the prior versions from rv32) and these
seem to work !

| PASS: sysvipc/check-installed-headers-c
| PASS: sysvipc/check-installed-headers-cxx
| PASS: sysvipc/check-obsolete-constructs
| PASS: sysvipc/check-wrapper-headers
| PASS: sysvipc/test-sysvmsg
| PASS: sysvipc/test-sysvsem
| PASS: sysvipc/test-sysvshm

FWIW: Tested-by: Vineet Gupta <vgupta@synopsys.com>



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

* Re: [PATCH 7/7] sysv: linux: Add 64-bit time_t variant for shmctl
  2020-07-01 17:07           ` Adhemerval Zanella
  2020-07-01 20:59             ` Vineet Gupta
@ 2020-07-01 23:00             ` Alistair Francis
  2020-07-02 21:41               ` Alistair Francis
  1 sibling, 1 reply; 41+ messages in thread
From: Alistair Francis @ 2020-07-01 23:00 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: GNU C Library, Stepan Golosunov, Alistair Francis

On Wed, Jul 1, 2020 at 10:07 AM Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
>
>
>
> On 01/07/2020 13:35, Adhemerval Zanella wrote:
> >
> >
> > On 01/07/2020 12:48, Alistair Francis wrote:
> >> On Wed, Jul 1, 2020 at 5:19 AM Adhemerval Zanella
> >> <adhemerval.zanella@linaro.org> wrote:
> >>>
> >>>
> >>>
> >>> On 30/06/2020 23:28, Alistair Francis wrote:
> >>> deps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
> >>>>> new file mode 100644
> >>>>> index 0000000000..5533d44dee
> >>>>> --- /dev/null
> >>>>> +++ b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
> >>>>> @@ -0,0 +1,24 @@
> >>>>> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
> >>>>> +struct kernel_shmid64_ds
> >>>>> +{
> >>>>> +  struct ipc_perm shm_perm;
> >>>>> +#if __TIMESIZE == 64
> >>>>> +  long int shm_atime;
> >>>>> +  long int shm_atime;
> >>>>> +  long int shm_atime;
> >>>>
> >>>> This fails to compile as all three variables have the same name.
> >>>
> >>> In fact this code specifically is not used on powerpc since it will
> >>> either use the __TIMESIZE == 32 (powerpc32) or not use this
> >>> structure at all (powerpc64{le}).  But it is still an issue I will
> >>> revise the patch for such issues and remove it (maybe adding a
> >>> #error if it used on powerpc64).
> >>
> >> Ah whoops, I commented inline on the wrong file. The generic one
> >> (sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h) also has the same
> >> problem which is why I saw the RISC-V build fail.
> >>
> >>>
> >>> Besides it, does it work for riscv32 (which should use the default
> >>> definition)?
> >>
> >> This patch doesn't work due to the same name variables in a few places
> >> (one of them being the generic one).
> >>
> >
> > I need to setup an 32-bit ABI with 64-bit time_t to catch these kind of
> > issues.
> >
> >> I am testing all the other patches and should know by tonight (about 8
> >> hours still), I'll let you know.
> >
> > Ack, you can also do a sniff test with the sysvipc tests to check if
> > they are ok.
>
> Ok, the __TIMESIZE should not be used to define the kernel_* struct anyway,
> they should be independent of the glibc time ABI selected or defined by
> the ABI.
>
> I have updated my personal branch [1] with an updated version and I will
> try to check if riscv32 at least built against. If you could also check
> it would be helpful.

Thanks!

I have tested this series with patch 7 (this patch) dropped and it
works for RV32.

>
> [1] https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/azanella/semctl-y2038

I am now running a full test of this branch, unfortunately it'll take
about 24 hours.

Alistair

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

* Re: [PATCH 1/7] sysv: linux: Add 64-bit time_t variant for semctl
  2020-06-30 19:24 [PATCH 1/7] sysv: linux: Add 64-bit time_t variant for semctl Adhemerval Zanella
                   ` (5 preceding siblings ...)
  2020-06-30 19:24 ` [PATCH 7/7] sysv: linux: Add 64-bit time_t variant for shmctl Adhemerval Zanella
@ 2020-07-02 19:01 ` Alistair Francis
  2020-07-07  3:32 ` Carlos O'Donell
  7 siblings, 0 replies; 41+ messages in thread
From: Alistair Francis @ 2020-07-02 19:01 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: GNU C Library, Stepan Golosunov, Alistair Francis

On Tue, Jun 30, 2020 at 12:26 PM Adhemerval Zanella via Libc-alpha
<libc-alpha@sourceware.org> wrote:
>
> Different than others 64-bit time_t syscalls, the SysIPC interface
> does not provide a new set of syscall for y2038 safeness.  Instead it
> uses ununsed fields in semid_ds structure the return the high bits for
> the timestamps.
>
> To provide a y2038 safe interface a new symbol __semctl64 is added
> and __semctl is change to call it instead (it adds some extra buffer
> copy for the 32 bit time_t implementation).
>
> Two two new structures are added:
>
>   1. kernel_semid64_ds: used internally only on 32-bit architectures
>      to issue the syscall.  A handful architectures (hppa, i386, mips,
>      powerpc32, sparc32) requires specific implementation due its
>      specific kernel ABI.
>
>   2. semid_ds64: this is only for __TIMESIZE != 64 to use along with
>      the 64-bit semctl.  It is different than the kernel one because
>      the exported 64-bit time_t might require different alignment
>      depending of the architecture ABI.
>
> So the resulting implementation does:
>
>   1. For 64-bit architectures it assumes semid_ds already contains
>      64-bit time_t fields it will result in just the __semctl symbol
>      using the __semctl64 code.  The semid_ds argument is passed as-is
>      to the syscall.
>
>   2. For 32-bit architectures with default 64-bit time_t (newer ABIs
>      such riscv32 or arc), it will also result in only one exported
>      symbol but with the required high/low handling.
>
>      It might be possible to optimize it further to avoid the
>      kernel_semid64_ds to semun transformation if the exported ABI
>      for the architectures matches the expected kernel ABI, but the
>      implementation is already complex enough and don't think this
>      should be a hotspot in any case.
>
>   3. Finally for 32-bit architecture with both 32-bit and 64-bit time_t
>      support we follow the already set way to provide one symbol with
>      64-bit time_t support and implement the 32-bit time_t support on
>      basis of the 64-bit one.
>
>      The default 32-bit symbol will allocate and copy the semid_ds
>      over multiple buffers, but this should be deprecated in favor
>      of the __semctl64 anyway.
>
> Checked on i686-linux-gnu and x86_64-linux-gnu.  I also did some sniff
> tests on powerpc, powerpc64, mips, mips64, armhf, sparcv9, and
> sparc64.

This looks good.

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  include/sys/sem.h                             |   7 +
>  .../sysv/linux/bits/types/struct_semid64_ds.h |  33 +++
>  .../sysv/linux/bits/types/struct_semid_ds.h   |  21 +-
>  .../linux/hppa/bits/types/struct_semid_ds.h   |   6 +-
>  .../linux/hppa/struct_kernel_semid64_ds.h     |  12 +
>  .../linux/i386/struct_kernel_semid64_ds.h     |  12 +
>  sysdeps/unix/sysv/linux/ipc_priv.h            |  10 +
>  .../linux/mips/bits/types/struct_semid_ds.h   |   4 +-
>  .../linux/mips/struct_kernel_semid64_ds.h     |  10 +
>  .../powerpc/bits/types/struct_semid_ds.h      |   4 +-
>  .../powerpc32/struct_kernel_semid64_ds.h      |  12 +
>  sysdeps/unix/sysv/linux/semctl.c              | 261 +++++++++++++++---
>  .../linux/sparc/bits/types/struct_semid_ds.h  |   4 +-
>  .../sparc/sparc32/struct_kernel_semid64_ds.h  |  12 +
>  .../sysv/linux/struct_kernel_semid64_ds.h     |  12 +
>  .../linux/x86/bits/types/struct_semid_ds.h    |   4 +-
>  16 files changed, 359 insertions(+), 65 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_semid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/hppa/struct_kernel_semid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/i386/struct_kernel_semid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/mips/struct_kernel_semid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_semid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_semid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/struct_kernel_semid64_ds.h
>
> diff --git a/include/sys/sem.h b/include/sys/sem.h
> index 69fdf1f752..a9151e057d 100644
> --- a/include/sys/sem.h
> +++ b/include/sys/sem.h
> @@ -5,5 +5,12 @@
>
>  __typeof__ (semtimedop) __semtimedop attribute_hidden;
>
> +#if __TIMESIZE == 64
> +# define __semctl64 __semctl
> +#else
> +extern int __semctl64 (int semid, int semnum, int cmd, ...);
> +libc_hidden_proto (__semctl64);
> +#endif
> +
>  # endif
>  #endif
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_semid64_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_semid64_ds.h
> new file mode 100644
> index 0000000000..bda9eb4469
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_semid64_ds.h
> @@ -0,0 +1,33 @@
> +/* Generic implementation of the semaphore struct semid64_ds.
> +   Copyright (C) 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 __TIMESIZE == 64
> +# define __semid64_ds semid_ds
> +#else
> +struct __semid64_ds
> +{
> +  struct ipc_perm sem_perm;            /* operation permission struct */
> +  __time64_t sem_otime;                        /* last semop() time */
> +  __time64_t sem_ctime;                        /* last time changed by semctl() */
> +  __syscall_ulong_t sem_nsems;         /* number of semaphores in set */
> +};
> +#endif
> 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 4222e6a59f..bc26d8be08 100644
> --- a/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h
> @@ -21,26 +21,19 @@
>  #endif
>
>  /* Data structure describing a set of semaphores.  */
> -#if __TIMESIZE == 32
>  struct semid_ds
>  {
>    struct ipc_perm sem_perm;        /* operation permission struct */
> +#if __TIMESIZE == 32
>    __time_t sem_otime;              /* last semop() time */
> -  __syscall_ulong_t __glibc_reserved1;
> +  __syscall_ulong_t __sem_otime_high;
>    __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;
> -};
> +  __syscall_ulong_t __sem_ctime_high;
>  #else
> -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 */
> +  __time_t sem_otime;
> +  __time_t sem_ctime;
> +#endif
> +  __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/hppa/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_semid_ds.h
> index d4c50b5ef8..68f9eca24c 100644
> --- a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_semid_ds.h
> +++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_semid_ds.h
> @@ -21,16 +21,14 @@
>  #endif
>
>  /* 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;
> +  __syscall_ulong_t __sem_otime_high;
>    __time_t sem_otime;         /* last semop() time */
> -  __syscall_ulong_t __glibc_reserved2;
> +  __syscall_ulong_t __sem_ctime_high;
>    __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/hppa/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/hppa/struct_kernel_semid64_ds.h
> new file mode 100644
> index 0000000000..2871030d0d
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/hppa/struct_kernel_semid64_ds.h
> @@ -0,0 +1,12 @@
> +/* Analogous to kernel struct semid64_ds used on semctl.  */
> +struct kernel_semid64_ds
> +{
> +  struct ipc_perm sem_perm;
> +  unsigned long sem_otime_high;
> +  unsigned long sem_otime;
> +  unsigned long sem_ctime_high;
> +  unsigned long sem_ctime;
> +  unsigned long sem_nsems;
> +  unsigned long __ununsed1;
> +  unsigned long __ununsed2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/i386/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/i386/struct_kernel_semid64_ds.h
> new file mode 100644
> index 0000000000..bab9cf63ba
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/i386/struct_kernel_semid64_ds.h
> @@ -0,0 +1,12 @@
> +/* Analogous to kernel struct semid64_ds used on semctl.  */
> +struct kernel_semid64_ds
> +{
> +  struct ipc_perm sem_perm;
> +  unsigned long sem_otime;
> +  unsigned long sem_otime_high;
> +  unsigned long sem_ctime;
> +  unsigned long sem_ctime_high;
> +  __syscall_ulong_t sem_nsems;
> +  __syscall_ulong_t __unused3;
> +  __syscall_ulong_t __unused4;
> +};
> diff --git a/sysdeps/unix/sysv/linux/ipc_priv.h b/sysdeps/unix/sysv/linux/ipc_priv.h
> index 15a6e683a4..93a6e5cb24 100644
> --- a/sysdeps/unix/sysv/linux/ipc_priv.h
> +++ b/sysdeps/unix/sysv/linux/ipc_priv.h
> @@ -53,4 +53,14 @@ struct __old_ipc_perm
>  #define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
>    (__nsops), 0, (__sops), (__timeout)
>
> +/* Linux SysV ipc does not provide new syscalls for 64-bit time support on
> +   32-bit architectures, but rather split the timestamps on previous unused
> +   fields.  */
> +#if (__WORDSIZE == 32 \
> +     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
> +# define __IPC_TIME64 1
> +#else
> +# define __IPC_TIME64 0
> +#endif
> +
>  #include <ipc_ops.h>
> diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h
> index 8954209a29..eec4a18cae 100644
> --- a/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h
> +++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h
> @@ -27,6 +27,6 @@ struct semid_ds
>    __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;
> +  __syscall_ulong_t __sem_otime_high;
> +  __syscall_ulong_t __sem_ctime_high;
>  };
> diff --git a/sysdeps/unix/sysv/linux/mips/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/mips/struct_kernel_semid64_ds.h
> new file mode 100644
> index 0000000000..76a9d83ea5
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/struct_kernel_semid64_ds.h
> @@ -0,0 +1,10 @@
> +/* Analogous to kernel struct semid64_ds used on semctl.  */
> +struct kernel_semid64_ds
> +{
> +  struct ipc_perm sem_perm;
> +  unsigned long sem_otime;
> +  unsigned long sem_ctime;
> +  unsigned long sem_nsems;
> +  unsigned long sem_otime_high;
> +  unsigned long sem_ctime_high;
> +};
> 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
> index 300a9b98e9..d382d93c52 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_semid_ds.h
> +++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_semid_ds.h
> @@ -25,9 +25,9 @@ struct semid_ds
>  {
>    struct ipc_perm sem_perm;   /* operation permission struct */
>  #if __TIMESIZE == 32
> -  __syscall_ulong_t __glibc_reserved1;
> +  __syscall_ulong_t __sem_otime_high;
>    __time_t sem_otime;         /* last semop() time */
> -  __syscall_ulong_t __glibc_reserved2;
> +  __syscall_ulong_t __sem_ctime_high;
>    __time_t sem_ctime;        /* last time changed by semctl() */
>  #else
>    __time_t sem_otime;         /* last semop() time */
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_semid64_ds.h
> new file mode 100644
> index 0000000000..7fa4ef6424
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_semid64_ds.h
> @@ -0,0 +1,12 @@
> +/* Analogous to kernel struct semid64_ds used on semctl.  */
> +struct kernel_semid64_ds
> +{
> +  struct ipc_perm sem_perm;
> +  unsigned long sem_otime_high;
> +  unsigned long sem_otime;
> +  unsigned long sem_ctime_high;
> +  unsigned long sem_ctime;
> +  unsigned long sem_nsems;
> +  unsigned long __unused3;
> +  unsigned long __unused4;
> +};
> diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c
> index 30571af49f..3a06270242 100644
> --- a/sysdeps/unix/sysv/linux/semctl.c
> +++ b/sysdeps/unix/sysv/linux/semctl.c
> @@ -21,10 +21,13 @@
>  #include <ipc_priv.h>
>  #include <sysdep.h>
>  #include <shlib-compat.h>
> -#include <errno.h>
> -#include <linux/posix_types.h>  /* For __kernel_mode_t.  */
> +#include <bits/types/struct_semid64_ds.h>  /* For __semid64_ds.  */
> +#include <linux/posix_types.h>             /* For __kernel_mode_t.  */
>
> -/* Define a `union semun' suitable for Linux here.  */
> +/* The struct used to issue the syscall.  For architecture that assume
> +   64-bit time as default (!__ASSUME_TIME64_SYSCALLS) the syscall will
> +   split the resulting 64-bit sem_{o,c}time in two fields (__sem_{o,c}time
> +   and __sem_{o,c}time_hi).  */
>  union semun
>  {
>    int val;                     /* value for SETVAL */
> @@ -33,16 +36,89 @@ union semun
>    struct seminfo *__buf;       /* buffer for IPC_INFO */
>  };
>
> -#ifndef DEFAULT_VERSION
> -# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -#  define DEFAULT_VERSION GLIBC_2_2
> +#if __IPC_TIME64 == 0
> +# define semun64 semun
> +typedef union semun semctl_arg_t;
> +#else
> +# include <struct_kernel_semid64_ds.h>
> +
> +union ksemun64
> +{
> +  int val;
> +  struct kernel_semid64_ds *buf;
> +  unsigned short int *array;
> +  struct seminfo *__buf;
> +};
> +
> +# if __TIMESIZE == 64
> +#  define semun64 semun
>  # else
> -#  define DEFAULT_VERSION GLIBC_2_31
> +/* The struct used when __semctl64 is called.  */
> +union semun64
> +{
> +  int val;
> +  struct __semid64_ds *buf;
> +  unsigned short int *array;
> +  struct seminfo *__buf;
> +};
>  # endif
> +
> +static void
> +semid64_to_ksemid64 (const struct __semid64_ds *semid64,
> +                    struct kernel_semid64_ds *ksemid)
> +{
> +  ksemid->sem_perm       = semid64->sem_perm;
> +  ksemid->sem_otime      = semid64->sem_otime;
> +  ksemid->sem_otime_high = semid64->sem_otime >> 32;
> +  ksemid->sem_ctime      = semid64->sem_ctime;
> +  ksemid->sem_ctime_high = semid64->sem_ctime >> 32;
> +  ksemid->sem_nsems      = semid64->sem_nsems;
> +}
> +
> +static void
> +ksemid64_to_semid64 (const struct kernel_semid64_ds *ksemid,
> +                    struct __semid64_ds *semid64)
> +{
> +  semid64->sem_perm  = ksemid->sem_perm;
> +  semid64->sem_otime = ksemid->sem_otime
> +                      | ((__time64_t) ksemid->sem_otime_high << 32);
> +  semid64->sem_ctime = ksemid->sem_ctime
> +                      | ((__time64_t) ksemid->sem_ctime_high << 32);
> +  semid64->sem_nsems = ksemid->sem_nsems;
> +}
> +
> +static union ksemun64
> +semun64_to_ksemun64 (int cmd, union semun64 semun64,
> +                    struct kernel_semid64_ds *buf)
> +{
> +  union ksemun64 r = { 0 };
> +  switch (cmd)
> +    {
> +    case SETVAL:
> +      r.val = semun64.val;
> +      break;
> +    case GETALL:
> +    case SETALL:
> +      r.array = semun64.array;
> +      break;
> +    case IPC_STAT:
> +    case IPC_SET:
> +      r.buf = buf;
> +      semid64_to_ksemid64 (semun64.buf, r.buf);
> +      break;
> +    case IPC_INFO:
> +    case SEM_INFO:
> +      r.__buf = semun64.__buf;
> +      break;
> +    }
> +  return r;
> +}
> +
> +typedef union ksemun64 semctl_arg_t;
>  #endif
>
>  static int
> -semctl_syscall (int semid, int semnum, int cmd, union semun arg)
> +semctl_syscall (int semid, int semnum, int cmd, semctl_arg_t arg)
>  {
>  #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
>    return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64,
> @@ -53,15 +129,15 @@ semctl_syscall (int semid, int semnum, int cmd, union semun arg)
>  #endif
>  }
>
> +/* 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)");
> +
>  int
> -__new_semctl (int semid, int semnum, int cmd, ...)
> +__semctl64 (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 };
> +  union semun64 arg64 = { 0 };
>    va_list ap;
>
>    /* Get the argument only if required.  */
> @@ -76,44 +152,151 @@ __new_semctl (int semid, int semnum, int cmd, ...)
>      case IPC_INFO:      /* arg.__buf */
>      case SEM_INFO:
>        va_start (ap, cmd);
> -      arg = va_arg (ap, union semun);
> +      arg64 = va_arg (ap, union semun64);
>        va_end (ap);
>        break;
>      }
>
> -#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;
> -    }
> +#if __IPC_TIME64
> +  struct kernel_semid64_ds ksemid;
> +  union ksemun64 ksemun = semun64_to_ksemun64 (cmd, arg64, &ksemid);
> +  union ksemun64 arg = ksemun;
> +#else
> +  union semun arg = arg64;
>  #endif
>
>    int ret = semctl_syscall (semid, semnum, cmd, arg);
> +  if (ret < 0)
> +    return ret;
>
> -  if (ret >= 0)
> +  switch (cmd)
>      {
> -      switch (cmd)
> -       {
> -        case IPC_STAT:
> -        case SEM_STAT:
> -        case SEM_STAT_ANY:
> +    case IPC_STAT:
> +    case SEM_STAT:
> +    case SEM_STAT_ANY:
>  #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -          arg.buf->sem_perm.mode >>= 16;
> +      arg.buf->sem_perm.mode >>= 16;
>  #else
> -         /* Old Linux kernel versions might not clear the mode padding.  */
> -         if (sizeof ((struct semid_ds){0}.sem_perm.mode)
> -             != sizeof (__kernel_mode_t))
> -           arg.buf->sem_perm.mode &= 0xFFFF;
> +      /* Old Linux kernel versions might not clear the mode padding.  */
> +      if (sizeof ((struct semid_ds){0}.sem_perm.mode)
> +         != sizeof (__kernel_mode_t))
> +       arg.buf->sem_perm.mode &= 0xFFFF;
>  #endif
> -       }
> +
> +#if __IPC_TIME64
> +      ksemid64_to_semid64 (arg.buf, arg64.buf);
> +#endif
> +    }
> +
> +  return ret;
> +}
> +#if __TIMESIZE != 64
> +libc_hidden_def (__semctl64)
> +
> +
> +/* The 64-bit time_t semid_ds version might have a different layout and
> +   internal field alignment.  */
> +static void
> +semid64_ds_to_semid_ds (struct semid_ds *ds, const struct __semid64_ds *ds64)
> +{
> +  ds->sem_perm = ds64->sem_perm;
> +  ds->sem_otime = ds64->sem_otime;
> +  ds->sem_ctime = ds64->sem_ctime;
> +  ds->sem_nsems = ds64->sem_nsems;
> +}
> +
> +static void
> +semid_ds_to_semid64_ds (struct __semid64_ds *ds64, const struct semid_ds *ds)
> +{
> +  ds64->sem_perm = ds->sem_perm;
> +  ds64->sem_otime = ds->sem_otime
> +                   | ((__time64_t) ds->__sem_otime_high << 32);
> +  ds64->sem_ctime = ds->sem_ctime
> +                   | ((__time64_t) ds->__sem_ctime_high << 32);
> +  ds64->sem_nsems = ds->sem_nsems;
> +}
> +
> +static union semun64
> +semun_to_semun64 (int cmd, union semun semun, struct __semid64_ds *semid64)
> +{
> +  union semun64 r = { 0 };
> +  switch (cmd)
> +    {
> +    case SETVAL:
> +      r.val = semun.val;
> +      break;
> +    case GETALL:
> +    case SETALL:
> +      r.array = semun.array;
> +      break;
> +    case IPC_STAT:
> +    case IPC_SET:
> +      r.buf = semid64;
> +      semid_ds_to_semid64_ds (r.buf, semun.buf);
> +# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> +      if (cmd == IPC_SET)
> +       r.buf->sem_perm.mode *= 0x10000U;
> +# endif
> +      break;
> +    case IPC_INFO:
> +    case SEM_INFO:
> +      r.__buf = semun.__buf;
> +      break;
> +    }
> +  return r;
> +}
> +
> +int
> +__semctl (int semid, int semnum, int cmd, ...)
> +{
> +  union semun arg = { 0 };
> +
> +  va_list ap;
> +
> +  /* Get the argument only if required.  */
> +  switch (cmd)
> +    {
> +    case SETVAL:        /* arg.val */
> +    case GETALL:        /* arg.array */
> +    case SETALL:
> +    case IPC_STAT:      /* arg.buf */
> +    case IPC_SET:
> +    case SEM_STAT:
> +    case IPC_INFO:      /* arg.__buf */
> +    case SEM_INFO:
> +      va_start (ap, cmd);
> +      arg = va_arg (ap, union semun);
> +      va_end (ap);
> +      break;
> +    }
> +
> +  struct __semid64_ds semid64;
> +  union semun64 arg64 = semun_to_semun64 (cmd, arg, &semid64);
> +
> +  int ret = __semctl64 (semid, semnum, cmd, arg64);
> +  if (ret < 0)
> +    return ret;
> +
> +  switch (cmd)
> +    {
> +    case IPC_STAT:
> +    case SEM_STAT:
> +    case SEM_STAT_ANY:
> +      semid64_ds_to_semid_ds (arg.buf, arg64.buf);
>      }
>
>    return ret;
>  }
> -versioned_symbol (libc, __new_semctl, semctl, DEFAULT_VERSION);
> +#endif
> +
> +#ifndef DEFAULT_VERSION
> +# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
> +#  define DEFAULT_VERSION GLIBC_2_2
> +# else
> +#  define DEFAULT_VERSION GLIBC_2_31
> +# endif
> +#endif
> +versioned_symbol (libc, __semctl, semctl, DEFAULT_VERSION);
>
>  #if defined __ASSUME_SYSVIPC_BROKEN_MODE_T \
>      && SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_31)
> @@ -121,7 +304,7 @@ int
>  attribute_compat_text_section
>  __semctl_mode16 (int semid, int semnum, int cmd, ...)
>  {
> -  union semun arg = { 0 };
> +  semctl_arg_t arg = { 0 };
>    va_list ap;
>
>    /* Get the argument only if required.  */
> @@ -136,7 +319,7 @@ __semctl_mode16 (int semid, int semnum, int cmd, ...)
>      case IPC_INFO:      /* arg.__buf */
>      case SEM_INFO:
>        va_start (ap, cmd);
> -      arg = va_arg (ap, union semun);
> +      arg = va_arg (ap, semctl_arg_t);
>        va_end (ap);
>        break;
>      }
> 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
> index 46fcd79fb6..0110c1a940 100644
> --- a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_semid_ds.h
> +++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_semid_ds.h
> @@ -25,9 +25,9 @@ struct semid_ds
>  {
>    struct ipc_perm sem_perm;   /* operation permission struct */
>  #if __TIMESIZE == 32
> -  __syscall_ulong_t __glibc_reserved1;
> +  __syscall_ulong_t __sem_otime_high;
>    __time_t sem_otime;         /* last semop() time */
> -  __syscall_ulong_t __glibc_reserved2;
> +  __syscall_ulong_t __sem_ctime_high;
>    __time_t sem_ctime;        /* last time changed by semctl() */
>  #else
>    __time_t sem_otime;         /* last semop() time */
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_semid64_ds.h
> new file mode 100644
> index 0000000000..8c4697f9ab
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_semid64_ds.h
> @@ -0,0 +1,12 @@
> +/* Analogous to kernel struct semid64_ds used on semctl.  */
> +struct kernel_semid64_ds
> +{
> +  struct ipc_perm sem_perm;
> +  unsigned long sem_otime_high;
> +  unsigned long sem_otime;
> +  unsigned long sem_ctime_high;
> +  unsigned long sem_ctime;
> +  unsigned long sem_nsems;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/struct_kernel_semid64_ds.h
> new file mode 100644
> index 0000000000..f9edf0f76f
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/struct_kernel_semid64_ds.h
> @@ -0,0 +1,12 @@
> +/* Analogous to kernel struct semid64_ds used on semctl.  */
> +struct kernel_semid64_ds
> +{
> +  struct ipc_perm sem_perm;
> +  unsigned long sem_otime;
> +  unsigned long sem_otime_high;
> +  unsigned long sem_ctime;
> +  unsigned long sem_ctime_high;
> +  unsigned long sem_nsems;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h
> index f7ec89d115..c3f2fde9fd 100644
> --- a/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h
> +++ b/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h
> @@ -25,9 +25,9 @@ struct semid_ds
>  {
>    struct ipc_perm sem_perm;   /* operation permission struct */
>    __time_t sem_otime;  /* last semop() time */
> -  __syscall_ulong_t __glibc_reserved1;
> +  __syscall_ulong_t __sem_otime_high;
>    __time_t sem_ctime;  /* last time changed by semctl() */
> -  __syscall_ulong_t __glibc_reserved2;
> +  __syscall_ulong_t __sem_ctime_high;
>    __syscall_ulong_t sem_nsems;    /* number of semaphores in set */
>    __syscall_ulong_t __glibc_reserved3;
>    __syscall_ulong_t __glibc_reserved4;
> --
> 2.25.1
>

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

* Re: [PATCH 2/7] sysvipc: Split out linux struct semid_ds
  2020-06-30 19:24 ` [PATCH 2/7] sysvipc: Split out linux struct semid_ds Adhemerval Zanella
@ 2020-07-02 21:20   ` Alistair Francis
  2020-07-07 19:01   ` Carlos O'Donell
  1 sibling, 0 replies; 41+ messages in thread
From: Alistair Francis @ 2020-07-02 21:20 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: GNU C Library, Stepan Golosunov, Alistair Francis

On Tue, Jun 30, 2020 at 12:24 PM Adhemerval Zanella via Libc-alpha
<libc-alpha@sourceware.org> wrote:
>
> This will allow us to have architectures specify their own version.
>
> Not semantic changes expected.  Checked with a build against the
> all affected ABIs.

I have the exact same patch in my tree, looks good.

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  sysdeps/unix/sysv/linux/Makefile              |  1 +
>  sysdeps/unix/sysv/linux/bits/msq.h            | 39 +++-----------
>  .../sysv/linux/bits/types/struct_msqid_ds.h   | 51 +++++++++++++++++++
>  3 files changed, 58 insertions(+), 33 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
>
> diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
> index e02065dc8d..70e2d9e044 100644
> --- a/sysdeps/unix/sysv/linux/Makefile
> +++ b/sysdeps/unix/sysv/linux/Makefile
> @@ -92,6 +92,7 @@ sysdep_headers += sys/mount.h sys/acct.h \
>                   bits/termios-c_lflag.h bits/termios-tcflow.h \
>                   bits/termios-misc.h \
>                   bits/types/struct_semid_ds.h \
> +                 bits/types/struct_msqid_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/msq.h b/sysdeps/unix/sysv/linux/bits/msq.h
> index cc4ebae0f0..6ce6408ebc 100644
> --- a/sysdeps/unix/sysv/linux/bits/msq.h
> +++ b/sysdeps/unix/sysv/linux/bits/msq.h
> @@ -20,7 +20,12 @@
>  #endif
>
>  #include <bits/types.h>
> -#include <bits/msq-pad.h>
> +
> +/* Types used in the MSQID_DS structure definition.  */
> +typedef __syscall_ulong_t msgqnum_t;
> +typedef __syscall_ulong_t msglen_t;
> +
> +#include <bits/types/struct_msqid_ds.h>
>
>  /* Define options for message queue functions.  */
>  #define MSG_NOERROR    010000  /* no error if message is too big */
> @@ -29,38 +34,6 @@
>  # define MSG_COPY      040000  /* copy (not remove) all queue messages */
>  #endif
>
> -/* Types used in the structure definition.  */
> -typedef __syscall_ulong_t msgqnum_t;
> -typedef __syscall_ulong_t msglen_t;
> -
> -#if __MSQ_PAD_BEFORE_TIME
> -# define __MSQ_PAD_TIME(NAME, RES)                             \
> -  unsigned long int __glibc_reserved ## RES; __time_t NAME
> -#elif __MSQ_PAD_AFTER_TIME
> -# define __MSQ_PAD_TIME(NAME, RES)                             \
> -  __time_t NAME; unsigned long int __glibc_reserved ## RES
> -#else
> -# define __MSQ_PAD_TIME(NAME, RES)             \
> -  __time_t NAME
> -#endif
> -
> -/* Structure of record for one message inside the kernel.
> -   The type `struct msg' is opaque.  */
> -struct msqid_ds
> -{
> -  struct ipc_perm msg_perm;    /* structure describing operation permission */
> -  __MSQ_PAD_TIME (msg_stime, 1);       /* time of last msgsnd command */
> -  __MSQ_PAD_TIME (msg_rtime, 2);       /* time of last msgrcv command */
> -  __MSQ_PAD_TIME (msg_ctime, 3);       /* time of last change */
> -  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
> -  msgqnum_t msg_qnum;          /* number of messages currently on queue */
> -  msglen_t msg_qbytes;         /* max number of bytes allowed on queue */
> -  __pid_t msg_lspid;           /* pid of last msgsnd() */
> -  __pid_t msg_lrpid;           /* pid of last msgrcv() */
> -  __syscall_ulong_t __glibc_reserved4;
> -  __syscall_ulong_t __glibc_reserved5;
> -};
> -
>  #ifdef __USE_MISC
>
>  # define msg_cbytes    __msg_cbytes
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> new file mode 100644
> index 0000000000..bfc56f6ac1
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> @@ -0,0 +1,51 @@
> +/* Generic implementation of the SysV message struct msqid_ds.
> +   Copyright (C) 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_MSG_H
> +# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
> +#endif
> +
> +#include <bits/msq-pad.h>
> +
> +#if __MSQ_PAD_BEFORE_TIME
> +# define __MSQ_PAD_TIME(NAME, RES)                             \
> +  unsigned long int __glibc_reserved ## RES; __time_t NAME
> +#elif __MSQ_PAD_AFTER_TIME
> +# define __MSQ_PAD_TIME(NAME, RES)                             \
> +  __time_t NAME; unsigned long int __glibc_reserved ## RES
> +#else
> +# define __MSQ_PAD_TIME(NAME, RES)             \
> +  __time_t NAME
> +#endif
> +
> +/* Structure of record for one message inside the kernel.
> +   The type `struct msg' is opaque.  */
> +struct msqid_ds
> +{
> +  struct ipc_perm msg_perm;    /* structure describing operation permission */
> +  __MSQ_PAD_TIME (msg_stime, 1);       /* time of last msgsnd command */
> +  __MSQ_PAD_TIME (msg_rtime, 2);       /* time of last msgrcv command */
> +  __MSQ_PAD_TIME (msg_ctime, 3);       /* time of last change */
> +  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
> +  msgqnum_t msg_qnum;          /* number of messages currently on queue */
> +  msglen_t msg_qbytes;         /* max number of bytes allowed on queue */
> +  __pid_t msg_lspid;           /* pid of last msgsnd() */
> +  __pid_t msg_lrpid;           /* pid of last msgrcv() */
> +  __syscall_ulong_t __glibc_reserved4;
> +  __syscall_ulong_t __glibc_reserved5;
> +};
> --
> 2.25.1
>

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

* Re: [PATCH 3/7] sysvipc: Remove the linux msq-pad.h file
  2020-06-30 19:24 ` [PATCH 3/7] sysvipc: Remove the linux msq-pad.h file Adhemerval Zanella
@ 2020-07-02 21:26   ` Alistair Francis
  2020-07-07 19:05   ` Carlos O'Donell
  1 sibling, 0 replies; 41+ messages in thread
From: Alistair Francis @ 2020-07-02 21:26 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: GNU C Library, Stepan Golosunov, Alistair Francis

On Tue, Jun 30, 2020 at 12:25 PM Adhemerval Zanella via Libc-alpha
<libc-alpha@sourceware.org> wrote:
>
> Each architecture overrides the struct msqid_ds which its required
> kernel ABI one.
>
> Checked on x86_64-linux-gnu and some bases sysvipc tests on hppa,
> mips, mipsle, mips64, mips64le, sparc64, sparcv9, powerpc64le,
> powerpc64, and powerpc.
> ---
>  sysdeps/unix/sysv/linux/Makefile              |  2 +-
>  sysdeps/unix/sysv/linux/bits/msq-pad.h        | 31 ----------
>  .../sysv/linux/bits/types/struct_msqid_ds.h   | 28 ++++------
>  sysdeps/unix/sysv/linux/hppa/bits/msq-pad.h   | 26 ---------
>  .../linux/hppa/bits/types/struct_msqid_ds.h   | 47 ++++++++++++++++
>  sysdeps/unix/sysv/linux/mips/bits/msq-pad.h   | 31 ----------
>  .../linux/mips/bits/types/struct_msqid_ds.h   | 56 +++++++++++++++++++
>  .../unix/sysv/linux/powerpc/bits/msq-pad.h    | 26 ---------
>  .../powerpc/bits/types/struct_msqid_ds.h      | 47 ++++++++++++++++
>  sysdeps/unix/sysv/linux/sparc/bits/msq-pad.h  | 26 ---------
>  .../linux/sparc/bits/types/struct_msqid_ds.h  | 47 ++++++++++++++++
>  11 files changed, 210 insertions(+), 157 deletions(-)
>  delete mode 100644 sysdeps/unix/sysv/linux/bits/msq-pad.h
>  delete mode 100644 sysdeps/unix/sysv/linux/hppa/bits/msq-pad.h
>  create mode 100644 sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
>  delete mode 100644 sysdeps/unix/sysv/linux/mips/bits/msq-pad.h
>  create mode 100644 sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
>  delete mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/msq-pad.h
>  create mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
>  delete mode 100644 sysdeps/unix/sysv/linux/sparc/bits/msq-pad.h
>  create mode 100644 sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
>
> diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
> index 70e2d9e044..505087e617 100644
> --- a/sysdeps/unix/sysv/linux/Makefile
> +++ b/sysdeps/unix/sysv/linux/Makefile
> @@ -85,7 +85,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/shmlba.h bits/shm-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/msq-pad.h b/sysdeps/unix/sysv/linux/bits/msq-pad.h
> deleted file mode 100644
> index e4ffd39f27..0000000000
> --- a/sysdeps/unix/sysv/linux/bits/msq-pad.h
> +++ /dev/null
> @@ -1,31 +0,0 @@
> -/* Define where padding goes in struct msqid_ds.  Generic 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_MSG_H
> -# error "Never use <bits/msq-pad.h> directly; include <sys/msg.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.  */
> -
> -#define __MSQ_PAD_AFTER_TIME (__TIMESIZE == 32)
> -#define __MSQ_PAD_BEFORE_TIME 0
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> index bfc56f6ac1..32173a7b60 100644
> --- a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> @@ -20,27 +20,23 @@
>  # error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
>  #endif
>
> -#include <bits/msq-pad.h>
> -
> -#if __MSQ_PAD_BEFORE_TIME
> -# define __MSQ_PAD_TIME(NAME, RES)                             \
> -  unsigned long int __glibc_reserved ## RES; __time_t NAME
> -#elif __MSQ_PAD_AFTER_TIME
> -# define __MSQ_PAD_TIME(NAME, RES)                             \
> -  __time_t NAME; unsigned long int __glibc_reserved ## RES
> -#else
> -# define __MSQ_PAD_TIME(NAME, RES)             \
> -  __time_t NAME
> -#endif
> -
>  /* Structure of record for one message inside the kernel.
>     The type `struct msg' is opaque.  */
>  struct msqid_ds
>  {
>    struct ipc_perm msg_perm;    /* structure describing operation permission */
> -  __MSQ_PAD_TIME (msg_stime, 1);       /* time of last msgsnd command */
> -  __MSQ_PAD_TIME (msg_rtime, 2);       /* time of last msgrcv command */
> -  __MSQ_PAD_TIME (msg_ctime, 3);       /* time of last change */
> +#if __TIMESIZE == 32
> +  __time_t msg_stime;          /* time of last msgsnd command */
> +  unsigned long int __glibc_reserved1;
> +  __time_t msg_rtime;          /* time of last msgsnd command */
> +  unsigned long int __glibc_reserved2;
> +  __time_t msg_ctime;          /* time of last change */
> +  unsigned long int __glibc_reserved3;
> +#else
> +  __time_t msg_stime;          /* time of last msgsnd command */
> +  __time_t msg_rtime;          /* time of last msgsnd command */
> +  __time_t msg_ctime;          /* time of last change */
> +#endif
>    __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
>    msgqnum_t msg_qnum;          /* number of messages currently on queue */
>    msglen_t msg_qbytes;         /* max number of bytes allowed on queue */
> diff --git a/sysdeps/unix/sysv/linux/hppa/bits/msq-pad.h b/sysdeps/unix/sysv/linux/hppa/bits/msq-pad.h
> deleted file mode 100644
> index 6986585ae7..0000000000
> --- a/sysdeps/unix/sysv/linux/hppa/bits/msq-pad.h
> +++ /dev/null
> @@ -1,26 +0,0 @@
> -/* Define where padding goes in struct msqid_ds.  HPPA 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_MSG_H
> -# error "Never use <bits/msq-pad.h> directly; include <sys/msg.h> instead."
> -#endif
> -
> -#include <bits/timesize.h>
> -
> -#define __MSQ_PAD_AFTER_TIME 0
> -#define __MSQ_PAD_BEFORE_TIME (__TIMESIZE == 32)
> diff --git a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
> new file mode 100644
> index 0000000000..3cf70e36c4
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
> @@ -0,0 +1,47 @@
> +/* Linux/HPPA implementation of the SysV message struct msqid_ds.
> +   Copyright (C) 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_MSG_H
> +# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
> +#endif
> +
> +/* Structure of record for one message inside the kernel.
> +   The type `struct msg' is opaque.  */
> +struct msqid_ds
> +{
> +  struct ipc_perm msg_perm;    /* structure describing operation permission */
> +#if __TIMESIZE == 32
> +  unsigned long int __glibc_reserved1;
> +  __time_t msg_stime;          /* time of last msgsnd command */
> +  unsigned long int __glibc_reserved2;
> +  __time_t msg_rtime;          /* time of last msgsnd command */
> +  unsigned long int __glibc_reserved3;
> +  __time_t msg_ctime;          /* time of last change */
> +#else
> +  __time_t msg_stime;          /* time of last msgsnd command */
> +  __time_t msg_rtime;          /* time of last msgsnd command */
> +  __time_t msg_ctime;          /* time of last change */
> +#endif
> +  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
> +  msgqnum_t msg_qnum;          /* number of messages currently on queue */
> +  msglen_t msg_qbytes;         /* max number of bytes allowed on queue */
> +  __pid_t msg_lspid;           /* pid of last msgsnd() */
> +  __pid_t msg_lrpid;           /* pid of last msgrcv() */
> +  __syscall_ulong_t __glibc_reserved4;
> +  __syscall_ulong_t __glibc_reserved5;
> +};

Looks good.

> diff --git a/sysdeps/unix/sysv/linux/mips/bits/msq-pad.h b/sysdeps/unix/sysv/linux/mips/bits/msq-pad.h
> deleted file mode 100644
> index 8e28c5abe1..0000000000
> --- a/sysdeps/unix/sysv/linux/mips/bits/msq-pad.h
> +++ /dev/null
> @@ -1,31 +0,0 @@
> -/* Define where padding goes in struct msqid_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_MSG_H
> -# error "Never use <bits/msq-pad.h> directly; include <sys/msg.h> instead."
> -#endif
> -
> -#include <bits/timesize.h>
> -
> -#ifdef __MIPSEL__
> -# define __MSQ_PAD_AFTER_TIME (__TIMESIZE == 32)
> -# define __MSQ_PAD_BEFORE_TIME 0
> -#else
> -# define __MSQ_PAD_AFTER_TIME 0
> -# define __MSQ_PAD_BEFORE_TIME (__TIMESIZE == 32)
> -#endif
> diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
> new file mode 100644
> index 0000000000..85fdeef274
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
> @@ -0,0 +1,56 @@
> +/* Linux/PowerPC implementation of the SysV message struct msqid_ds.

This should be MIPS, not PowerPC.

> +   Copyright (C) 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_MSG_H
> +# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
> +#endif
> +
> +/* Structure of record for one message inside the kernel.
> +   The type `struct msg' is opaque.  */
> +struct msqid_ds
> +{
> +  struct ipc_perm msg_perm;    /* structure describing operation permission */
> +#if __TIMESIZE == 32
> +# ifdef __MIPSEL__
> +  __time_t msg_stime;          /* time of last msgsnd command */
> +  unsigned long int __glibc_reserved1;
> +  __time_t msg_rtime;          /* time of last msgsnd command */
> +  unsigned long int __glibc_reserved2;
> +  __time_t msg_ctime;          /* time of last change */
> +  unsigned long int __glibc_reserved3;
> +# else
> +  unsigned long int __glibc_reserved1;
> +  __time_t msg_stime;          /* time of last msgsnd command */
> +  unsigned long int __glibc_reserved2;
> +  __time_t msg_rtime;          /* time of last msgsnd command */
> +  unsigned long int __glibc_reserved3;
> +  __time_t msg_ctime;          /* time of last change */
> +# endif
> +#else
> +  __time_t msg_stime;          /* time of last msgsnd command */
> +  __time_t msg_rtime;          /* time of last msgsnd command */
> +  __time_t msg_ctime;          /* time of last change */
> +#endif
> +  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
> +  msgqnum_t msg_qnum;          /* number of messages currently on queue */
> +  msglen_t msg_qbytes;         /* max number of bytes allowed on queue */
> +  __pid_t msg_lspid;           /* pid of last msgsnd() */
> +  __pid_t msg_lrpid;           /* pid of last msgrcv() */
> +  __syscall_ulong_t __glibc_reserved4;
> +  __syscall_ulong_t __glibc_reserved5;
> +};

Implementation looks good.

> diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/msq-pad.h b/sysdeps/unix/sysv/linux/powerpc/bits/msq-pad.h
> deleted file mode 100644
> index e2b9310800..0000000000
> --- a/sysdeps/unix/sysv/linux/powerpc/bits/msq-pad.h
> +++ /dev/null
> @@ -1,26 +0,0 @@
> -/* Define where padding goes in struct msqid_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_MSG_H
> -# error "Never use <bits/msq-pad.h> directly; include <sys/msg.h> instead."
> -#endif
> -
> -#include <bits/timesize.h>
> -
> -#define __MSQ_PAD_AFTER_TIME 0
> -#define __MSQ_PAD_BEFORE_TIME (__TIMESIZE == 32)
> diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
> new file mode 100644
> index 0000000000..4ae2fbcbdc
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
> @@ -0,0 +1,47 @@
> +/* Linux/PowerPC implementation of the SysV message struct msqid_ds.
> +   Copyright (C) 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_MSG_H
> +# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
> +#endif
> +
> +/* Structure of record for one message inside the kernel.
> +   The type `struct msg' is opaque.  */
> +struct msqid_ds
> +{
> +  struct ipc_perm msg_perm;    /* structure describing operation permission */
> +#if __TIMESIZE == 32
> +  unsigned long int __glibc_reserved1;
> +  __time_t msg_stime;          /* time of last msgsnd command */
> +  unsigned long int __glibc_reserved2;
> +  __time_t msg_rtime;          /* time of last msgsnd command */
> +  unsigned long int __glibc_reserved3;
> +  __time_t msg_ctime;          /* time of last change */
> +#else
> +  __time_t msg_stime;          /* time of last msgsnd command */
> +  __time_t msg_rtime;          /* time of last msgsnd command */
> +  __time_t msg_ctime;          /* time of last change */
> +#endif
> +  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
> +  msgqnum_t msg_qnum;          /* number of messages currently on queue */
> +  msglen_t msg_qbytes;         /* max number of bytes allowed on queue */
> +  __pid_t msg_lspid;           /* pid of last msgsnd() */
> +  __pid_t msg_lrpid;           /* pid of last msgrcv() */
> +  __syscall_ulong_t __glibc_reserved4;
> +  __syscall_ulong_t __glibc_reserved5;
> +};

Looks good.

> diff --git a/sysdeps/unix/sysv/linux/sparc/bits/msq-pad.h b/sysdeps/unix/sysv/linux/sparc/bits/msq-pad.h
> deleted file mode 100644
> index 99fdf8c8f0..0000000000
> --- a/sysdeps/unix/sysv/linux/sparc/bits/msq-pad.h
> +++ /dev/null
> @@ -1,26 +0,0 @@
> -/* Define where padding goes in struct msqid_ds.  SPARC 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_MSG_H
> -# error "Never use <bits/msq-pad.h> directly; include <sys/msg.h> instead."
> -#endif
> -
> -#include <bits/timesize.h>
> -
> -#define __MSQ_PAD_AFTER_TIME 0
> -#define __MSQ_PAD_BEFORE_TIME (__TIMESIZE == 32)
> diff --git a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
> new file mode 100644
> index 0000000000..71980839c7
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
> @@ -0,0 +1,47 @@
> +/* Linux/SPARC implementation of the SysV message struct msqid_ds.
> +   Copyright (C) 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_MSG_H
> +# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
> +#endif
> +
> +/* Structure of record for one message inside the kernel.
> +   The type `struct msg' is opaque.  */
> +struct msqid_ds
> +{
> +  struct ipc_perm msg_perm;    /* structure describing operation permission */
> +#if __TIMESIZE == 32
> +  unsigned long int __glibc_reserved1;
> +  __time_t msg_stime;          /* time of last msgsnd command */
> +  unsigned long int __glibc_reserved2;
> +  __time_t msg_rtime;          /* time of last msgsnd command */
> +  unsigned long int __glibc_reserved3;
> +  __time_t msg_ctime;          /* time of last change */
> +#else
> +  __time_t msg_stime;          /* time of last msgsnd command */
> +  __time_t msg_rtime;          /* time of last msgsnd command */
> +  __time_t msg_ctime;          /* time of last change */
> +#endif
> +  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
> +  msgqnum_t msg_qnum;          /* number of messages currently on queue */
> +  msglen_t msg_qbytes;         /* max number of bytes allowed on queue */
> +  __pid_t msg_lspid;           /* pid of last msgsnd() */
> +  __pid_t msg_lrpid;           /* pid of last msgrcv() */
> +  __syscall_ulong_t __glibc_reserved4;
> +  __syscall_ulong_t __glibc_reserved5;
> +};

Looks good.

Alistair

> --
> 2.25.1
>

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

* Re: [PATCH 4/7] sysv: linux: Add 64-bit time_t variant for msgctl
  2020-06-30 19:24 ` [PATCH 4/7] sysv: linux: Add 64-bit time_t variant for msgctl Adhemerval Zanella
@ 2020-07-02 21:39   ` Alistair Francis
  2020-07-08 18:07     ` Adhemerval Zanella
  2020-07-07 19:51   ` Carlos O'Donell
  1 sibling, 1 reply; 41+ messages in thread
From: Alistair Francis @ 2020-07-02 21:39 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: GNU C Library, Stepan Golosunov, Alistair Francis

On Tue, Jun 30, 2020 at 12:27 PM Adhemerval Zanella via Libc-alpha
<libc-alpha@sourceware.org> wrote:
>
> To provide a y2038 safe interface a new symbol __msgctl64 is added
> and __msgctl is change to call it instead (it adds some extra buffer
> copy for the 32 bit time_t implementation).
>
> Two two new structures are added:
>
>   1. kernel_msqid64_ds: used internally only on 32-bit architectures
>      to issue the syscall.  A handful architectures (hppa, i386, mips,
>      powerpc32, and sparc32) requires specific implementation due its
>      specific kernel ABI.
>
>   2. msqid_ds64: this is only for __TIMESIZE != 64 to use along with
>      the 64-bit semctl.  It is different than the kernel one because
>      the exported 64-bit time_t might require different alignment
>      depending of the architecture ABI.
>
> So the resulting implementation does:
>
>   1. For 64-bit architectures it assumes msqid_ds already contains
>      64-bit time_t fields it will result in just the __msgctl symbol
>      using the __msgctl64 code.  The msgid_ds argument is passed as-is
>      to the syscall.
>
>   2. For 32-bit architectures with default 64-bit time_t (newer ABIs
>      such riscv32 or arc), it will also result in only one exported
>      symbol but with the required high/low time handling.
>
>   3. Finally for 32-bit architecture with both 32-bit and 64-bit time_t
>      support we follow the already set way to provide one symbol with
>      64-bit time_t support and implement the 32-bit time_t support on
>      basis of the 64-bit one.
>
>      The default 32-bit symbol will allocate and copy the msqid_ds
>      over multiple buffers, but this should be deprecated in favor
>      of the __msgctl64 anyway.
>
> Checked on i686-linux-gnu and x86_64-linux-gnu.  I also did some sniff
> tests on powerpc, powerpc64, mips, mips64, armhf, sparcv9, and
> sparc64.
> ---
>  include/sys/msg.h                             |  10 +
>  .../sysv/linux/bits/types/struct_msqid64_ds.h |  38 ++++
>  .../sysv/linux/bits/types/struct_msqid_ds.h   |   6 +-
>  .../linux/hppa/bits/types/struct_msqid_ds.h   |   6 +-
>  .../linux/hppa/struct_kernel_msqid64_ds.h     |  18 ++
>  .../linux/i386/struct_kernel_msqid64_ds.h     |  18 ++
>  .../linux/mips/bits/types/struct_msqid_ds.h   |  12 +-
>  .../linux/mips/struct_kernel_msqid64_ds.h     |  33 ++++
>  sysdeps/unix/sysv/linux/msgctl.c              | 179 ++++++++++++++----
>  .../powerpc/bits/types/struct_msqid_ds.h      |   6 +-
>  .../powerpc32/struct_kernel_msqid64_ds.h      |  18 ++
>  sysdeps/unix/sysv/linux/semctl.c              |  27 +--
>  .../linux/sparc/bits/types/struct_msqid_ds.h  |   6 +-
>  .../sparc/sparc32/struct_kernel_msqid64_ds.h  |  18 ++
>  .../sysv/linux/struct_kernel_msqid64_ds.h     |  19 ++
>  15 files changed, 350 insertions(+), 64 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h
>
> diff --git a/include/sys/msg.h b/include/sys/msg.h
> index 43ec5b9472..522903f818 100644
> --- a/include/sys/msg.h
> +++ b/include/sys/msg.h
> @@ -6,6 +6,16 @@ extern ssize_t __libc_msgrcv (int msqid, void *msgp, size_t msgsz,
>                               long int msgtyp, int msgflg);
>  extern int __libc_msgsnd (int msqid, const void *msgp, size_t msgsz,
>                           int msgflg);
> +
> +# include <bits/types/struct_msqid64_ds.h>
> +
> +# if __TIMESIZE == 64
> +#  define __msgctl64 __msgctl
> +# else
> +extern int __msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf);
> +libc_hidden_proto (__msgctl64);
> +# endif
> +
>  #endif
>
>  #endif
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h
> new file mode 100644
> index 0000000000..3536c8ea62
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h
> @@ -0,0 +1,38 @@
> +/* Generic implementation of the SysV message struct msqid64_ds.
> +   Copyright (C) 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_MSG_H
> +# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
> +#endif
> +
> +#if __TIMESIZE == 64
> +# define __msqid64_ds msqid_ds
> +#else
> +struct __msqid64_ds
> +{
> +  struct ipc_perm msg_perm;    /* structure describing operation permission */
> +  __time64_t msg_stime;                /* time of last msgsnd command */
> +  __time64_t msg_rtime;                /* time of last msgsnd command */
> +  __time64_t msg_ctime;                /* time of last change */
> +  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
> +  msgqnum_t msg_qnum;          /* number of messages currently on queue */
> +  msglen_t msg_qbytes;         /* max number of bytes allowed on queue */
> +  __pid_t msg_lspid;           /* pid of last msgsnd() */
> +  __pid_t msg_lrpid;           /* pid of last msgrcv() */
> +};
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> index 32173a7b60..43b38175ad 100644
> --- a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> @@ -27,11 +27,11 @@ struct msqid_ds
>    struct ipc_perm msg_perm;    /* structure describing operation permission */
>  #if __TIMESIZE == 32
>    __time_t msg_stime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_rtime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_ctime;          /* time of last change */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>  #else
>    __time_t msg_stime;          /* time of last msgsnd command */
>    __time_t msg_rtime;          /* time of last msgsnd command */
> diff --git a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
> index 3cf70e36c4..16eac46941 100644
> --- a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
> @@ -26,11 +26,11 @@ struct msqid_ds
>  {
>    struct ipc_perm msg_perm;    /* structure describing operation permission */
>  #if __TIMESIZE == 32
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_stime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_rtime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>    __time_t msg_ctime;          /* time of last change */
>  #else
>    __time_t msg_stime;          /* time of last msgsnd command */
> diff --git a/sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..69a63ee27a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long msg_stime_high;
> +  unsigned long msg_stime;
> +  unsigned long msg_rtime_high;
> +  unsigned long msg_rtime;
> +  unsigned long msg_ctime_high;
> +  unsigned long msg_ctime;
> +  unsigned long msg_cbytes;
> +  unsigned long msg_qnum;
> +  unsigned long msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..65b940567b
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct compat_msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long msg_stime;
> +  unsigned long msg_stime_high;
> +  unsigned long msg_rtime;
> +  unsigned long msg_rtime_high;
> +  unsigned long msg_ctime;
> +  unsigned long msg_ctime_high;
> +  unsigned long msg_cbytes;
> +  unsigned long msg_qnum;
> +  unsigned long msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
> index 85fdeef274..9ff010c763 100644
> --- a/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
> @@ -28,17 +28,17 @@ struct msqid_ds
>  #if __TIMESIZE == 32
>  # ifdef __MIPSEL__
>    __time_t msg_stime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_rtime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_ctime;          /* time of last change */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>  # else
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_stime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_rtime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>    __time_t msg_ctime;          /* time of last change */
>  # endif
>  #else
> diff --git a/sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..9cfd5a0dfe
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,33 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +#if __TIMESIZE == 32
> +# ifdef __MIPSEL__
> +  unsigned long int msg_stime;
> +  unsigned long int msg_stime_high;
> +  unsigned long int msg_rtime;
> +  unsigned long int msg_rtime_high;
> +  unsigned long int msg_ctime;
> +  unsigned long int msg_ctime_high;
> +# else
> +  unsigned long int msg_stime_high;
> +  unsigned long int msg_stime;
> +  unsigned long int msg_rtime_high;
> +  unsigned long int msg_rtime;
> +  unsigned long int msg_ctime_high;
> +  unsigned long int msg_ctime;
> +# endif
> +#else
> +  unsigned long int msg_stime;
> +  unsigned long int msg_rtime;
> +  unsigned long int msg_ctime;
> +#endif
> +  unsigned long int msg_cbytes;
> +  unsigned long int msg_qnum;
> +  unsigned long int msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long int __unused1;
> +  unsigned long int __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c
> index fd46aec1a0..a7f7651280 100644
> --- a/sysdeps/unix/sysv/linux/msgctl.c
> +++ b/sysdeps/unix/sysv/linux/msgctl.c
> @@ -23,16 +23,55 @@
>  #include <errno.h>
>  #include <linux/posix_types.h>  /* For __kernel_mode_t.  */
>
> -#ifndef DEFAULT_VERSION
> -# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -#  define DEFAULT_VERSION GLIBC_2_2
> -# else
> -#  define DEFAULT_VERSION GLIBC_2_31
> -# endif
> +/* POSIX states ipc_perm mode should have type of mode_t.  */
> +_Static_assert (sizeof ((struct msqid_ds){0}.msg_perm.mode)
> +               == sizeof (mode_t),
> +               "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");
> +
> +#if __IPC_TIME64 == 0
> +typedef struct msqid_ds msgctl_arg_t;
> +#else
> +# include <struct_kernel_msqid64_ds.h>
> +
> +static void
> +msqid64_to_kmsqid64 (const struct __msqid64_ds *msqid64,
> +                    struct kernel_msqid64_ds *kmsqid)
> +{
> +  kmsqid->msg_perm       = msqid64->msg_perm;
> +  kmsqid->msg_stime      = msqid64->msg_stime;
> +  kmsqid->msg_stime_high = msqid64->msg_stime >> 32;
> +  kmsqid->msg_rtime      = msqid64->msg_rtime;
> +  kmsqid->msg_rtime_high = msqid64->msg_rtime >> 32;
> +  kmsqid->msg_ctime      = msqid64->msg_ctime;
> +  kmsqid->msg_ctime_high = msqid64->msg_ctime >> 32;
> +  kmsqid->msg_qnum       = msqid64->msg_qnum;
> +  kmsqid->msg_qbytes     = msqid64->msg_qbytes;
> +  kmsqid->msg_lspid      = msqid64->msg_lspid;
> +  kmsqid->msg_lrpid      = msqid64->msg_lrpid;
> +}
> +
> +static void
> +kmsqid64_to_msqid64 (const struct kernel_msqid64_ds *kmsqid,
> +                    struct __msqid64_ds *msqid64)
> +{
> +  msqid64->msg_perm   = kmsqid->msg_perm;
> +  msqid64->msg_stime  = kmsqid->msg_stime
> +                       | ((__time64_t) kmsqid->msg_stime_high << 32);
> +  msqid64->msg_rtime  = kmsqid->msg_rtime
> +                       | ((__time64_t) kmsqid->msg_rtime_high << 32);
> +  msqid64->msg_ctime  = kmsqid->msg_ctime
> +                       | ((__time64_t) kmsqid->msg_ctime_high << 32);
> +  msqid64->msg_qnum   = kmsqid->msg_qnum;
> +  msqid64->msg_qbytes = kmsqid->msg_qbytes;
> +  msqid64->msg_lspid  = kmsqid->msg_lspid;
> +  msqid64->msg_lrpid  = kmsqid->msg_lrpid;
> +}
> +
> +typedef struct kernel_msqid64_ds msgctl_arg_t;
>  #endif
>
>  static int
> -msgctl_syscall (int msqid, int cmd, struct msqid_ds *buf)
> +msgctl_syscall (int msqid, int cmd, msgctl_arg_t *buf)
>  {
>  #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
>    return INLINE_SYSCALL_CALL (msgctl, msqid, cmd | __IPC_64, buf);
> @@ -43,46 +82,118 @@ msgctl_syscall (int msqid, int cmd, struct msqid_ds *buf)
>  }
>
>  int
> -__new_msgctl (int msqid, int cmd, struct msqid_ds *buf)
> +__msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf)
>  {
> -  /* POSIX states ipc_perm mode should have type of mode_t.  */
> -  _Static_assert (sizeof ((struct msqid_ds){0}.msg_perm.mode)
> -                 == sizeof (mode_t),
> -                 "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");
> -
> -#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -  struct msqid_ds tmpds;
> -  if (cmd == IPC_SET)
> +#if __IPC_TIME64
> +  struct kernel_msqid64_ds ksemid, *arg = NULL;
> +  if (buf != NULL)
>      {
> -      tmpds = *buf;
> -      tmpds.msg_perm.mode *= 0x10000U;
> -      buf = &tmpds;
> +      msqid64_to_kmsqid64 (buf, &ksemid);
> +      arg = &ksemid;
>      }
> +# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> +  if (cmd == IPC_SET)
> +    arg->msg_perm.mode *= 0x10000U;
> +# endif
> +#else
> +  msgctl_arg_t *arg = buf;
>  #endif
>
> -  int ret = msgctl_syscall (msqid, cmd, buf);
> +  int ret = msgctl_syscall (msqid, cmd, arg);
> +  if (ret < 0)
> +    return ret;
>
> -  if (ret >= 0)
> +  switch (cmd)
>      {
> -      switch (cmd)
> -       {
> -       case IPC_STAT:
> -       case MSG_STAT:
> -       case MSG_STAT_ANY:
> +    case IPC_STAT:
> +    case MSG_STAT:
> +    case MSG_STAT_ANY:
>  #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -         buf->msg_perm.mode >>= 16;
> +      arg->msg_perm.mode >>= 16;
>  #else
> -         /* Old Linux kernel versions might not clear the mode padding.  */
> -         if (sizeof ((struct msqid_ds){0}.msg_perm.mode)
> -             != sizeof (__kernel_mode_t))
> -           buf->msg_perm.mode &= 0xFFFF;
> +      /* Old Linux kernel versions might not clear the mode padding.  */
> +      if (sizeof ((struct msqid_ds){0}.msg_perm.mode)
> +          != sizeof (__kernel_mode_t))
> +       arg->msg_perm.mode &= 0xFFFF;
> +#endif
> +
> +#if __IPC_TIME64
> +      kmsqid64_to_msqid64 (arg, buf);
>  #endif
> -       }
>      }
>
>    return ret;
>  }
> -versioned_symbol (libc, __new_msgctl, msgctl, DEFAULT_VERSION);
> +#if __TIMESIZE != 64
> +libc_hidden_def (__msgctl64)
> +
> +static void
> +msqid_to_msqid64 (struct __msqid64_ds *mq64, const struct msqid_ds *mq)
> +{
> +  mq64->msg_perm   = mq->msg_perm;
> +  mq64->msg_stime  = mq->msg_stime
> +                    | ((__time64_t) mq->__msg_stime_high << 32);
> +  mq64->msg_rtime  = mq->msg_rtime
> +                    | ((__time64_t) mq->__msg_rtime_high << 32);
> +  mq64->msg_ctime  = mq->msg_ctime
> +                    | ((__time64_t) mq->__msg_ctime_high << 32);
> +  mq64->msg_qnum   = mq->msg_qnum;
> +  mq64->msg_qbytes = mq->msg_qbytes;
> +  mq64->msg_lspid  = mq->msg_lspid;
> +  mq64->msg_lrpid  = mq->msg_lrpid;
> +}
> +
> +static void
> +msqid64_to_msqid (struct msqid_ds *mq, const struct __msqid64_ds *mq64)
> +{
> +  mq->msg_perm         = mq64->msg_perm;
> +  mq->msg_stime        = mq64->msg_stime;
> +  mq->__msg_stime_high = 0;
> +  mq->msg_rtime        = mq64->msg_rtime;
> +  mq->__msg_rtime_high = 0;
> +  mq->msg_ctime        = mq64->msg_ctime;
> +  mq->__msg_ctime_high = 0;
> +  mq->msg_qnum         = mq64->msg_qnum;
> +  mq->msg_qbytes       = mq64->msg_qbytes;
> +  mq->msg_lspid        = mq64->msg_lspid;
> +  mq->msg_lrpid        = mq64->msg_lrpid;
> +}
> +
> +int
> +__msgctl (int msqid, int cmd, struct msqid_ds *buf)
> +{
> +  struct __msqid64_ds msqid64, *buf64 = NULL;
> +  if (buf != NULL)
> +    {
> +      msqid_to_msqid64 (&msqid64, buf);
> +      buf64 = &msqid64;
> +    }
> +
> +  int ret = __msgctl64 (msqid, cmd, buf64);
> +  if (ret < 0)
> +    return ret;
> +
> +  switch (cmd)
> +    {
> +    case IPC_STAT:
> +    case MSG_STAT:
> +    case MSG_STAT_ANY:
> +      if (buf64 != NULL)
> +        msqid64_to_msqid (buf, buf64);
> +    }
> +
> +  return ret;
> +}
> +#endif
> +
> +#ifndef DEFAULT_VERSION
> +# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
> +#  define DEFAULT_VERSION GLIBC_2_2
> +# else
> +#  define DEFAULT_VERSION GLIBC_2_31
> +# endif
> +#endif
> +versioned_symbol (libc, __msgctl, msgctl, DEFAULT_VERSION);
>
>  #if defined __ASSUME_SYSVIPC_BROKEN_MODE_T \
>      && SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_31)
> @@ -90,7 +201,7 @@ int
>  attribute_compat_text_section
>  __msgctl_mode16 (int msqid, int cmd, struct msqid_ds *buf)
>  {
> -  return msgctl_syscall (msqid, cmd, buf);
> +  return msgctl_syscall (msqid, cmd, (msgctl_arg_t *) buf);
>  }
>  compat_symbol (libc, __msgctl_mode16, msgctl, GLIBC_2_2);
>  #endif

Shouldn't everything below here be in a separate patch?

Alistair

> diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
> index 4ae2fbcbdc..35cc51f733 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
> @@ -26,11 +26,11 @@ struct msqid_ds
>  {
>    struct ipc_perm msg_perm;    /* structure describing operation permission */
>  #if __TIMESIZE == 32
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_stime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_rtime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>    __time_t msg_ctime;          /* time of last change */
>  #else
>    __time_t msg_stime;          /* time of last msgsnd command */
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..69a63ee27a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long msg_stime_high;
> +  unsigned long msg_stime;
> +  unsigned long msg_rtime_high;
> +  unsigned long msg_rtime;
> +  unsigned long msg_ctime_high;
> +  unsigned long msg_ctime;
> +  unsigned long msg_cbytes;
> +  unsigned long msg_qnum;
> +  unsigned long msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c
> index 3a06270242..7467d2566e 100644
> --- a/sysdeps/unix/sysv/linux/semctl.c
> +++ b/sysdeps/unix/sysv/linux/semctl.c
> @@ -196,19 +196,11 @@ libc_hidden_def (__semctl64)
>
>  /* The 64-bit time_t semid_ds version might have a different layout and
>     internal field alignment.  */
> -static void
> -semid64_ds_to_semid_ds (struct semid_ds *ds, const struct __semid64_ds *ds64)
> -{
> -  ds->sem_perm = ds64->sem_perm;
> -  ds->sem_otime = ds64->sem_otime;
> -  ds->sem_ctime = ds64->sem_ctime;
> -  ds->sem_nsems = ds64->sem_nsems;
> -}
>
>  static void
> -semid_ds_to_semid64_ds (struct __semid64_ds *ds64, const struct semid_ds *ds)
> +semid_to_semid64 (struct __semid64_ds *ds64, const struct semid_ds *ds)
>  {
> -  ds64->sem_perm = ds->sem_perm;
> +  ds64->sem_perm  = ds->sem_perm;
>    ds64->sem_otime = ds->sem_otime
>                     | ((__time64_t) ds->__sem_otime_high << 32);
>    ds64->sem_ctime = ds->sem_ctime
> @@ -216,6 +208,17 @@ semid_ds_to_semid64_ds (struct __semid64_ds *ds64, const struct semid_ds *ds)
>    ds64->sem_nsems = ds->sem_nsems;
>  }
>
> +static void
> +semid64_to_semid (struct semid_ds *ds, const struct __semid64_ds *ds64)
> +{
> +  ds->sem_perm         = ds64->sem_perm;
> +  ds->sem_otime        = ds64->sem_otime;
> +  ds->__sem_otime_high = 0;
> +  ds->sem_ctime        = ds64->sem_ctime;
> +  ds->__sem_ctime_high = 0;
> +  ds->sem_nsems        = ds64->sem_nsems;
> +}
> +
>  static union semun64
>  semun_to_semun64 (int cmd, union semun semun, struct __semid64_ds *semid64)
>  {
> @@ -232,7 +235,7 @@ semun_to_semun64 (int cmd, union semun semun, struct __semid64_ds *semid64)
>      case IPC_STAT:
>      case IPC_SET:
>        r.buf = semid64;
> -      semid_ds_to_semid64_ds (r.buf, semun.buf);
> +      semid_to_semid64 (r.buf, semun.buf);
>  # ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
>        if (cmd == IPC_SET)
>         r.buf->sem_perm.mode *= 0x10000U;
> @@ -282,7 +285,7 @@ __semctl (int semid, int semnum, int cmd, ...)
>      case IPC_STAT:
>      case SEM_STAT:
>      case SEM_STAT_ANY:
> -      semid64_ds_to_semid_ds (arg.buf, arg64.buf);
> +      semid64_to_semid (arg.buf, arg64.buf);
>      }
>
>    return ret;
> diff --git a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
> index 71980839c7..502c23d91e 100644
> --- a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
> @@ -26,11 +26,11 @@ struct msqid_ds
>  {
>    struct ipc_perm msg_perm;    /* structure describing operation permission */
>  #if __TIMESIZE == 32
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_stime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_rtime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>    __time_t msg_ctime;          /* time of last change */
>  #else
>    __time_t msg_stime;          /* time of last msgsnd command */
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..69a63ee27a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long msg_stime_high;
> +  unsigned long msg_stime;
> +  unsigned long msg_rtime_high;
> +  unsigned long msg_rtime;
> +  unsigned long msg_ctime_high;
> +  unsigned long msg_ctime;
> +  unsigned long msg_cbytes;
> +  unsigned long msg_qnum;
> +  unsigned long msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..a676e34a5a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,19 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  It is only used
> +   for 32-bit architectures on 64-bit time_t msgctl64 implementation.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long int msg_stime;
> +  unsigned long int msg_stime_high;
> +  unsigned long int msg_rtime;
> +  unsigned long int msg_rtime_high;
> +  unsigned long int msg_ctime;
> +  unsigned long int msg_ctime_high;
> +  unsigned long int msg_cbytes;
> +  unsigned long int msg_qnum;
> +  unsigned long int  msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long int __unused4;
> +  unsigned long int __unused5;
> +};
> --
> 2.25.1
>

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

* Re: [PATCH 5/7] sysvipc: Split out linux struct shmid_ds
  2020-06-30 19:24 ` [PATCH 5/7] sysvipc: Split out linux struct shmid_ds Adhemerval Zanella
@ 2020-07-02 21:40   ` Alistair Francis
  2020-07-07 19:52   ` Carlos O'Donell
  1 sibling, 0 replies; 41+ messages in thread
From: Alistair Francis @ 2020-07-02 21:40 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: GNU C Library, Stepan Golosunov, Alistair Francis

On Tue, Jun 30, 2020 at 12:27 PM Adhemerval Zanella via Libc-alpha
<libc-alpha@sourceware.org> wrote:
>
> This will allow us to have architectures specify their own version.
>
> Not semantic changes expected.  Checked with a build against the
> all affected ABIs.

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  sysdeps/unix/sysv/linux/Makefile              |  1 +
>  sysdeps/unix/sysv/linux/bits/shm.h            | 34 +----------
>  .../sysv/linux/bits/types/struct_shmid_ds.h   | 57 +++++++++++++++++++
>  3 files changed, 59 insertions(+), 33 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
>
> diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
> index 505087e617..bdd187af73 100644
> --- a/sysdeps/unix/sysv/linux/Makefile
> +++ b/sysdeps/unix/sysv/linux/Makefile
> @@ -93,6 +93,7 @@ sysdep_headers += sys/mount.h sys/acct.h \
>                   bits/termios-misc.h \
>                   bits/types/struct_semid_ds.h \
>                   bits/types/struct_msqid_ds.h \
> +                 bits/types/struct_shmid_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/shm.h b/sysdeps/unix/sysv/linux/bits/shm.h
> index 113c05ee89..9ef6aeaf92 100644
> --- a/sysdeps/unix/sysv/linux/bits/shm.h
> +++ b/sysdeps/unix/sysv/linux/bits/shm.h
> @@ -43,39 +43,7 @@ __BEGIN_DECLS
>  /* Type to count number of attaches.  */
>  typedef __syscall_ulong_t shmatt_t;
>
> -#if __SHM_PAD_BEFORE_TIME
> -# define __SHM_PAD_TIME(NAME, RES)                             \
> -  unsigned long int __glibc_reserved ## RES; __time_t NAME
> -#elif __SHM_PAD_AFTER_TIME
> -# define __SHM_PAD_TIME(NAME, RES)                             \
> -  __time_t NAME; unsigned long int __glibc_reserved ## RES
> -#else
> -# define __SHM_PAD_TIME(NAME, RES)             \
> -  __time_t NAME
> -#endif
> -
> -/* Data structure describing a shared memory segment.  */
> -struct shmid_ds
> -  {
> -    struct ipc_perm shm_perm;          /* operation permission struct */
> -#if !__SHM_SEGSZ_AFTER_TIME
> -    size_t shm_segsz;                  /* size of segment in bytes */
> -#endif
> -    __SHM_PAD_TIME (shm_atime, 1);     /* time of last shmat() */
> -    __SHM_PAD_TIME (shm_dtime, 2);     /* time of last shmdt() */
> -    __SHM_PAD_TIME (shm_ctime, 3);     /* time of last change by shmctl() */
> -#if __SHM_PAD_BETWEEN_TIME_AND_SEGSZ
> -    unsigned long int __glibc_reserved4;
> -#endif
> -#if __SHM_SEGSZ_AFTER_TIME
> -    size_t shm_segsz;                  /* size of segment in bytes */
> -#endif
> -    __pid_t shm_cpid;                  /* pid of creator */
> -    __pid_t shm_lpid;                  /* pid of last shmop */
> -    shmatt_t shm_nattch;               /* number of current attaches */
> -    __syscall_ulong_t __glibc_reserved5;
> -    __syscall_ulong_t __glibc_reserved6;
> -  };
> +#include <bits/types/struct_shmid_ds.h>
>
>  #ifdef __USE_MISC
>
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
> new file mode 100644
> index 0000000000..938bbedfcd
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
> @@ -0,0 +1,57 @@
> +/* Generic implementation of the shared memory struct shmid_ds.
> +   Copyright (C) 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_SHM_H
> +# error "Never include <bits/types/struct_shmid_ds.h> directly; use <sys/shm.h> instead."
> +#endif
> +
> +#include <bits/shm-pad.h>
> +
> +#if __SHM_PAD_BEFORE_TIME
> +# define __SHM_PAD_TIME(NAME, RES)                             \
> +  unsigned long int __glibc_reserved ## RES; __time_t NAME
> +#elif __SHM_PAD_AFTER_TIME
> +# define __SHM_PAD_TIME(NAME, RES)                             \
> +  __time_t NAME; unsigned long int __glibc_reserved ## RES
> +#else
> +# define __SHM_PAD_TIME(NAME, RES)             \
> +  __time_t NAME
> +#endif
> +
> +/* Data structure describing a shared memory segment.  */
> +struct shmid_ds
> +  {
> +    struct ipc_perm shm_perm;          /* operation permission struct */
> +#if !__SHM_SEGSZ_AFTER_TIME
> +    size_t shm_segsz;                  /* size of segment in bytes */
> +#endif
> +    __SHM_PAD_TIME (shm_atime, 1);     /* time of last shmat() */
> +    __SHM_PAD_TIME (shm_dtime, 2);     /* time of last shmdt() */
> +    __SHM_PAD_TIME (shm_ctime, 3);     /* time of last change by shmctl() */
> +#if __SHM_PAD_BETWEEN_TIME_AND_SEGSZ
> +    unsigned long int __glibc_reserved4;
> +#endif
> +#if __SHM_SEGSZ_AFTER_TIME
> +    size_t shm_segsz;                  /* size of segment in bytes */
> +#endif
> +    __pid_t shm_cpid;                  /* pid of creator */
> +    __pid_t shm_lpid;                  /* pid of last shmop */
> +    shmatt_t shm_nattch;               /* number of current attaches */
> +    __syscall_ulong_t __glibc_reserved5;
> +    __syscall_ulong_t __glibc_reserved6;
> +  };
> --
> 2.25.1
>

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

* Re: [PATCH 7/7] sysv: linux: Add 64-bit time_t variant for shmctl
  2020-07-01 23:00             ` Alistair Francis
@ 2020-07-02 21:41               ` Alistair Francis
  0 siblings, 0 replies; 41+ messages in thread
From: Alistair Francis @ 2020-07-02 21:41 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: GNU C Library, Stepan Golosunov, Alistair Francis

On Wed, Jul 1, 2020 at 4:00 PM Alistair Francis <alistair23@gmail.com> wrote:
>
> On Wed, Jul 1, 2020 at 10:07 AM Adhemerval Zanella
> <adhemerval.zanella@linaro.org> wrote:
> >
> >
> >
> > On 01/07/2020 13:35, Adhemerval Zanella wrote:
> > >
> > >
> > > On 01/07/2020 12:48, Alistair Francis wrote:
> > >> On Wed, Jul 1, 2020 at 5:19 AM Adhemerval Zanella
> > >> <adhemerval.zanella@linaro.org> wrote:
> > >>>
> > >>>
> > >>>
> > >>> On 30/06/2020 23:28, Alistair Francis wrote:
> > >>> deps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
> > >>>>> new file mode 100644
> > >>>>> index 0000000000..5533d44dee
> > >>>>> --- /dev/null
> > >>>>> +++ b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
> > >>>>> @@ -0,0 +1,24 @@
> > >>>>> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
> > >>>>> +struct kernel_shmid64_ds
> > >>>>> +{
> > >>>>> +  struct ipc_perm shm_perm;
> > >>>>> +#if __TIMESIZE == 64
> > >>>>> +  long int shm_atime;
> > >>>>> +  long int shm_atime;
> > >>>>> +  long int shm_atime;
> > >>>>
> > >>>> This fails to compile as all three variables have the same name.
> > >>>
> > >>> In fact this code specifically is not used on powerpc since it will
> > >>> either use the __TIMESIZE == 32 (powerpc32) or not use this
> > >>> structure at all (powerpc64{le}).  But it is still an issue I will
> > >>> revise the patch for such issues and remove it (maybe adding a
> > >>> #error if it used on powerpc64).
> > >>
> > >> Ah whoops, I commented inline on the wrong file. The generic one
> > >> (sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h) also has the same
> > >> problem which is why I saw the RISC-V build fail.
> > >>
> > >>>
> > >>> Besides it, does it work for riscv32 (which should use the default
> > >>> definition)?
> > >>
> > >> This patch doesn't work due to the same name variables in a few places
> > >> (one of them being the generic one).
> > >>
> > >
> > > I need to setup an 32-bit ABI with 64-bit time_t to catch these kind of
> > > issues.
> > >
> > >> I am testing all the other patches and should know by tonight (about 8
> > >> hours still), I'll let you know.
> > >
> > > Ack, you can also do a sniff test with the sysvipc tests to check if
> > > they are ok.
> >
> > Ok, the __TIMESIZE should not be used to define the kernel_* struct anyway,
> > they should be independent of the glibc time ABI selected or defined by
> > the ABI.
> >
> > I have updated my personal branch [1] with an updated version and I will
> > try to check if riscv32 at least built against. If you could also check
> > it would be helpful.
>
> Thanks!
>
> I have tested this series with patch 7 (this patch) dropped and it
> works for RV32.
>
> >
> > [1] https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/azanella/semctl-y2038
>
> I am now running a full test of this branch, unfortunately it'll take
> about 24 hours.

I tested the above branch for RV32 and it passes all the tests, so works for me.

I have also reviewed the current patches on list.

Let me know if I can do anything else to help get this merged.

Alistair

>
> Alistair

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

* Re: [PATCH 1/7] sysv: linux: Add 64-bit time_t variant for semctl
  2020-06-30 19:24 [PATCH 1/7] sysv: linux: Add 64-bit time_t variant for semctl Adhemerval Zanella
                   ` (6 preceding siblings ...)
  2020-07-02 19:01 ` [PATCH 1/7] sysv: linux: Add 64-bit time_t variant for semctl Alistair Francis
@ 2020-07-07  3:32 ` Carlos O'Donell
  2020-07-07 14:09   ` Adhemerval Zanella
  7 siblings, 1 reply; 41+ messages in thread
From: Carlos O'Donell @ 2020-07-07  3:32 UTC (permalink / raw)
  To: Adhemerval Zanella, libc-alpha; +Cc: stepan, Alistair Francis

On 6/30/20 3:24 PM, Adhemerval Zanella via Libc-alpha wrote:

OK for master with comment cleanups. Very clean, very easy to understand
patch. I should finish the other 6 patches tomorrow morning.

No regressions on x86_64 or i686 (I did see the new rseq regression
for posix/tst-affinity-static though).

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Tested-by: Carlos O'Donell <carlos@redhat.com>

> Different than others 64-bit time_t syscalls, the SysIPC interface
> does not provide a new set of syscall for y2038 safeness.  Instead it
> uses ununsed fields in semid_ds structure the return the high bits for

s/ununsed/unused/g
s/the return/to return/g

> the timestamps.
> 
> To provide a y2038 safe interface a new symbol __semctl64 is added
> and __semctl is change to call it instead (it adds some extra buffer
> copy for the 32 bit time_t implementation).

OK.

> 
> Two two new structures are added:

s/Two two/Two/g

> 
>   1. kernel_semid64_ds: used internally only on 32-bit architectures
>      to issue the syscall.  A handful architectures (hppa, i386, mips,

s/handful/handful of/g

>      powerpc32, sparc32) requires specific implementation due its
>      specific kernel ABI.

Suggest:

require specific implementations due to their kernel ABI.

> 
>   2. semid_ds64: this is only for __TIMESIZE != 64 to use along with
>      the 64-bit semctl.  It is different than the kernel one because

s/one/struct/g

>      the exported 64-bit time_t might require different alignment
>      depending of the architecture ABI.

OK.

> 
> So the resulting implementation does:
> 
>   1. For 64-bit architectures it assumes semid_ds already contains
>      64-bit time_t fields it will result in just the __semctl symbol

s/it/and/g

>      using the __semctl64 code.  The semid_ds argument is passed as-is
>      to the syscall.
> 
>   2. For 32-bit architectures with default 64-bit time_t (newer ABIs
>      such riscv32 or arc), it will also result in only one exported
>      symbol but with the required high/low handling.

OK.
 
>      It might be possible to optimize it further to avoid the
>      kernel_semid64_ds to semun transformation if the exported ABI
>      for the architectures matches the expected kernel ABI, but the
>      implementation is already complex enough and don't think this
>      should be a hotspot in any case.

OK. Agreed. If we see a hotspot here we can discuss.

>   3. Finally for 32-bit architecture with both 32-bit and 64-bit time_t
>      support we follow the already set way to provide one symbol with
>      64-bit time_t support and implement the 32-bit time_t support on
>      basis of the 64-bit one.

s/on basis of/using/g
s/one/time_t/g
 
>      The default 32-bit symbol will allocate and copy the semid_ds
>      over multiple buffers, but this should be deprecated in favor
>      of the __semctl64 anyway.

OK.

> 
> Checked on i686-linux-gnu and x86_64-linux-gnu.  I also did some sniff
> tests on powerpc, powerpc64, mips, mips64, armhf, sparcv9, and
> sparc64.

OK.

> ---
>  include/sys/sem.h                             |   7 +
>  .../sysv/linux/bits/types/struct_semid64_ds.h |  33 +++
>  .../sysv/linux/bits/types/struct_semid_ds.h   |  21 +-
>  .../linux/hppa/bits/types/struct_semid_ds.h   |   6 +-
>  .../linux/hppa/struct_kernel_semid64_ds.h     |  12 +
>  .../linux/i386/struct_kernel_semid64_ds.h     |  12 +
>  sysdeps/unix/sysv/linux/ipc_priv.h            |  10 +
>  .../linux/mips/bits/types/struct_semid_ds.h   |   4 +-
>  .../linux/mips/struct_kernel_semid64_ds.h     |  10 +
>  .../powerpc/bits/types/struct_semid_ds.h      |   4 +-
>  .../powerpc32/struct_kernel_semid64_ds.h      |  12 +
>  sysdeps/unix/sysv/linux/semctl.c              | 261 +++++++++++++++---
>  .../linux/sparc/bits/types/struct_semid_ds.h  |   4 +-
>  .../sparc/sparc32/struct_kernel_semid64_ds.h  |  12 +
>  .../sysv/linux/struct_kernel_semid64_ds.h     |  12 +
>  .../linux/x86/bits/types/struct_semid_ds.h    |   4 +-
>  16 files changed, 359 insertions(+), 65 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_semid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/hppa/struct_kernel_semid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/i386/struct_kernel_semid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/mips/struct_kernel_semid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_semid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_semid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/struct_kernel_semid64_ds.h
> 
> diff --git a/include/sys/sem.h b/include/sys/sem.h
> index 69fdf1f752..a9151e057d 100644
> --- a/include/sys/sem.h
> +++ b/include/sys/sem.h
> @@ -5,5 +5,12 @@
>  
>  __typeof__ (semtimedop) __semtimedop attribute_hidden;
>  
> +#if __TIMESIZE == 64
> +# define __semctl64 __semctl
> +#else
> +extern int __semctl64 (int semid, int semnum, int cmd, ...);
> +libc_hidden_proto (__semctl64);

OK.

> +#endif
> +
>  # endif
>  #endif
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_semid64_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_semid64_ds.h
> new file mode 100644
> index 0000000000..bda9eb4469
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_semid64_ds.h
> @@ -0,0 +1,33 @@
> +/* Generic implementation of the semaphore struct semid64_ds.
> +   Copyright (C) 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 __TIMESIZE == 64
> +# define __semid64_ds semid_ds
> +#else
> +struct __semid64_ds
> +{
> +  struct ipc_perm sem_perm;		/* operation permission struct */

OK.

> +  __time64_t sem_otime;			/* last semop() time */
> +  __time64_t sem_ctime;			/* last time changed by semctl() */
> +  __syscall_ulong_t sem_nsems;		/* number of semaphores in set */

OK.

> +};
> +#endif
> 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 4222e6a59f..bc26d8be08 100644
> --- a/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h
> @@ -21,26 +21,19 @@
>  #endif
>  
>  /* Data structure describing a set of semaphores.  */
> -#if __TIMESIZE == 32
>  struct semid_ds
>  {
>    struct ipc_perm sem_perm;        /* operation permission struct */
> +#if __TIMESIZE == 32
>    __time_t sem_otime;              /* last semop() time */
> -  __syscall_ulong_t __glibc_reserved1;
> +  __syscall_ulong_t __sem_otime_high;

OK.

>    __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;
> -};
> +  __syscall_ulong_t __sem_ctime_high;

OK.

>  #else
> -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 */
> +  __time_t sem_otime;
> +  __time_t sem_ctime;

OK.

> +#endif
> +  __syscall_ulong_t sem_nsems;    /* number of semaphores in set */

OK.

>    __syscall_ulong_t __glibc_reserved3;
>    __syscall_ulong_t __glibc_reserved4;
>  };
> -#endif
> diff --git a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_semid_ds.h
> index d4c50b5ef8..68f9eca24c 100644
> --- a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_semid_ds.h
> +++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_semid_ds.h
> @@ -21,16 +21,14 @@
>  #endif
>  
>  /* 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;
> +  __syscall_ulong_t __sem_otime_high;
>    __time_t sem_otime;         /* last semop() time */
> -  __syscall_ulong_t __glibc_reserved2;
> +  __syscall_ulong_t __sem_ctime_high;

OK.

>    __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/hppa/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/hppa/struct_kernel_semid64_ds.h
> new file mode 100644
> index 0000000000..2871030d0d
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/hppa/struct_kernel_semid64_ds.h
> @@ -0,0 +1,12 @@
> +/* Analogous to kernel struct semid64_ds used on semctl.  */
> +struct kernel_semid64_ds
> +{
> +  struct ipc_perm sem_perm;
> +  unsigned long sem_otime_high;
> +  unsigned long sem_otime;
> +  unsigned long sem_ctime_high;
> +  unsigned long sem_ctime;

OK. Matches where the reserved entries were for hppa.

> +  unsigned long sem_nsems;
> +  unsigned long __ununsed1;
> +  unsigned long __ununsed2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/i386/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/i386/struct_kernel_semid64_ds.h
> new file mode 100644
> index 0000000000..bab9cf63ba
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/i386/struct_kernel_semid64_ds.h
> @@ -0,0 +1,12 @@
> +/* Analogous to kernel struct semid64_ds used on semctl.  */
> +struct kernel_semid64_ds
> +{
> +  struct ipc_perm sem_perm;
> +  unsigned long sem_otime;
> +  unsigned long sem_otime_high;
> +  unsigned long sem_ctime;
> +  unsigned long sem_ctime_high;

OK.

> +  __syscall_ulong_t sem_nsems;
> +  __syscall_ulong_t __unused3;
> +  __syscall_ulong_t __unused4;
> +};
> diff --git a/sysdeps/unix/sysv/linux/ipc_priv.h b/sysdeps/unix/sysv/linux/ipc_priv.h
> index 15a6e683a4..93a6e5cb24 100644
> --- a/sysdeps/unix/sysv/linux/ipc_priv.h
> +++ b/sysdeps/unix/sysv/linux/ipc_priv.h
> @@ -53,4 +53,14 @@ struct __old_ipc_perm
>  #define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
>    (__nsops), 0, (__sops), (__timeout)
>  
> +/* Linux SysV ipc does not provide new syscalls for 64-bit time support on
> +   32-bit architectures, but rather split the timestamps on previous unused
> +   fields.  */

Suggest:

but rather split the timestamp into high and low; storing the high value in
previously unused fields.

> +#if (__WORDSIZE == 32 \
> +     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
> +# define __IPC_TIME64 1
> +#else
> +# define __IPC_TIME64 0
> +#endif

OK.

> +
>  #include <ipc_ops.h>
> diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h
> index 8954209a29..eec4a18cae 100644
> --- a/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h
> +++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h
> @@ -27,6 +27,6 @@ struct semid_ds
>    __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;
> +  __syscall_ulong_t __sem_otime_high;
> +  __syscall_ulong_t __sem_ctime_high;

OK.

>  };
> diff --git a/sysdeps/unix/sysv/linux/mips/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/mips/struct_kernel_semid64_ds.h
> new file mode 100644
> index 0000000000..76a9d83ea5
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/struct_kernel_semid64_ds.h
> @@ -0,0 +1,10 @@
> +/* Analogous to kernel struct semid64_ds used on semctl.  */
> +struct kernel_semid64_ds
> +{
> +  struct ipc_perm sem_perm;
> +  unsigned long sem_otime;
> +  unsigned long sem_ctime;
> +  unsigned long sem_nsems;
> +  unsigned long sem_otime_high;
> +  unsigned long sem_ctime_high;

OK. Matches mips.

> +};
> 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
> index 300a9b98e9..d382d93c52 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_semid_ds.h
> +++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_semid_ds.h
> @@ -25,9 +25,9 @@ struct semid_ds
>  {
>    struct ipc_perm sem_perm;   /* operation permission struct */
>  #if __TIMESIZE == 32
> -  __syscall_ulong_t __glibc_reserved1;
> +  __syscall_ulong_t __sem_otime_high;
>    __time_t sem_otime;         /* last semop() time */
> -  __syscall_ulong_t __glibc_reserved2;
> +  __syscall_ulong_t __sem_ctime_high;

OK.

>    __time_t sem_ctime;        /* last time changed by semctl() */
>  #else
>    __time_t sem_otime;         /* last semop() time */
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_semid64_ds.h
> new file mode 100644
> index 0000000000..7fa4ef6424
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_semid64_ds.h
> @@ -0,0 +1,12 @@
> +/* Analogous to kernel struct semid64_ds used on semctl.  */
> +struct kernel_semid64_ds
> +{
> +  struct ipc_perm sem_perm;
> +  unsigned long sem_otime_high;
> +  unsigned long sem_otime;
> +  unsigned long sem_ctime_high;
> +  unsigned long sem_ctime;
> +  unsigned long sem_nsems;
> +  unsigned long __unused3;
> +  unsigned long __unused4;

OK. Matches powerpc32.

> +};
> diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c
> index 30571af49f..3a06270242 100644
> --- a/sysdeps/unix/sysv/linux/semctl.c
> +++ b/sysdeps/unix/sysv/linux/semctl.c
> @@ -21,10 +21,13 @@
>  #include <ipc_priv.h>
>  #include <sysdep.h>
>  #include <shlib-compat.h>
> -#include <errno.h>
> -#include <linux/posix_types.h>  /* For __kernel_mode_t.  */
> +#include <bits/types/struct_semid64_ds.h>  /* For __semid64_ds.  */
> +#include <linux/posix_types.h>             /* For __kernel_mode_t.  */

OK.

>  
> -/* Define a `union semun' suitable for Linux here.  */
> +/* The struct used to issue the syscall.  For architecture that assume

s/architecture/architectures/g

> +   64-bit time as default (!__ASSUME_TIME64_SYSCALLS) the syscall will
> +   split the resulting 64-bit sem_{o,c}time in two fields (__sem_{o,c}time

s/__sem_{o,c}time/sem_{o,c}time/g

> +   and __sem_{o,c}time_hi).  */

s/__sem_{o,c}time_hi/__sem{o,c}time_high/g

>  union semun
>  {
>    int val;			/* value for SETVAL */
> @@ -33,16 +36,89 @@ union semun
>    struct seminfo *__buf;	/* buffer for IPC_INFO */
>  };
>  
> -#ifndef DEFAULT_VERSION
> -# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -#  define DEFAULT_VERSION GLIBC_2_2
> +#if __IPC_TIME64 == 0
> +# define semun64 semun
> +typedef union semun semctl_arg_t;
> +#else
> +# include <struct_kernel_semid64_ds.h>
> +
> +union ksemun64
> +{
> +  int val;
> +  struct kernel_semid64_ds *buf;
> +  unsigned short int *array;
> +  struct seminfo *__buf;
> +};

OK. Kernel side.

> +
> +# if __TIMESIZE == 64
> +#  define semun64 semun
>  # else
> -#  define DEFAULT_VERSION GLIBC_2_31
> +/* The struct used when __semctl64 is called.  */
> +union semun64
> +{
> +  int val;
> +  struct __semid64_ds *buf;
> +  unsigned short int *array;
> +  struct seminfo *__buf;
> +};

OK. User side.

>  # endif
> +
> +static void
> +semid64_to_ksemid64 (const struct __semid64_ds *semid64,
> +		     struct kernel_semid64_ds *ksemid)
> +{
> +  ksemid->sem_perm       = semid64->sem_perm;
> +  ksemid->sem_otime      = semid64->sem_otime;
> +  ksemid->sem_otime_high = semid64->sem_otime >> 32;
> +  ksemid->sem_ctime      = semid64->sem_ctime;
> +  ksemid->sem_ctime_high = semid64->sem_ctime >> 32;
> +  ksemid->sem_nsems      = semid64->sem_nsems;
> +}

OK. Copy to kernel.

> +
> +static void
> +ksemid64_to_semid64 (const struct kernel_semid64_ds *ksemid,
> +		     struct __semid64_ds *semid64)
> +{
> +  semid64->sem_perm  = ksemid->sem_perm;
> +  semid64->sem_otime = ksemid->sem_otime
> +		       | ((__time64_t) ksemid->sem_otime_high << 32);
> +  semid64->sem_ctime = ksemid->sem_ctime
> +		       | ((__time64_t) ksemid->sem_ctime_high << 32);
> +  semid64->sem_nsems = ksemid->sem_nsems;
> +}

OK. Copy to user (full 64-bit wide).

> +
> +static union ksemun64
> +semun64_to_ksemun64 (int cmd, union semun64 semun64,
> +		     struct kernel_semid64_ds *buf)
> +{
> +  union ksemun64 r = { 0 };
> +  switch (cmd)
> +    {
> +    case SETVAL:
> +      r.val = semun64.val;
> +      break;
> +    case GETALL:
> +    case SETALL:
> +      r.array = semun64.array;
> +      break;
> +    case IPC_STAT:
> +    case IPC_SET:
> +      r.buf = buf;
> +      semid64_to_ksemid64 (semun64.buf, r.buf);
> +      break;
> +    case IPC_INFO:
> +    case SEM_INFO:
> +      r.__buf = semun64.__buf;
> +      break;
> +    }
> +  return r;
> +}

OK. Union copy.

> +
> +typedef union ksemun64 semctl_arg_t;
>  #endif
>  
>  static int
> -semctl_syscall (int semid, int semnum, int cmd, union semun arg)
> +semctl_syscall (int semid, int semnum, int cmd, semctl_arg_t arg)
>  {
>  #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
>    return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64,
> @@ -53,15 +129,15 @@ semctl_syscall (int semid, int semnum, int cmd, union semun arg)
>  #endif
>  }
>  
> +/* 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)");

OK.

> +
>  int
> -__new_semctl (int semid, int semnum, int cmd, ...)
> +__semctl64 (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 };
> +  union semun64 arg64 = { 0 };
>    va_list ap;
>  
>    /* Get the argument only if required.  */
> @@ -76,44 +152,151 @@ __new_semctl (int semid, int semnum, int cmd, ...)
>      case IPC_INFO:      /* arg.__buf */
>      case SEM_INFO:
>        va_start (ap, cmd);
> -      arg = va_arg (ap, union semun);
> +      arg64 = va_arg (ap, union semun64);
>        va_end (ap);
>        break;
>      }
>  
> -#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;
> -    }
> +#if __IPC_TIME64
> +  struct kernel_semid64_ds ksemid;
> +  union ksemun64 ksemun = semun64_to_ksemun64 (cmd, arg64, &ksemid);
> +  union ksemun64 arg = ksemun;
> +#else
> +  union semun arg = arg64;
>  #endif
>  
>    int ret = semctl_syscall (semid, semnum, cmd, arg);
> +  if (ret < 0)
> +    return ret;
>  
> -  if (ret >= 0)
> +  switch (cmd)
>      {
> -      switch (cmd)
> -	{
> -        case IPC_STAT:
> -        case SEM_STAT:
> -        case SEM_STAT_ANY:
> +    case IPC_STAT:
> +    case SEM_STAT:
> +    case SEM_STAT_ANY:
>  #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -          arg.buf->sem_perm.mode >>= 16;
> +      arg.buf->sem_perm.mode >>= 16;
>  #else
> -	  /* Old Linux kernel versions might not clear the mode padding.  */
> -	  if (sizeof ((struct semid_ds){0}.sem_perm.mode)
> -	      != sizeof (__kernel_mode_t))
> -	    arg.buf->sem_perm.mode &= 0xFFFF;
> +      /* Old Linux kernel versions might not clear the mode padding.  */
> +      if (sizeof ((struct semid_ds){0}.sem_perm.mode)
> +	  != sizeof (__kernel_mode_t))
> +	arg.buf->sem_perm.mode &= 0xFFFF;
>  #endif
> -	}
> +
> +#if __IPC_TIME64
> +      ksemid64_to_semid64 (arg.buf, arg64.buf);
> +#endif
> +    }
> +
> +  return ret;
> +}

OK.

> +#if __TIMESIZE != 64
> +libc_hidden_def (__semctl64)
> +
> +
> +/* The 64-bit time_t semid_ds version might have a different layout and
> +   internal field alignment.  */
> +static void
> +semid64_ds_to_semid_ds (struct semid_ds *ds, const struct __semid64_ds *ds64)
> +{
> +  ds->sem_perm = ds64->sem_perm;
> +  ds->sem_otime = ds64->sem_otime;
> +  ds->sem_ctime = ds64->sem_ctime;
> +  ds->sem_nsems = ds64->sem_nsems;
> +}
> +
> +static void
> +semid_ds_to_semid64_ds (struct __semid64_ds *ds64, const struct semid_ds *ds)
> +{
> +  ds64->sem_perm = ds->sem_perm;
> +  ds64->sem_otime = ds->sem_otime
> +		    | ((__time64_t) ds->__sem_otime_high << 32);
> +  ds64->sem_ctime = ds->sem_ctime
> +		    | ((__time64_t) ds->__sem_ctime_high << 32);
> +  ds64->sem_nsems = ds->sem_nsems;
> +}
> +
> +static union semun64
> +semun_to_semun64 (int cmd, union semun semun, struct __semid64_ds *semid64)
> +{
> +  union semun64 r = { 0 };
> +  switch (cmd)
> +    {
> +    case SETVAL:
> +      r.val = semun.val;
> +      break;
> +    case GETALL:
> +    case SETALL:
> +      r.array = semun.array;
> +      break;
> +    case IPC_STAT:
> +    case IPC_SET:
> +      r.buf = semid64;
> +      semid_ds_to_semid64_ds (r.buf, semun.buf);
> +# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> +      if (cmd == IPC_SET)
> +	r.buf->sem_perm.mode *= 0x10000U;
> +# endif
> +      break;
> +    case IPC_INFO:
> +    case SEM_INFO:
> +      r.__buf = semun.__buf;
> +      break;
> +    }
> +  return r;
> +}

OK.

> +
> +int
> +__semctl (int semid, int semnum, int cmd, ...)
> +{
> +  union semun arg = { 0 };
> +
> +  va_list ap;
> +
> +  /* Get the argument only if required.  */
> +  switch (cmd)
> +    {
> +    case SETVAL:        /* arg.val */
> +    case GETALL:        /* arg.array */
> +    case SETALL:
> +    case IPC_STAT:      /* arg.buf */
> +    case IPC_SET:
> +    case SEM_STAT:
> +    case IPC_INFO:      /* arg.__buf */
> +    case SEM_INFO:
> +      va_start (ap, cmd);
> +      arg = va_arg (ap, union semun);
> +      va_end (ap);
> +      break;
> +    }
> +
> +  struct __semid64_ds semid64;
> +  union semun64 arg64 = semun_to_semun64 (cmd, arg, &semid64);
> +
> +  int ret = __semctl64 (semid, semnum, cmd, arg64);

OK. Implement with __semctl64.

> +  if (ret < 0)
> +    return ret;
> +
> +  switch (cmd)
> +    {
> +    case IPC_STAT:
> +    case SEM_STAT:
> +    case SEM_STAT_ANY:
> +      semid64_ds_to_semid_ds (arg.buf, arg64.buf);
>      }
>  
>    return ret;
>  }
> -versioned_symbol (libc, __new_semctl, semctl, DEFAULT_VERSION);
> +#endif
> +
> +#ifndef DEFAULT_VERSION
> +# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
> +#  define DEFAULT_VERSION GLIBC_2_2
> +# else
> +#  define DEFAULT_VERSION GLIBC_2_31
> +# endif
> +#endif
> +versioned_symbol (libc, __semctl, semctl, DEFAULT_VERSION);
>  
>  #if defined __ASSUME_SYSVIPC_BROKEN_MODE_T \
>      && SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_31)
> @@ -121,7 +304,7 @@ int
>  attribute_compat_text_section
>  __semctl_mode16 (int semid, int semnum, int cmd, ...)
>  {
> -  union semun arg = { 0 };
> +  semctl_arg_t arg = { 0 };
>    va_list ap;
>  
>    /* Get the argument only if required.  */
> @@ -136,7 +319,7 @@ __semctl_mode16 (int semid, int semnum, int cmd, ...)
>      case IPC_INFO:      /* arg.__buf */
>      case SEM_INFO:
>        va_start (ap, cmd);
> -      arg = va_arg (ap, union semun);
> +      arg = va_arg (ap, semctl_arg_t);
>        va_end (ap);
>        break;
>      }
> 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
> index 46fcd79fb6..0110c1a940 100644
> --- a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_semid_ds.h
> +++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_semid_ds.h
> @@ -25,9 +25,9 @@ struct semid_ds
>  {
>    struct ipc_perm sem_perm;   /* operation permission struct */
>  #if __TIMESIZE == 32
> -  __syscall_ulong_t __glibc_reserved1;
> +  __syscall_ulong_t __sem_otime_high;
>    __time_t sem_otime;         /* last semop() time */
> -  __syscall_ulong_t __glibc_reserved2;
> +  __syscall_ulong_t __sem_ctime_high;

OK.

>    __time_t sem_ctime;        /* last time changed by semctl() */
>  #else
>    __time_t sem_otime;         /* last semop() time */
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_semid64_ds.h
> new file mode 100644
> index 0000000000..8c4697f9ab
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_semid64_ds.h
> @@ -0,0 +1,12 @@
> +/* Analogous to kernel struct semid64_ds used on semctl.  */
> +struct kernel_semid64_ds
> +{
> +  struct ipc_perm sem_perm;
> +  unsigned long sem_otime_high;
> +  unsigned long sem_otime;
> +  unsigned long sem_ctime_high;
> +  unsigned long sem_ctime;

OK. Matches sparc32.

> +  unsigned long sem_nsems;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/struct_kernel_semid64_ds.h
> new file mode 100644
> index 0000000000..f9edf0f76f
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/struct_kernel_semid64_ds.h
> @@ -0,0 +1,12 @@
> +/* Analogous to kernel struct semid64_ds used on semctl.  */
> +struct kernel_semid64_ds
> +{
> +  struct ipc_perm sem_perm;
> +  unsigned long sem_otime;
> +  unsigned long sem_otime_high;
> +  unsigned long sem_ctime;
> +  unsigned long sem_ctime_high;
> +  unsigned long sem_nsems;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h
> index f7ec89d115..c3f2fde9fd 100644
> --- a/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h
> +++ b/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h
> @@ -25,9 +25,9 @@ struct semid_ds
>  {
>    struct ipc_perm sem_perm;   /* operation permission struct */
>    __time_t sem_otime;  /* last semop() time */
> -  __syscall_ulong_t __glibc_reserved1;
> +  __syscall_ulong_t __sem_otime_high;
>    __time_t sem_ctime;  /* last time changed by semctl() */
> -  __syscall_ulong_t __glibc_reserved2;
> +  __syscall_ulong_t __sem_ctime_high;
>    __syscall_ulong_t sem_nsems;    /* number of semaphores in set */
>    __syscall_ulong_t __glibc_reserved3;
>    __syscall_ulong_t __glibc_reserved4;
> 

OK.

-- 
Cheers,
Carlos.


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

* Re: [PATCH 1/7] sysv: linux: Add 64-bit time_t variant for semctl
  2020-07-07  3:32 ` Carlos O'Donell
@ 2020-07-07 14:09   ` Adhemerval Zanella
  2020-07-08 15:32     ` [PATCH v2] " Adhemerval Zanella
  0 siblings, 1 reply; 41+ messages in thread
From: Adhemerval Zanella @ 2020-07-07 14:09 UTC (permalink / raw)
  To: Carlos O'Donell; +Cc: GNU C Library, Stepan Golosunov, Alistair Francis

On Tue, Jul 7, 2020 at 12:32 AM Carlos O'Donell <carlos@redhat.com> wrote:
>
> On 6/30/20 3:24 PM, Adhemerval Zanella via Libc-alpha wrote:
>
> OK for master with comment cleanups. Very clean, very easy to understand
> patch. I should finish the other 6 patches tomorrow morning.

Ack, I have included all your comment suggestions changes.

>
> No regressions on x86_64 or i686 (I did see the new rseq regression
> for posix/tst-affinity-static though).
>
> Reviewed-by: Carlos O'Donell <carlos@redhat.com>
> Tested-by: Carlos O'Donell <carlos@redhat.com>

Thanks!

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

* Re: [PATCH 2/7] sysvipc: Split out linux struct semid_ds
  2020-06-30 19:24 ` [PATCH 2/7] sysvipc: Split out linux struct semid_ds Adhemerval Zanella
  2020-07-02 21:20   ` Alistair Francis
@ 2020-07-07 19:01   ` Carlos O'Donell
  1 sibling, 0 replies; 41+ messages in thread
From: Carlos O'Donell @ 2020-07-07 19:01 UTC (permalink / raw)
  To: Adhemerval Zanella, libc-alpha; +Cc: stepan, Alistair Francis

On 6/30/20 3:24 PM, Adhemerval Zanella via Libc-alpha wrote:
> This will allow us to have architectures specify their own version.
> 
> Not semantic changes expected.  Checked with a build against the
> all affected ABIs.

OK for master.

No regressions on x86_64 or i686.

Tested-by: Carlos O'Donell <carlos@redhat.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> ---
>  sysdeps/unix/sysv/linux/Makefile              |  1 +
>  sysdeps/unix/sysv/linux/bits/msq.h            | 39 +++-----------
>  .../sysv/linux/bits/types/struct_msqid_ds.h   | 51 +++++++++++++++++++
>  3 files changed, 58 insertions(+), 33 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> 
> diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
> index e02065dc8d..70e2d9e044 100644
> --- a/sysdeps/unix/sysv/linux/Makefile
> +++ b/sysdeps/unix/sysv/linux/Makefile
> @@ -92,6 +92,7 @@ sysdep_headers += sys/mount.h sys/acct.h \
>  		  bits/termios-c_lflag.h bits/termios-tcflow.h \
>  		  bits/termios-misc.h \
>  		  bits/types/struct_semid_ds.h \
> +		  bits/types/struct_msqid_ds.h \

OK.

>  		  bits/ipc-perm.h
>  
>  tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
> diff --git a/sysdeps/unix/sysv/linux/bits/msq.h b/sysdeps/unix/sysv/linux/bits/msq.h
> index cc4ebae0f0..6ce6408ebc 100644
> --- a/sysdeps/unix/sysv/linux/bits/msq.h
> +++ b/sysdeps/unix/sysv/linux/bits/msq.h
> @@ -20,7 +20,12 @@
>  #endif
>  
>  #include <bits/types.h>
> -#include <bits/msq-pad.h>
> +
> +/* Types used in the MSQID_DS structure definition.  */
> +typedef __syscall_ulong_t msgqnum_t;
> +typedef __syscall_ulong_t msglen_t;
> +
> +#include <bits/types/struct_msqid_ds.h>

OK.

>  
>  /* Define options for message queue functions.  */
>  #define MSG_NOERROR	010000	/* no error if message is too big */
> @@ -29,38 +34,6 @@
>  # define MSG_COPY	040000	/* copy (not remove) all queue messages */
>  #endif
>  
> -/* Types used in the structure definition.  */
> -typedef __syscall_ulong_t msgqnum_t;
> -typedef __syscall_ulong_t msglen_t;
> -
> -#if __MSQ_PAD_BEFORE_TIME
> -# define __MSQ_PAD_TIME(NAME, RES)				\
> -  unsigned long int __glibc_reserved ## RES; __time_t NAME
> -#elif __MSQ_PAD_AFTER_TIME
> -# define __MSQ_PAD_TIME(NAME, RES)				\
> -  __time_t NAME; unsigned long int __glibc_reserved ## RES
> -#else
> -# define __MSQ_PAD_TIME(NAME, RES)		\
> -  __time_t NAME
> -#endif
> -
> -/* Structure of record for one message inside the kernel.
> -   The type `struct msg' is opaque.  */
> -struct msqid_ds
> -{
> -  struct ipc_perm msg_perm;	/* structure describing operation permission */
> -  __MSQ_PAD_TIME (msg_stime, 1);	/* time of last msgsnd command */
> -  __MSQ_PAD_TIME (msg_rtime, 2);	/* time of last msgrcv command */
> -  __MSQ_PAD_TIME (msg_ctime, 3);	/* time of last change */
> -  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
> -  msgqnum_t msg_qnum;		/* number of messages currently on queue */
> -  msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
> -  __pid_t msg_lspid;		/* pid of last msgsnd() */
> -  __pid_t msg_lrpid;		/* pid of last msgrcv() */
> -  __syscall_ulong_t __glibc_reserved4;
> -  __syscall_ulong_t __glibc_reserved5;
> -};
> -
>  #ifdef __USE_MISC
>  
>  # define msg_cbytes	__msg_cbytes
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> new file mode 100644
> index 0000000000..bfc56f6ac1
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> @@ -0,0 +1,51 @@
> +/* Generic implementation of the SysV message struct msqid_ds.
> +   Copyright (C) 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_MSG_H
> +# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
> +#endif
> +
> +#include <bits/msq-pad.h>
> +
> +#if __MSQ_PAD_BEFORE_TIME
> +# define __MSQ_PAD_TIME(NAME, RES)				\
> +  unsigned long int __glibc_reserved ## RES; __time_t NAME
> +#elif __MSQ_PAD_AFTER_TIME
> +# define __MSQ_PAD_TIME(NAME, RES)				\
> +  __time_t NAME; unsigned long int __glibc_reserved ## RES
> +#else
> +# define __MSQ_PAD_TIME(NAME, RES)		\
> +  __time_t NAME
> +#endif

OK.

> +
> +/* Structure of record for one message inside the kernel.
> +   The type `struct msg' is opaque.  */
> +struct msqid_ds
> +{
> +  struct ipc_perm msg_perm;	/* structure describing operation permission */
> +  __MSQ_PAD_TIME (msg_stime, 1);	/* time of last msgsnd command */
> +  __MSQ_PAD_TIME (msg_rtime, 2);	/* time of last msgrcv command */
> +  __MSQ_PAD_TIME (msg_ctime, 3);	/* time of last change */
> +  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
> +  msgqnum_t msg_qnum;		/* number of messages currently on queue */
> +  msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
> +  __pid_t msg_lspid;		/* pid of last msgsnd() */
> +  __pid_t msg_lrpid;		/* pid of last msgrcv() */
> +  __syscall_ulong_t __glibc_reserved4;
> +  __syscall_ulong_t __glibc_reserved5;
> +};
> 


-- 
Cheers,
Carlos.


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

* Re: [PATCH 3/7] sysvipc: Remove the linux msq-pad.h file
  2020-06-30 19:24 ` [PATCH 3/7] sysvipc: Remove the linux msq-pad.h file Adhemerval Zanella
  2020-07-02 21:26   ` Alistair Francis
@ 2020-07-07 19:05   ` Carlos O'Donell
  1 sibling, 0 replies; 41+ messages in thread
From: Carlos O'Donell @ 2020-07-07 19:05 UTC (permalink / raw)
  To: Adhemerval Zanella, libc-alpha; +Cc: stepan, Alistair Francis

On 6/30/20 3:24 PM, Adhemerval Zanella via Libc-alpha wrote:
> Each architecture overrides the struct msqid_ds which its required
> kernel ABI one.
> 
> Checked on x86_64-linux-gnu and some bases sysvipc tests on hppa,
> mips, mipsle, mips64, mips64le, sparc64, sparcv9, powerpc64le,
> powerpc64, and powerpc.

OK for master with one comment fix.

No regressions on x86_64 and i686.

Tested-by: Carlos O'Donell <carlos@redhat.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> ---
>  sysdeps/unix/sysv/linux/Makefile              |  2 +-
>  sysdeps/unix/sysv/linux/bits/msq-pad.h        | 31 ----------
>  .../sysv/linux/bits/types/struct_msqid_ds.h   | 28 ++++------
>  sysdeps/unix/sysv/linux/hppa/bits/msq-pad.h   | 26 ---------
>  .../linux/hppa/bits/types/struct_msqid_ds.h   | 47 ++++++++++++++++
>  sysdeps/unix/sysv/linux/mips/bits/msq-pad.h   | 31 ----------
>  .../linux/mips/bits/types/struct_msqid_ds.h   | 56 +++++++++++++++++++
>  .../unix/sysv/linux/powerpc/bits/msq-pad.h    | 26 ---------
>  .../powerpc/bits/types/struct_msqid_ds.h      | 47 ++++++++++++++++
>  sysdeps/unix/sysv/linux/sparc/bits/msq-pad.h  | 26 ---------
>  .../linux/sparc/bits/types/struct_msqid_ds.h  | 47 ++++++++++++++++
>  11 files changed, 210 insertions(+), 157 deletions(-)
>  delete mode 100644 sysdeps/unix/sysv/linux/bits/msq-pad.h
>  delete mode 100644 sysdeps/unix/sysv/linux/hppa/bits/msq-pad.h
>  create mode 100644 sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
>  delete mode 100644 sysdeps/unix/sysv/linux/mips/bits/msq-pad.h
>  create mode 100644 sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
>  delete mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/msq-pad.h
>  create mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
>  delete mode 100644 sysdeps/unix/sysv/linux/sparc/bits/msq-pad.h
>  create mode 100644 sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
> 
> diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
> index 70e2d9e044..505087e617 100644
> --- a/sysdeps/unix/sysv/linux/Makefile
> +++ b/sysdeps/unix/sysv/linux/Makefile
> @@ -85,7 +85,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/shmlba.h bits/shm-pad.h \
> +		  bits/shmlba.h bits/shm-pad.h \

OK. Remove msq-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/msq-pad.h b/sysdeps/unix/sysv/linux/bits/msq-pad.h
> deleted file mode 100644
> index e4ffd39f27..0000000000
> --- a/sysdeps/unix/sysv/linux/bits/msq-pad.h
> +++ /dev/null
> @@ -1,31 +0,0 @@
> -/* Define where padding goes in struct msqid_ds.  Generic 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_MSG_H
> -# error "Never use <bits/msq-pad.h> directly; include <sys/msg.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.  */
> -
> -#define __MSQ_PAD_AFTER_TIME (__TIMESIZE == 32)
> -#define __MSQ_PAD_BEFORE_TIME 0

OK. No generic version required.

> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> index bfc56f6ac1..32173a7b60 100644
> --- a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> @@ -20,27 +20,23 @@
>  # error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
>  #endif
>  
> -#include <bits/msq-pad.h>
> -
> -#if __MSQ_PAD_BEFORE_TIME
> -# define __MSQ_PAD_TIME(NAME, RES)				\
> -  unsigned long int __glibc_reserved ## RES; __time_t NAME
> -#elif __MSQ_PAD_AFTER_TIME
> -# define __MSQ_PAD_TIME(NAME, RES)				\
> -  __time_t NAME; unsigned long int __glibc_reserved ## RES
> -#else
> -# define __MSQ_PAD_TIME(NAME, RES)		\
> -  __time_t NAME
> -#endif
> -
>  /* Structure of record for one message inside the kernel.
>     The type `struct msg' is opaque.  */
>  struct msqid_ds
>  {
>    struct ipc_perm msg_perm;	/* structure describing operation permission */
> -  __MSQ_PAD_TIME (msg_stime, 1);	/* time of last msgsnd command */
> -  __MSQ_PAD_TIME (msg_rtime, 2);	/* time of last msgrcv command */
> -  __MSQ_PAD_TIME (msg_ctime, 3);	/* time of last change */
> +#if __TIMESIZE == 32
> +  __time_t msg_stime;		/* time of last msgsnd command */
> +  unsigned long int __glibc_reserved1;
> +  __time_t msg_rtime;		/* time of last msgsnd command */
> +  unsigned long int __glibc_reserved2;
> +  __time_t msg_ctime;		/* time of last change */
> +  unsigned long int __glibc_reserved3;
> +#else
> +  __time_t msg_stime;		/* time of last msgsnd command */
> +  __time_t msg_rtime;		/* time of last msgsnd command */
> +  __time_t msg_ctime;		/* time of last change */
> +#endif

OK. Generic linux version.

>    __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
>    msgqnum_t msg_qnum;		/* number of messages currently on queue */
>    msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
> diff --git a/sysdeps/unix/sysv/linux/hppa/bits/msq-pad.h b/sysdeps/unix/sysv/linux/hppa/bits/msq-pad.h
> deleted file mode 100644
> index 6986585ae7..0000000000
> --- a/sysdeps/unix/sysv/linux/hppa/bits/msq-pad.h
> +++ /dev/null
> @@ -1,26 +0,0 @@
> -/* Define where padding goes in struct msqid_ds.  HPPA 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_MSG_H
> -# error "Never use <bits/msq-pad.h> directly; include <sys/msg.h> instead."
> -#endif
> -
> -#include <bits/timesize.h>
> -
> -#define __MSQ_PAD_AFTER_TIME 0
> -#define __MSQ_PAD_BEFORE_TIME (__TIMESIZE == 32)

OK.

> diff --git a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
> new file mode 100644
> index 0000000000..3cf70e36c4
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
> @@ -0,0 +1,47 @@
> +/* Linux/HPPA implementation of the SysV message struct msqid_ds.
> +   Copyright (C) 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_MSG_H
> +# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
> +#endif
> +
> +/* Structure of record for one message inside the kernel.
> +   The type `struct msg' is opaque.  */
> +struct msqid_ds
> +{
> +  struct ipc_perm msg_perm;	/* structure describing operation permission */
> +#if __TIMESIZE == 32
> +  unsigned long int __glibc_reserved1;
> +  __time_t msg_stime;		/* time of last msgsnd command */
> +  unsigned long int __glibc_reserved2;
> +  __time_t msg_rtime;		/* time of last msgsnd command */
> +  unsigned long int __glibc_reserved3;
> +  __time_t msg_ctime;		/* time of last change */
> +#else
> +  __time_t msg_stime;		/* time of last msgsnd command */
> +  __time_t msg_rtime;		/* time of last msgsnd command */
> +  __time_t msg_ctime;		/* time of last change */
> +#endif
> +  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
> +  msgqnum_t msg_qnum;		/* number of messages currently on queue */
> +  msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
> +  __pid_t msg_lspid;		/* pid of last msgsnd() */
> +  __pid_t msg_lrpid;		/* pid of last msgrcv() */
> +  __syscall_ulong_t __glibc_reserved4;
> +  __syscall_ulong_t __glibc_reserved5;
> +};

OK. Specific definition for hppa.

> diff --git a/sysdeps/unix/sysv/linux/mips/bits/msq-pad.h b/sysdeps/unix/sysv/linux/mips/bits/msq-pad.h
> deleted file mode 100644
> index 8e28c5abe1..0000000000
> --- a/sysdeps/unix/sysv/linux/mips/bits/msq-pad.h
> +++ /dev/null
> @@ -1,31 +0,0 @@
> -/* Define where padding goes in struct msqid_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_MSG_H
> -# error "Never use <bits/msq-pad.h> directly; include <sys/msg.h> instead."
> -#endif
> -
> -#include <bits/timesize.h>
> -
> -#ifdef __MIPSEL__
> -# define __MSQ_PAD_AFTER_TIME (__TIMESIZE == 32)
> -# define __MSQ_PAD_BEFORE_TIME 0
> -#else
> -# define __MSQ_PAD_AFTER_TIME 0
> -# define __MSQ_PAD_BEFORE_TIME (__TIMESIZE == 32)
> -#endif

OK.

> diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
> new file mode 100644
> index 0000000000..85fdeef274
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
> @@ -0,0 +1,56 @@
> +/* Linux/PowerPC implementation of the SysV message struct msqid_ds.

s/PowerPC/MIPS/g

> +   Copyright (C) 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_MSG_H
> +# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
> +#endif
> +
> +/* Structure of record for one message inside the kernel.
> +   The type `struct msg' is opaque.  */
> +struct msqid_ds
> +{
> +  struct ipc_perm msg_perm;	/* structure describing operation permission */
> +#if __TIMESIZE == 32
> +# ifdef __MIPSEL__
> +  __time_t msg_stime;		/* time of last msgsnd command */
> +  unsigned long int __glibc_reserved1;
> +  __time_t msg_rtime;		/* time of last msgsnd command */
> +  unsigned long int __glibc_reserved2;
> +  __time_t msg_ctime;		/* time of last change */
> +  unsigned long int __glibc_reserved3;
> +# else
> +  unsigned long int __glibc_reserved1;
> +  __time_t msg_stime;		/* time of last msgsnd command */
> +  unsigned long int __glibc_reserved2;
> +  __time_t msg_rtime;		/* time of last msgsnd command */
> +  unsigned long int __glibc_reserved3;
> +  __time_t msg_ctime;		/* time of last change */
> +# endif
> +#else
> +  __time_t msg_stime;		/* time of last msgsnd command */
> +  __time_t msg_rtime;		/* time of last msgsnd command */
> +  __time_t msg_ctime;		/* time of last change */
> +#endif
> +  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
> +  msgqnum_t msg_qnum;		/* number of messages currently on queue */
> +  msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
> +  __pid_t msg_lspid;		/* pid of last msgsnd() */
> +  __pid_t msg_lrpid;		/* pid of last msgrcv() */
> +  __syscall_ulong_t __glibc_reserved4;
> +  __syscall_ulong_t __glibc_reserved5;
> +};
> diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/msq-pad.h b/sysdeps/unix/sysv/linux/powerpc/bits/msq-pad.h
> deleted file mode 100644
> index e2b9310800..0000000000
> --- a/sysdeps/unix/sysv/linux/powerpc/bits/msq-pad.h
> +++ /dev/null
> @@ -1,26 +0,0 @@
> -/* Define where padding goes in struct msqid_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_MSG_H
> -# error "Never use <bits/msq-pad.h> directly; include <sys/msg.h> instead."
> -#endif
> -
> -#include <bits/timesize.h>
> -
> -#define __MSQ_PAD_AFTER_TIME 0
> -#define __MSQ_PAD_BEFORE_TIME (__TIMESIZE == 32)

OK.

> diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
> new file mode 100644
> index 0000000000..4ae2fbcbdc
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
> @@ -0,0 +1,47 @@
> +/* Linux/PowerPC implementation of the SysV message struct msqid_ds.

OK.

> +   Copyright (C) 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_MSG_H
> +# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
> +#endif
> +
> +/* Structure of record for one message inside the kernel.
> +   The type `struct msg' is opaque.  */
> +struct msqid_ds
> +{
> +  struct ipc_perm msg_perm;	/* structure describing operation permission */
> +#if __TIMESIZE == 32
> +  unsigned long int __glibc_reserved1;
> +  __time_t msg_stime;		/* time of last msgsnd command */
> +  unsigned long int __glibc_reserved2;
> +  __time_t msg_rtime;		/* time of last msgsnd command */
> +  unsigned long int __glibc_reserved3;
> +  __time_t msg_ctime;		/* time of last change */
> +#else
> +  __time_t msg_stime;		/* time of last msgsnd command */
> +  __time_t msg_rtime;		/* time of last msgsnd command */
> +  __time_t msg_ctime;		/* time of last change */
> +#endif
> +  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
> +  msgqnum_t msg_qnum;		/* number of messages currently on queue */
> +  msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
> +  __pid_t msg_lspid;		/* pid of last msgsnd() */
> +  __pid_t msg_lrpid;		/* pid of last msgrcv() */
> +  __syscall_ulong_t __glibc_reserved4;
> +  __syscall_ulong_t __glibc_reserved5;
> +};
> diff --git a/sysdeps/unix/sysv/linux/sparc/bits/msq-pad.h b/sysdeps/unix/sysv/linux/sparc/bits/msq-pad.h
> deleted file mode 100644
> index 99fdf8c8f0..0000000000
> --- a/sysdeps/unix/sysv/linux/sparc/bits/msq-pad.h
> +++ /dev/null
> @@ -1,26 +0,0 @@
> -/* Define where padding goes in struct msqid_ds.  SPARC 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_MSG_H
> -# error "Never use <bits/msq-pad.h> directly; include <sys/msg.h> instead."
> -#endif
> -
> -#include <bits/timesize.h>
> -
> -#define __MSQ_PAD_AFTER_TIME 0
> -#define __MSQ_PAD_BEFORE_TIME (__TIMESIZE == 32)

OK.

> diff --git a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
> new file mode 100644
> index 0000000000..71980839c7
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
> @@ -0,0 +1,47 @@
> +/* Linux/SPARC implementation of the SysV message struct msqid_ds.

OK.

> +   Copyright (C) 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_MSG_H
> +# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
> +#endif
> +
> +/* Structure of record for one message inside the kernel.
> +   The type `struct msg' is opaque.  */
> +struct msqid_ds
> +{
> +  struct ipc_perm msg_perm;	/* structure describing operation permission */
> +#if __TIMESIZE == 32
> +  unsigned long int __glibc_reserved1;
> +  __time_t msg_stime;		/* time of last msgsnd command */
> +  unsigned long int __glibc_reserved2;
> +  __time_t msg_rtime;		/* time of last msgsnd command */
> +  unsigned long int __glibc_reserved3;
> +  __time_t msg_ctime;		/* time of last change */
> +#else
> +  __time_t msg_stime;		/* time of last msgsnd command */
> +  __time_t msg_rtime;		/* time of last msgsnd command */
> +  __time_t msg_ctime;		/* time of last change */
> +#endif
> +  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
> +  msgqnum_t msg_qnum;		/* number of messages currently on queue */
> +  msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
> +  __pid_t msg_lspid;		/* pid of last msgsnd() */
> +  __pid_t msg_lrpid;		/* pid of last msgrcv() */
> +  __syscall_ulong_t __glibc_reserved4;
> +  __syscall_ulong_t __glibc_reserved5;
> +};
> 

OK.

-- 
Cheers,
Carlos.


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

* Re: [PATCH 4/7] sysv: linux: Add 64-bit time_t variant for msgctl
  2020-06-30 19:24 ` [PATCH 4/7] sysv: linux: Add 64-bit time_t variant for msgctl Adhemerval Zanella
  2020-07-02 21:39   ` Alistair Francis
@ 2020-07-07 19:51   ` Carlos O'Donell
  2020-07-08 15:32     ` [PATCH v2] " Adhemerval Zanella
  1 sibling, 1 reply; 41+ messages in thread
From: Carlos O'Donell @ 2020-07-07 19:51 UTC (permalink / raw)
  To: Adhemerval Zanella, libc-alpha; +Cc: stepan, Alistair Francis

On 6/30/20 3:24 PM, Adhemerval Zanella via Libc-alpha wrote:

OK for master with textual changes.

Tested on x86_64 and i686.

Tested-by: Carlos O'Donell <carlos@redhat.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> To provide a y2038 safe interface a new symbol __msgctl64 is added
> and __msgctl is change to call it instead (it adds some extra buffer
> copy for the 32 bit time_t implementation).

s/copy/copying/g

> 
> Two two new structures are added:

s/Two two/Two/g

> 
>   1. kernel_msqid64_ds: used internally only on 32-bit architectures
>      to issue the syscall.  A handful architectures (hppa, i386, mips,

s/handful/handful of/g

>      powerpc32, and sparc32) requires specific implementation due its
>      specific kernel ABI.
> 

Suggest:

require specific implementations due to their kernel ABI.

(get to reuse my text from 0/7 ;-))

>   2. msqid_ds64: this is only for __TIMESIZE != 64 to use along with
>      the 64-bit semctl.  It is different than the kernel one because

s/one/struct/g

>      the exported 64-bit time_t might require different alignment
>      depending of the architecture ABI.

s/of/on/g (fix in 0/7 also required)

> 
> So the resulting implementation does:
> 
>   1. For 64-bit architectures it assumes msqid_ds already contains
>      64-bit time_t fields it will result in just the __msgctl symbol

s/it/and/g

>      using the __msgctl64 code.  The msgid_ds argument is passed as-is
>      to the syscall.
> 
>   2. For 32-bit architectures with default 64-bit time_t (newer ABIs
>      such riscv32 or arc), it will also result in only one exported
>      symbol but with the required high/low time handling.
> 
>   3. Finally for 32-bit architecture with both 32-bit and 64-bit time_t
>      support we follow the already set way to provide one symbol with
>      64-bit time_t support and implement the 32-bit time_t support on
>      basis of the 64-bit one.

s/on basis of/using/g
s/one/time_t/g

>      The default 32-bit symbol will allocate and copy the msqid_ds
>      over multiple buffers, but this should be deprecated in favor
>      of the __msgctl64 anyway.
> 
> Checked on i686-linux-gnu and x86_64-linux-gnu.  I also did some sniff
> tests on powerpc, powerpc64, mips, mips64, armhf, sparcv9, and
> sparc64.
> ---
>  include/sys/msg.h                             |  10 +
>  .../sysv/linux/bits/types/struct_msqid64_ds.h |  38 ++++
>  .../sysv/linux/bits/types/struct_msqid_ds.h   |   6 +-
>  .../linux/hppa/bits/types/struct_msqid_ds.h   |   6 +-
>  .../linux/hppa/struct_kernel_msqid64_ds.h     |  18 ++
>  .../linux/i386/struct_kernel_msqid64_ds.h     |  18 ++
>  .../linux/mips/bits/types/struct_msqid_ds.h   |  12 +-
>  .../linux/mips/struct_kernel_msqid64_ds.h     |  33 ++++
>  sysdeps/unix/sysv/linux/msgctl.c              | 179 ++++++++++++++----
>  .../powerpc/bits/types/struct_msqid_ds.h      |   6 +-
>  .../powerpc32/struct_kernel_msqid64_ds.h      |  18 ++
>  sysdeps/unix/sysv/linux/semctl.c              |  27 +--
>  .../linux/sparc/bits/types/struct_msqid_ds.h  |   6 +-
>  .../sparc/sparc32/struct_kernel_msqid64_ds.h  |  18 ++
>  .../sysv/linux/struct_kernel_msqid64_ds.h     |  19 ++
>  15 files changed, 350 insertions(+), 64 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h
> 
> diff --git a/include/sys/msg.h b/include/sys/msg.h
> index 43ec5b9472..522903f818 100644
> --- a/include/sys/msg.h
> +++ b/include/sys/msg.h
> @@ -6,6 +6,16 @@ extern ssize_t __libc_msgrcv (int msqid, void *msgp, size_t msgsz,
>  			      long int msgtyp, int msgflg);
>  extern int __libc_msgsnd (int msqid, const void *msgp, size_t msgsz,
>  			  int msgflg);
> +
> +# include <bits/types/struct_msqid64_ds.h>
> +
> +# if __TIMESIZE == 64
> +#  define __msgctl64 __msgctl
> +# else
> +extern int __msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf);
> +libc_hidden_proto (__msgctl64);

OK.

> +# endif
> +
>  #endif
>  
>  #endif
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h
> new file mode 100644
> index 0000000000..3536c8ea62
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h
> @@ -0,0 +1,38 @@
> +/* Generic implementation of the SysV message struct msqid64_ds.

OK.

> +   Copyright (C) 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_MSG_H
> +# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
> +#endif
> +
> +#if __TIMESIZE == 64
> +# define __msqid64_ds msqid_ds
> +#else
> +struct __msqid64_ds
> +{
> +  struct ipc_perm msg_perm;	/* structure describing operation permission */
> +  __time64_t msg_stime;		/* time of last msgsnd command */
> +  __time64_t msg_rtime;		/* time of last msgsnd command */
> +  __time64_t msg_ctime;		/* time of last change */

OK.

> +  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
> +  msgqnum_t msg_qnum;		/* number of messages currently on queue */
> +  msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
> +  __pid_t msg_lspid;		/* pid of last msgsnd() */
> +  __pid_t msg_lrpid;		/* pid of last msgrcv() */
> +};
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> index 32173a7b60..43b38175ad 100644
> --- a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> @@ -27,11 +27,11 @@ struct msqid_ds
>    struct ipc_perm msg_perm;	/* structure describing operation permission */
>  #if __TIMESIZE == 32
>    __time_t msg_stime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_rtime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_ctime;		/* time of last change */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;

OK.

>  #else
>    __time_t msg_stime;		/* time of last msgsnd command */
>    __time_t msg_rtime;		/* time of last msgsnd command */
> diff --git a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
> index 3cf70e36c4..16eac46941 100644
> --- a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
> @@ -26,11 +26,11 @@ struct msqid_ds
>  {
>    struct ipc_perm msg_perm;	/* structure describing operation permission */
>  #if __TIMESIZE == 32
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_stime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_rtime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;

OK

>    __time_t msg_ctime;		/* time of last change */
>  #else
>    __time_t msg_stime;		/* time of last msgsnd command */
> diff --git a/sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..69a63ee27a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long msg_stime_high;
> +  unsigned long msg_stime;
> +  unsigned long msg_rtime_high;
> +  unsigned long msg_rtime;
> +  unsigned long msg_ctime_high;
> +  unsigned long msg_ctime;

OK.

> +  unsigned long msg_cbytes;
> +  unsigned long msg_qnum;
> +  unsigned long msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..65b940567b
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct compat_msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long msg_stime;
> +  unsigned long msg_stime_high;
> +  unsigned long msg_rtime;
> +  unsigned long msg_rtime_high;
> +  unsigned long msg_ctime;
> +  unsigned long msg_ctime_high;

OK.

> +  unsigned long msg_cbytes;
> +  unsigned long msg_qnum;
> +  unsigned long msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
> index 85fdeef274..9ff010c763 100644
> --- a/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
> @@ -28,17 +28,17 @@ struct msqid_ds
>  #if __TIMESIZE == 32
>  # ifdef __MIPSEL__
>    __time_t msg_stime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_rtime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_ctime;		/* time of last change */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>  # else
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_stime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_rtime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;

OK.

>    __time_t msg_ctime;		/* time of last change */
>  # endif
>  #else
> diff --git a/sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..9cfd5a0dfe
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,33 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +#if __TIMESIZE == 32
> +# ifdef __MIPSEL__
> +  unsigned long int msg_stime;
> +  unsigned long int msg_stime_high;
> +  unsigned long int msg_rtime;
> +  unsigned long int msg_rtime_high;
> +  unsigned long int msg_ctime;
> +  unsigned long int msg_ctime_high;
> +# else
> +  unsigned long int msg_stime_high;
> +  unsigned long int msg_stime;
> +  unsigned long int msg_rtime_high;
> +  unsigned long int msg_rtime;
> +  unsigned long int msg_ctime_high;
> +  unsigned long int msg_ctime;

OK.

> +# endif
> +#else
> +  unsigned long int msg_stime;
> +  unsigned long int msg_rtime;
> +  unsigned long int msg_ctime;
> +#endif
> +  unsigned long int msg_cbytes;
> +  unsigned long int msg_qnum;
> +  unsigned long int msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long int __unused1;
> +  unsigned long int __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c
> index fd46aec1a0..a7f7651280 100644
> --- a/sysdeps/unix/sysv/linux/msgctl.c
> +++ b/sysdeps/unix/sysv/linux/msgctl.c
> @@ -23,16 +23,55 @@
>  #include <errno.h>
>  #include <linux/posix_types.h>  /* For __kernel_mode_t.  */
>  
> -#ifndef DEFAULT_VERSION
> -# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -#  define DEFAULT_VERSION GLIBC_2_2
> -# else
> -#  define DEFAULT_VERSION GLIBC_2_31
> -# endif
> +/* POSIX states ipc_perm mode should have type of mode_t.  */
> +_Static_assert (sizeof ((struct msqid_ds){0}.msg_perm.mode)
> +		== sizeof (mode_t),
> +		"sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");

OK.

> +
> +#if __IPC_TIME64 == 0
> +typedef struct msqid_ds msgctl_arg_t;
> +#else
> +# include <struct_kernel_msqid64_ds.h>
> +
> +static void
> +msqid64_to_kmsqid64 (const struct __msqid64_ds *msqid64,
> +		     struct kernel_msqid64_ds *kmsqid)
> +{
> +  kmsqid->msg_perm       = msqid64->msg_perm;
> +  kmsqid->msg_stime      = msqid64->msg_stime;
> +  kmsqid->msg_stime_high = msqid64->msg_stime >> 32;
> +  kmsqid->msg_rtime      = msqid64->msg_rtime;
> +  kmsqid->msg_rtime_high = msqid64->msg_rtime >> 32;
> +  kmsqid->msg_ctime      = msqid64->msg_ctime;
> +  kmsqid->msg_ctime_high = msqid64->msg_ctime >> 32;
> +  kmsqid->msg_qnum       = msqid64->msg_qnum;
> +  kmsqid->msg_qbytes     = msqid64->msg_qbytes;
> +  kmsqid->msg_lspid      = msqid64->msg_lspid;
> +  kmsqid->msg_lrpid      = msqid64->msg_lrpid;
> +}

OK.

> +
> +static void
> +kmsqid64_to_msqid64 (const struct kernel_msqid64_ds *kmsqid,
> +		     struct __msqid64_ds *msqid64)
> +{
> +  msqid64->msg_perm   = kmsqid->msg_perm;
> +  msqid64->msg_stime  = kmsqid->msg_stime
> +		        | ((__time64_t) kmsqid->msg_stime_high << 32);
> +  msqid64->msg_rtime  = kmsqid->msg_rtime
> +		        | ((__time64_t) kmsqid->msg_rtime_high << 32);
> +  msqid64->msg_ctime  = kmsqid->msg_ctime
> +		        | ((__time64_t) kmsqid->msg_ctime_high << 32);
> +  msqid64->msg_qnum   = kmsqid->msg_qnum;
> +  msqid64->msg_qbytes = kmsqid->msg_qbytes;
> +  msqid64->msg_lspid  = kmsqid->msg_lspid;
> +  msqid64->msg_lrpid  = kmsqid->msg_lrpid;
> +}

OK.

> +
> +typedef struct kernel_msqid64_ds msgctl_arg_t;
>  #endif
>  
>  static int
> -msgctl_syscall (int msqid, int cmd, struct msqid_ds *buf)
> +msgctl_syscall (int msqid, int cmd, msgctl_arg_t *buf)
>  {
>  #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
>    return INLINE_SYSCALL_CALL (msgctl, msqid, cmd | __IPC_64, buf);
> @@ -43,46 +82,118 @@ msgctl_syscall (int msqid, int cmd, struct msqid_ds *buf)
>  }
>  
>  int
> -__new_msgctl (int msqid, int cmd, struct msqid_ds *buf)
> +__msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf)
>  {
> -  /* POSIX states ipc_perm mode should have type of mode_t.  */
> -  _Static_assert (sizeof ((struct msqid_ds){0}.msg_perm.mode)
> -		  == sizeof (mode_t),
> -		  "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");
> -
> -#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -  struct msqid_ds tmpds;
> -  if (cmd == IPC_SET)
> +#if __IPC_TIME64
> +  struct kernel_msqid64_ds ksemid, *arg = NULL;
> +  if (buf != NULL)
>      {
> -      tmpds = *buf;
> -      tmpds.msg_perm.mode *= 0x10000U;
> -      buf = &tmpds;
> +      msqid64_to_kmsqid64 (buf, &ksemid);
> +      arg = &ksemid;
>      }
> +# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> +  if (cmd == IPC_SET)
> +    arg->msg_perm.mode *= 0x10000U;
> +# endif
> +#else
> +  msgctl_arg_t *arg = buf;
>  #endif
>  
> -  int ret = msgctl_syscall (msqid, cmd, buf);
> +  int ret = msgctl_syscall (msqid, cmd, arg);
> +  if (ret < 0)
> +    return ret;
>  
> -  if (ret >= 0)
> +  switch (cmd)
>      {
> -      switch (cmd)
> -	{
> -	case IPC_STAT:
> -	case MSG_STAT:
> -	case MSG_STAT_ANY:
> +    case IPC_STAT:
> +    case MSG_STAT:
> +    case MSG_STAT_ANY:
>  #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -	  buf->msg_perm.mode >>= 16;
> +      arg->msg_perm.mode >>= 16;
>  #else
> -	  /* Old Linux kernel versions might not clear the mode padding.  */
> -	  if (sizeof ((struct msqid_ds){0}.msg_perm.mode)
> -	      != sizeof (__kernel_mode_t))
> -	    buf->msg_perm.mode &= 0xFFFF;
> +      /* Old Linux kernel versions might not clear the mode padding.  */
> +      if (sizeof ((struct msqid_ds){0}.msg_perm.mode)
> +          != sizeof (__kernel_mode_t))
> +	arg->msg_perm.mode &= 0xFFFF;
> +#endif
> +
> +#if __IPC_TIME64
> +      kmsqid64_to_msqid64 (arg, buf);
>  #endif
> -	}
>      }
>  
>    return ret;
>  }

OK.

> -versioned_symbol (libc, __new_msgctl, msgctl, DEFAULT_VERSION);
> +#if __TIMESIZE != 64
> +libc_hidden_def (__msgctl64)
> +
> +static void
> +msqid_to_msqid64 (struct __msqid64_ds *mq64, const struct msqid_ds *mq)
> +{
> +  mq64->msg_perm   = mq->msg_perm;
> +  mq64->msg_stime  = mq->msg_stime
> +		     | ((__time64_t) mq->__msg_stime_high << 32);
> +  mq64->msg_rtime  = mq->msg_rtime
> +		     | ((__time64_t) mq->__msg_rtime_high << 32);
> +  mq64->msg_ctime  = mq->msg_ctime
> +		     | ((__time64_t) mq->__msg_ctime_high << 32);
> +  mq64->msg_qnum   = mq->msg_qnum;
> +  mq64->msg_qbytes = mq->msg_qbytes;
> +  mq64->msg_lspid  = mq->msg_lspid;
> +  mq64->msg_lrpid  = mq->msg_lrpid;
> +}
> +
> +static void
> +msqid64_to_msqid (struct msqid_ds *mq, const struct __msqid64_ds *mq64)
> +{
> +  mq->msg_perm         = mq64->msg_perm;
> +  mq->msg_stime        = mq64->msg_stime;
> +  mq->__msg_stime_high = 0;
> +  mq->msg_rtime        = mq64->msg_rtime;
> +  mq->__msg_rtime_high = 0;
> +  mq->msg_ctime        = mq64->msg_ctime;
> +  mq->__msg_ctime_high = 0;

OK. No high values to transfer, but zero out the high values.

> +  mq->msg_qnum         = mq64->msg_qnum;
> +  mq->msg_qbytes       = mq64->msg_qbytes;
> +  mq->msg_lspid        = mq64->msg_lspid;
> +  mq->msg_lrpid        = mq64->msg_lrpid;
> +}
> +
> +int
> +__msgctl (int msqid, int cmd, struct msqid_ds *buf)
> +{
> +  struct __msqid64_ds msqid64, *buf64 = NULL;
> +  if (buf != NULL)
> +    {
> +      msqid_to_msqid64 (&msqid64, buf);
> +      buf64 = &msqid64;
> +    }
> +
> +  int ret = __msgctl64 (msqid, cmd, buf64);

OK.

> +  if (ret < 0)
> +    return ret;
> +
> +  switch (cmd)
> +    {
> +    case IPC_STAT:
> +    case MSG_STAT:
> +    case MSG_STAT_ANY:
> +      if (buf64 != NULL)
> +        msqid64_to_msqid (buf, buf64);
> +    }
> +
> +  return ret;
> +}
> +#endif
> +
> +#ifndef DEFAULT_VERSION
> +# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
> +#  define DEFAULT_VERSION GLIBC_2_2
> +# else
> +#  define DEFAULT_VERSION GLIBC_2_31
> +# endif
> +#endif
> +versioned_symbol (libc, __msgctl, msgctl, DEFAULT_VERSION);
>  
>  #if defined __ASSUME_SYSVIPC_BROKEN_MODE_T \
>      && SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_31)
> @@ -90,7 +201,7 @@ int
>  attribute_compat_text_section
>  __msgctl_mode16 (int msqid, int cmd, struct msqid_ds *buf)
>  {
> -  return msgctl_syscall (msqid, cmd, buf);
> +  return msgctl_syscall (msqid, cmd, (msgctl_arg_t *) buf);

OK.

>  }
>  compat_symbol (libc, __msgctl_mode16, msgctl, GLIBC_2_2);
>  #endif
> diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
> index 4ae2fbcbdc..35cc51f733 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
> @@ -26,11 +26,11 @@ struct msqid_ds
>  {
>    struct ipc_perm msg_perm;	/* structure describing operation permission */
>  #if __TIMESIZE == 32
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_stime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_rtime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>    __time_t msg_ctime;		/* time of last change */
>  #else
>    __time_t msg_stime;		/* time of last msgsnd command */

OK.

> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..69a63ee27a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long msg_stime_high;
> +  unsigned long msg_stime;
> +  unsigned long msg_rtime_high;
> +  unsigned long msg_rtime;
> +  unsigned long msg_ctime_high;
> +  unsigned long msg_ctime;

OK.

> +  unsigned long msg_cbytes;
> +  unsigned long msg_qnum;
> +  unsigned long msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c
> index 3a06270242..7467d2566e 100644
> --- a/sysdeps/unix/sysv/linux/semctl.c
> +++ b/sysdeps/unix/sysv/linux/semctl.c
> @@ -196,19 +196,11 @@ libc_hidden_def (__semctl64)
>  
>  /* The 64-bit time_t semid_ds version might have a different layout and
>     internal field alignment.  */
> -static void
> -semid64_ds_to_semid_ds (struct semid_ds *ds, const struct __semid64_ds *ds64)
> -{
> -  ds->sem_perm = ds64->sem_perm;
> -  ds->sem_otime = ds64->sem_otime;
> -  ds->sem_ctime = ds64->sem_ctime;
> -  ds->sem_nsems = ds64->sem_nsems;
> -}
>  
>  static void
> -semid_ds_to_semid64_ds (struct __semid64_ds *ds64, const struct semid_ds *ds)
> +semid_to_semid64 (struct __semid64_ds *ds64, const struct semid_ds *ds)
>  {
> -  ds64->sem_perm = ds->sem_perm;
> +  ds64->sem_perm  = ds->sem_perm;
>    ds64->sem_otime = ds->sem_otime
>  		    | ((__time64_t) ds->__sem_otime_high << 32);
>    ds64->sem_ctime = ds->sem_ctime
> @@ -216,6 +208,17 @@ semid_ds_to_semid64_ds (struct __semid64_ds *ds64, const struct semid_ds *ds)
>    ds64->sem_nsems = ds->sem_nsems;
>  }
>  
> +static void
> +semid64_to_semid (struct semid_ds *ds, const struct __semid64_ds *ds64)
> +{
> +  ds->sem_perm         = ds64->sem_perm;
> +  ds->sem_otime        = ds64->sem_otime;
> +  ds->__sem_otime_high = 0;
> +  ds->sem_ctime        = ds64->sem_ctime;
> +  ds->__sem_ctime_high = 0;
> +  ds->sem_nsems        = ds64->sem_nsems;
> +}

OK.

> +
>  static union semun64
>  semun_to_semun64 (int cmd, union semun semun, struct __semid64_ds *semid64)
>  {
> @@ -232,7 +235,7 @@ semun_to_semun64 (int cmd, union semun semun, struct __semid64_ds *semid64)
>      case IPC_STAT:
>      case IPC_SET:
>        r.buf = semid64;
> -      semid_ds_to_semid64_ds (r.buf, semun.buf);
> +      semid_to_semid64 (r.buf, semun.buf);
>  # ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
>        if (cmd == IPC_SET)
>  	r.buf->sem_perm.mode *= 0x10000U;
> @@ -282,7 +285,7 @@ __semctl (int semid, int semnum, int cmd, ...)
>      case IPC_STAT:
>      case SEM_STAT:
>      case SEM_STAT_ANY:
> -      semid64_ds_to_semid_ds (arg.buf, arg64.buf);
> +      semid64_to_semid (arg.buf, arg64.buf);
>      }
>  
>    return ret;
> diff --git a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
> index 71980839c7..502c23d91e 100644
> --- a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
> @@ -26,11 +26,11 @@ struct msqid_ds
>  {
>    struct ipc_perm msg_perm;	/* structure describing operation permission */
>  #if __TIMESIZE == 32
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_stime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_rtime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>    __time_t msg_ctime;		/* time of last change */
>  #else
>    __time_t msg_stime;		/* time of last msgsnd command */
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..69a63ee27a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long msg_stime_high;
> +  unsigned long msg_stime;
> +  unsigned long msg_rtime_high;
> +  unsigned long msg_rtime;
> +  unsigned long msg_ctime_high;
> +  unsigned long msg_ctime;
> +  unsigned long msg_cbytes;
> +  unsigned long msg_qnum;
> +  unsigned long msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..a676e34a5a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,19 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  It is only used
> +   for 32-bit architectures on 64-bit time_t msgctl64 implementation.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long int msg_stime;
> +  unsigned long int msg_stime_high;
> +  unsigned long int msg_rtime;
> +  unsigned long int msg_rtime_high;
> +  unsigned long int msg_ctime;
> +  unsigned long int msg_ctime_high;
> +  unsigned long int msg_cbytes;
> +  unsigned long int msg_qnum;
> +  unsigned long int  msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid; 
> +  unsigned long int __unused4;
> +  unsigned long int __unused5;
> +};
> 


-- 
Cheers,
Carlos.


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

* Re: [PATCH 5/7] sysvipc: Split out linux struct shmid_ds
  2020-06-30 19:24 ` [PATCH 5/7] sysvipc: Split out linux struct shmid_ds Adhemerval Zanella
  2020-07-02 21:40   ` Alistair Francis
@ 2020-07-07 19:52   ` Carlos O'Donell
  1 sibling, 0 replies; 41+ messages in thread
From: Carlos O'Donell @ 2020-07-07 19:52 UTC (permalink / raw)
  To: Adhemerval Zanella, libc-alpha; +Cc: stepan, Alistair Francis

On 6/30/20 3:24 PM, Adhemerval Zanella via Libc-alpha wrote:
> This will allow us to have architectures specify their own version.

OK for master.

No regressions on x86_64 and i686.

Tested-by: Carlos O'Donell <carlos@redhat.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> 
> Not semantic changes expected.  Checked with a build against the
> all affected ABIs.
> ---
>  sysdeps/unix/sysv/linux/Makefile              |  1 +
>  sysdeps/unix/sysv/linux/bits/shm.h            | 34 +----------
>  .../sysv/linux/bits/types/struct_shmid_ds.h   | 57 +++++++++++++++++++
>  3 files changed, 59 insertions(+), 33 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
> 
> diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
> index 505087e617..bdd187af73 100644
> --- a/sysdeps/unix/sysv/linux/Makefile
> +++ b/sysdeps/unix/sysv/linux/Makefile
> @@ -93,6 +93,7 @@ sysdep_headers += sys/mount.h sys/acct.h \
>  		  bits/termios-misc.h \
>  		  bits/types/struct_semid_ds.h \
>  		  bits/types/struct_msqid_ds.h \
> +		  bits/types/struct_shmid_ds.h \

OK.

>  		  bits/ipc-perm.h
>  
>  tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
> diff --git a/sysdeps/unix/sysv/linux/bits/shm.h b/sysdeps/unix/sysv/linux/bits/shm.h
> index 113c05ee89..9ef6aeaf92 100644
> --- a/sysdeps/unix/sysv/linux/bits/shm.h
> +++ b/sysdeps/unix/sysv/linux/bits/shm.h
> @@ -43,39 +43,7 @@ __BEGIN_DECLS
>  /* Type to count number of attaches.  */
>  typedef __syscall_ulong_t shmatt_t;
>  
> -#if __SHM_PAD_BEFORE_TIME
> -# define __SHM_PAD_TIME(NAME, RES)				\
> -  unsigned long int __glibc_reserved ## RES; __time_t NAME
> -#elif __SHM_PAD_AFTER_TIME
> -# define __SHM_PAD_TIME(NAME, RES)				\
> -  __time_t NAME; unsigned long int __glibc_reserved ## RES
> -#else
> -# define __SHM_PAD_TIME(NAME, RES)		\
> -  __time_t NAME
> -#endif
> -
> -/* Data structure describing a shared memory segment.  */
> -struct shmid_ds
> -  {
> -    struct ipc_perm shm_perm;		/* operation permission struct */
> -#if !__SHM_SEGSZ_AFTER_TIME
> -    size_t shm_segsz;			/* size of segment in bytes */
> -#endif
> -    __SHM_PAD_TIME (shm_atime, 1);	/* time of last shmat() */
> -    __SHM_PAD_TIME (shm_dtime, 2);	/* time of last shmdt() */
> -    __SHM_PAD_TIME (shm_ctime, 3);	/* time of last change by shmctl() */
> -#if __SHM_PAD_BETWEEN_TIME_AND_SEGSZ
> -    unsigned long int __glibc_reserved4;
> -#endif
> -#if __SHM_SEGSZ_AFTER_TIME
> -    size_t shm_segsz;			/* size of segment in bytes */
> -#endif
> -    __pid_t shm_cpid;			/* pid of creator */
> -    __pid_t shm_lpid;			/* pid of last shmop */
> -    shmatt_t shm_nattch;		/* number of current attaches */
> -    __syscall_ulong_t __glibc_reserved5;
> -    __syscall_ulong_t __glibc_reserved6;
> -  };
> +#include <bits/types/struct_shmid_ds.h>

OK.

>  
>  #ifdef __USE_MISC
>  
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
> new file mode 100644
> index 0000000000..938bbedfcd
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
> @@ -0,0 +1,57 @@
> +/* Generic implementation of the shared memory struct shmid_ds.

OK.

> +   Copyright (C) 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_SHM_H
> +# error "Never include <bits/types/struct_shmid_ds.h> directly; use <sys/shm.h> instead."
> +#endif
> +
> +#include <bits/shm-pad.h>
> +
> +#if __SHM_PAD_BEFORE_TIME
> +# define __SHM_PAD_TIME(NAME, RES)				\
> +  unsigned long int __glibc_reserved ## RES; __time_t NAME
> +#elif __SHM_PAD_AFTER_TIME
> +# define __SHM_PAD_TIME(NAME, RES)				\
> +  __time_t NAME; unsigned long int __glibc_reserved ## RES
> +#else
> +# define __SHM_PAD_TIME(NAME, RES)		\
> +  __time_t NAME
> +#endif
> +
> +/* Data structure describing a shared memory segment.  */
> +struct shmid_ds
> +  {
> +    struct ipc_perm shm_perm;		/* operation permission struct */
> +#if !__SHM_SEGSZ_AFTER_TIME
> +    size_t shm_segsz;			/* size of segment in bytes */
> +#endif
> +    __SHM_PAD_TIME (shm_atime, 1);	/* time of last shmat() */
> +    __SHM_PAD_TIME (shm_dtime, 2);	/* time of last shmdt() */
> +    __SHM_PAD_TIME (shm_ctime, 3);	/* time of last change by shmctl() */
> +#if __SHM_PAD_BETWEEN_TIME_AND_SEGSZ
> +    unsigned long int __glibc_reserved4;
> +#endif
> +#if __SHM_SEGSZ_AFTER_TIME
> +    size_t shm_segsz;			/* size of segment in bytes */
> +#endif
> +    __pid_t shm_cpid;			/* pid of creator */
> +    __pid_t shm_lpid;			/* pid of last shmop */
> +    shmatt_t shm_nattch;		/* number of current attaches */
> +    __syscall_ulong_t __glibc_reserved5;
> +    __syscall_ulong_t __glibc_reserved6;
> +  };
> 


-- 
Cheers,
Carlos.


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

* Re: [PATCH 6/7] sysvipc: Remove the linux shm-pad.h file
  2020-06-30 19:24 ` [PATCH 6/7] sysvipc: Remove the linux shm-pad.h file Adhemerval Zanella
@ 2020-07-07 19:57   ` Carlos O'Donell
  0 siblings, 0 replies; 41+ messages in thread
From: Carlos O'Donell @ 2020-07-07 19:57 UTC (permalink / raw)
  To: Adhemerval Zanella, libc-alpha; +Cc: stepan, Alistair Francis

On 6/30/20 3:24 PM, Adhemerval Zanella via Libc-alpha wrote:
> Each architecture overrides the struct msqid_ds which its required
> kernel ABI one.

OK for master.

No regressions on x86_64 and i686.

Tested-by: Carlos O'Donell <carlos@redhat.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
 
> Checked on x86_64-linux-gnu and some bases sysvipc tests on hppa,
> mips, mipsle, mips64, mips64le, sparc64, sparcv9, powerpc64le,
> powerpc64, and powerpc.
> ---
>  sysdeps/unix/sysv/linux/Makefile              |  2 +-
>  sysdeps/unix/sysv/linux/bits/shm-pad.h        | 37 --------------
>  sysdeps/unix/sysv/linux/bits/shm.h            |  1 -
>  .../sysv/linux/bits/types/struct_shmid_ds.h   | 34 +++++--------
>  sysdeps/unix/sysv/linux/hppa/bits/shm-pad.h   | 28 -----------
>  .../linux/hppa/bits/types/struct_shmid_ds.h   | 46 +++++++++++++++++
>  sysdeps/unix/sysv/linux/mips/bits/shm-pad.h   | 26 ----------
>  .../linux/mips/bits/types/struct_shmid_ds.h   | 49 +++++++++++++++++++
>  .../unix/sysv/linux/powerpc/bits/shm-pad.h    | 28 -----------
>  .../powerpc/bits/types/struct_shmid_ds.h      | 46 +++++++++++++++++
>  sysdeps/unix/sysv/linux/sparc/bits/shm-pad.h  | 28 -----------
>  .../linux/sparc/bits/types/struct_shmid_ds.h  | 45 +++++++++++++++++
>  12 files changed, 198 insertions(+), 172 deletions(-)
>  delete mode 100644 sysdeps/unix/sysv/linux/bits/shm-pad.h
>  delete mode 100644 sysdeps/unix/sysv/linux/hppa/bits/shm-pad.h
>  create mode 100644 sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
>  delete mode 100644 sysdeps/unix/sysv/linux/mips/bits/shm-pad.h
>  create mode 100644 sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
>  delete mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/shm-pad.h
>  create mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
>  delete mode 100644 sysdeps/unix/sysv/linux/sparc/bits/shm-pad.h
>  create mode 100644 sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h
> 
> diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
> index bdd187af73..fd0c313041 100644
> --- a/sysdeps/unix/sysv/linux/Makefile
> +++ b/sysdeps/unix/sysv/linux/Makefile
> @@ -85,7 +85,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/shmlba.h bits/shm-pad.h \
> +		  bits/shmlba.h \

OK. Remove 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/shm-pad.h b/sysdeps/unix/sysv/linux/bits/shm-pad.h
> deleted file mode 100644
> index 565e0e344b..0000000000
> --- a/sysdeps/unix/sysv/linux/bits/shm-pad.h
> +++ /dev/null
> @@ -1,37 +0,0 @@
> -/* Define where padding goes in struct shmid_ds.  Generic 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_SHM_H
> -# error "Never use <bits/shm-pad.h> directly; include <sys/shm.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.  Furthermore, some
> -   architectures place shm_segsz after the time fields rather than
> -   before them, with or without padding there.  This must match the
> -   layout used for struct shmid64_ds in <asm/shmbuf.h>, as glibc does
> -   not do layout conversions for this structure.  */
> -
> -#define __SHM_PAD_AFTER_TIME (__TIMESIZE == 32)
> -#define __SHM_PAD_BEFORE_TIME 0
> -#define __SHM_SEGSZ_AFTER_TIME 0
> -#define __SHM_PAD_BETWEEN_TIME_AND_SEGSZ 0

OK. Remove this padding, but now we'll have to define it explicilty for each arch
which in many ways is cleaner.

> diff --git a/sysdeps/unix/sysv/linux/bits/shm.h b/sysdeps/unix/sysv/linux/bits/shm.h
> index 9ef6aeaf92..f6aefa17f2 100644
> --- a/sysdeps/unix/sysv/linux/bits/shm.h
> +++ b/sysdeps/unix/sysv/linux/bits/shm.h
> @@ -22,7 +22,6 @@
>  #include <bits/types.h>
>  #include <bits/wordsize.h>
>  #include <bits/shmlba.h>
> -#include <bits/shm-pad.h>
>  
>  /* Permission flag for shmget.  */
>  #define SHM_R		0400		/* or S_IRUGO from <linux/stat.h> */
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
> index 938bbedfcd..61ed4a08c3 100644
> --- a/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
> @@ -20,34 +20,22 @@
>  # error "Never include <bits/types/struct_shmid_ds.h> directly; use <sys/shm.h> instead."
>  #endif
>  
> -#include <bits/shm-pad.h>
> -
> -#if __SHM_PAD_BEFORE_TIME
> -# define __SHM_PAD_TIME(NAME, RES)				\
> -  unsigned long int __glibc_reserved ## RES; __time_t NAME
> -#elif __SHM_PAD_AFTER_TIME
> -# define __SHM_PAD_TIME(NAME, RES)				\
> -  __time_t NAME; unsigned long int __glibc_reserved ## RES
> -#else
> -# define __SHM_PAD_TIME(NAME, RES)		\
> -  __time_t NAME
> -#endif
> -
>  /* Data structure describing a shared memory segment.  */
>  struct shmid_ds
>    {
>      struct ipc_perm shm_perm;		/* operation permission struct */
> -#if !__SHM_SEGSZ_AFTER_TIME
> -    size_t shm_segsz;			/* size of segment in bytes */
> -#endif
> -    __SHM_PAD_TIME (shm_atime, 1);	/* time of last shmat() */
> -    __SHM_PAD_TIME (shm_dtime, 2);	/* time of last shmdt() */
> -    __SHM_PAD_TIME (shm_ctime, 3);	/* time of last change by shmctl() */
> -#if __SHM_PAD_BETWEEN_TIME_AND_SEGSZ
> -    unsigned long int __glibc_reserved4;
> -#endif
> -#if __SHM_SEGSZ_AFTER_TIME
>      size_t shm_segsz;			/* size of segment in bytes */
> +#if __TIMESIZE == 32
> +    __time_t shm_atime;			/* time of last shmat() */
> +    unsigned long int __glibc_reserved1;
> +    __time_t shm_dtime;			/* time of last shmdt() */
> +    unsigned long int __glibc_reserved2;
> +    __time_t shm_ctime;			/* time of last change by shmctl() */
> +    unsigned long int __glibc_reserved3;
> +#else
> +    __time_t shm_atime;			/* time of last shmat() */
> +    __time_t shm_dtime;			/* time of last shmdt() */
> +    __time_t shm_ctime;			/* time of last change by shmctl() */

OK.

>  #endif
>      __pid_t shm_cpid;			/* pid of creator */
>      __pid_t shm_lpid;			/* pid of last shmop */
> diff --git a/sysdeps/unix/sysv/linux/hppa/bits/shm-pad.h b/sysdeps/unix/sysv/linux/hppa/bits/shm-pad.h
> deleted file mode 100644
> index d0811fe543..0000000000
> --- a/sysdeps/unix/sysv/linux/hppa/bits/shm-pad.h
> +++ /dev/null
> @@ -1,28 +0,0 @@
> -/* Define where padding goes in struct shmid_ds.  HPPA 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_SHM_H
> -# error "Never use <bits/shm-pad.h> directly; include <sys/shm.h> instead."
> -#endif
> -
> -#include <bits/timesize.h>
> -
> -#define __SHM_PAD_AFTER_TIME 0
> -#define __SHM_PAD_BEFORE_TIME (__TIMESIZE == 32)
> -#define __SHM_SEGSZ_AFTER_TIME 1
> -#define __SHM_PAD_BETWEEN_TIME_AND_SEGSZ (__TIMESIZE == 32)

OK.

> diff --git a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
> new file mode 100644
> index 0000000000..1ebf222eac
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
> @@ -0,0 +1,46 @@
> +/* Linux/HPPA implementation of the shared memory struct shmid_ds.
> +   Copyright (C) 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_SHM_H
> +# error "Never include <bits/types/struct_shmid_ds.h> directly; use <sys/shm.h> instead."
> +#endif
> +
> +/* Data structure describing a shared memory segment.  */
> +struct shmid_ds
> +  {
> +    struct ipc_perm shm_perm;		/* operation permission struct */
> +#if __TIMESIZE == 32
> +    unsigned long int __glibc_reserved1;
> +    __time_t shm_atime;			/* time of last shmat() */
> +    unsigned long int __glibc_reserved2;
> +    __time_t shm_dtime;			/* time of last shmdt() */
> +    unsigned long int __glibc_reserved3;
> +    __time_t shm_ctime;			/* time of last change by shmctl() */
> +    unsigned long int __glibc_reserved4;

OK.

> +#else
> +    __time_t shm_atime;			/* time of last shmat() */
> +    __time_t shm_dtime;			/* time of last shmdt() */
> +    __time_t shm_ctime;			/* time of last change by shmctl() */
> +#endif
> +    size_t shm_segsz;			/* size of segment in bytes */
> +    __pid_t shm_cpid;			/* pid of creator */
> +    __pid_t shm_lpid;			/* pid of last shmop */
> +    shmatt_t shm_nattch;		/* number of current attaches */
> +    __syscall_ulong_t __glibc_reserved5;
> +    __syscall_ulong_t __glibc_reserved6;
> +  };
> diff --git a/sysdeps/unix/sysv/linux/mips/bits/shm-pad.h b/sysdeps/unix/sysv/linux/mips/bits/shm-pad.h
> deleted file mode 100644
> index 5a475a64f9..0000000000
> --- a/sysdeps/unix/sysv/linux/mips/bits/shm-pad.h
> +++ /dev/null
> @@ -1,26 +0,0 @@
> -/* Define where padding goes in struct shmid_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_SHM_H
> -# error "Never use <bits/shm-pad.h> directly; include <sys/shm.h> instead."
> -#endif
> -
> -#define __SHM_PAD_AFTER_TIME 0
> -#define __SHM_PAD_BEFORE_TIME 0
> -#define __SHM_SEGSZ_AFTER_TIME 0
> -#define __SHM_PAD_BETWEEN_TIME_AND_SEGSZ 0

OK.

> diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
> new file mode 100644
> index 0000000000..8e13928980
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
> @@ -0,0 +1,49 @@
> +/* Linux/MIPS implementation of the shared memory struct shmid_ds.
> +   Copyright (C) 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_SHM_H
> +# error "Never include <bits/types/struct_shmid_ds.h> directly; use <sys/shm.h> instead."
> +#endif
> +
> +/* Data structure describing a shared memory segment.  */
> +struct shmid_ds
> +  {
> +    struct ipc_perm shm_perm;		/* operation permission struct */
> +    size_t shm_segsz;			/* size of segment in bytes */
> +#if __TIMESIZE == 32
> +    __time_t shm_atime;			/* time of last shmat() */
> +    __time_t shm_dtime;			/* time of last shmdt() */
> +    __time_t shm_ctime;			/* time of last change by shmctl() */
> +#else
> +    __time_t shm_atime;			/* time of last shmat() */
> +    __time_t shm_dtime;			/* time of last shmdt() */
> +    __time_t shm_ctime;			/* time of last change by shmctl() */
> +#endif
> +    __pid_t shm_cpid;			/* pid of creator */
> +    __pid_t shm_lpid;			/* pid of last shmop */
> +    shmatt_t shm_nattch;		/* number of current attaches */
> +#if __TIMESIZE == 32
> +    unsigned short int __glibc_reserved1;
> +    unsigned short int __glibc_reserved2;
> +    unsigned short int __glibc_reserved3;
> +    unsigned short int __glibc_reserved4;
> +#else
> +    __syscall_ulong_t __glibc_reserved5;
> +    __syscall_ulong_t __glibc_reserved6;

OK.

> +#endif
> +  };
> diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/shm-pad.h b/sysdeps/unix/sysv/linux/powerpc/bits/shm-pad.h
> deleted file mode 100644
> index 34cbdb2a0d..0000000000
> --- a/sysdeps/unix/sysv/linux/powerpc/bits/shm-pad.h
> +++ /dev/null
> @@ -1,28 +0,0 @@
> -/* Define where padding goes in struct shmid_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_SHM_H
> -# error "Never use <bits/shm-pad.h> directly; include <sys/shm.h> instead."
> -#endif
> -
> -#include <bits/timesize.h>
> -
> -#define __SHM_PAD_AFTER_TIME 0
> -#define __SHM_PAD_BEFORE_TIME (__TIMESIZE == 32)
> -#define __SHM_SEGSZ_AFTER_TIME 1
> -#define __SHM_PAD_BETWEEN_TIME_AND_SEGSZ (__TIMESIZE == 32)

OK.

> diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
> new file mode 100644
> index 0000000000..b0816fb16a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
> @@ -0,0 +1,46 @@
> +/* Linux/PowerPC implementation of the shared memory struct shmid_ds.
> +   Copyright (C) 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_SHM_H
> +# error "Never include <bits/types/struct_shmid_ds.h> directly; use <sys/shm.h> instead."
> +#endif
> +
> +/* Data structure describing a shared memory segment.  */
> +struct shmid_ds
> +  {
> +    struct ipc_perm shm_perm;		/* operation permission struct */
> +#if __TIMESIZE == 32
> +    unsigned long int __glibc_reserved1;
> +    __time_t shm_atime;			/* time of last shmat() */
> +    unsigned long int __glibc_reserved2;
> +    __time_t shm_dtime;			/* time of last shmdt() */
> +    unsigned long int __glibc_reserved3;
> +    __time_t shm_ctime;			/* time of last change by shmctl() */
> +    unsigned long int __glibc_reserved4;
> +#else
> +    __time_t shm_atime;			/* time of last shmat() */
> +    __time_t shm_dtime;			/* time of last shmdt() */
> +    __time_t shm_ctime;			/* time of last change by shmctl() */
> +#endif

OK.

> +    size_t shm_segsz;			/* size of segment in bytes */
> +    __pid_t shm_cpid;			/* pid of creator */
> +    __pid_t shm_lpid;			/* pid of last shmop */
> +    shmatt_t shm_nattch;		/* number of current attaches */
> +    __syscall_ulong_t __glibc_reserved5;
> +    __syscall_ulong_t __glibc_reserved6;
> +  };
> diff --git a/sysdeps/unix/sysv/linux/sparc/bits/shm-pad.h b/sysdeps/unix/sysv/linux/sparc/bits/shm-pad.h
> deleted file mode 100644
> index cd0b1fe543..0000000000
> --- a/sysdeps/unix/sysv/linux/sparc/bits/shm-pad.h
> +++ /dev/null
> @@ -1,28 +0,0 @@
> -/* Define where padding goes in struct shmid_ds.  SPARC 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_SHM_H
> -# error "Never use <bits/shm-pad.h> directly; include <sys/shm.h> instead."
> -#endif
> -
> -#include <bits/timesize.h>
> -
> -#define __SHM_PAD_AFTER_TIME 0
> -#define __SHM_PAD_BEFORE_TIME (__TIMESIZE == 32)
> -#define __SHM_SEGSZ_AFTER_TIME 1
> -#define __SHM_PAD_BETWEEN_TIME_AND_SEGSZ 0
> diff --git a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h
> new file mode 100644
> index 0000000000..d5fb61d374
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h
> @@ -0,0 +1,45 @@
> +/* Linux/SPARC implementation of the shared memory struct shmid_ds.
> +   Copyright (C) 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_SHM_H
> +# error "Never include <bits/types/struct_shmid_ds.h> directly; use <sys/shm.h> instead."
> +#endif
> +
> +/* Data structure describing a shared memory segment.  */
> +struct shmid_ds
> +  {
> +    struct ipc_perm shm_perm;		/* operation permission struct */
> +#if __TIMESIZE == 32
> +    unsigned long int __glibc_reserved1;
> +    __time_t shm_atime;			/* time of last shmat() */
> +    unsigned long int __glibc_reserved2;
> +    __time_t shm_dtime;			/* time of last shmdt() */
> +    unsigned long int __glibc_reserved3;
> +    __time_t shm_ctime;			/* time of last change by shmctl() */
> +#else
> +    __time_t shm_atime;			/* time of last shmat() */
> +    __time_t shm_dtime;			/* time of last shmdt() */
> +    __time_t shm_ctime;			/* time of last change by shmctl() */

OK.

> +#endif
> +    size_t shm_segsz;			/* size of segment in bytes */
> +    __pid_t shm_cpid;			/* pid of creator */
> +    __pid_t shm_lpid;			/* pid of last shmop */
> +    shmatt_t shm_nattch;		/* number of current attaches */
> +    __syscall_ulong_t __glibc_reserved5;
> +    __syscall_ulong_t __glibc_reserved6;
> +  };
> 


-- 
Cheers,
Carlos.


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

* Re: [PATCH 7/7] sysv: linux: Add 64-bit time_t variant for shmctl
  2020-06-30 19:24 ` [PATCH 7/7] sysv: linux: Add 64-bit time_t variant for shmctl Adhemerval Zanella
  2020-07-01  2:28   ` Alistair Francis
@ 2020-07-07 21:33   ` Carlos O'Donell
  2020-07-08 15:32     ` [PATCH v2] " Adhemerval Zanella
  1 sibling, 1 reply; 41+ messages in thread
From: Carlos O'Donell @ 2020-07-07 21:33 UTC (permalink / raw)
  To: Adhemerval Zanella, libc-alpha; +Cc: stepan, Alistair Francis

On 6/30/20 3:24 PM, Adhemerval Zanella via Libc-alpha wrote:

OK for master with textual changes.

No regressions for x86_64 and i686.

Tested-by: Carlos O'Donell <carlos@redhat.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> To provide a y2038 safe interface a new symbol __shmctl64 is added
> and __shmctl is change to call it instead (it adds some extra buffer
> copy for the 32 bit time_t implementation).

s/copy/copying/g

> Two two new structures are added:

s/Two two/Two/g

> 
>   1. kernel_shmid64_ds: used internally only on 32-bit architectures
>      to issue the syscall.  A handful architectures (hppa, i386, mips,

s/handful/handful of/g


>      powerpc32, and sparc32) requires specific implementation due its
>      specific kernel ABI.

Suggest:

require specific implementations due to their kernel ABI.

>   2. shmid_ds64: this is only for __TIMESIZE != 64 to use along with
>      the 64-bit semctl.  It is different than the kernel one because

s/one/struct/g

>      the exported 64-bit time_t might require different alignment
>      depending of the architecture ABI.

s/of/on/g

> 
> So the resulting implementation does:
> 
>   1. For 64-bit architectures it assumes shmid_ds already contains
>      64-bit time_t fields it will result in just the __shmctl symbol

s/it/and/g

>      using the __shmctl64 code.  The shmid_ds argument is passed as-is
>      to the syscall.
> 
>   2. For 32-bit architectures with default 64-bit time_t (newer ABIs
>      such riscv32 or arc), it will also result in only one exported
>      symbol but with the required high/low time handling.
> 
>   3. Finally for 32-bit architecture with both 32-bit and 64-bit time_t
>      support we follow the already set way to provide one symbol with
>      64-bit time_t support and implement the 32-bit time_t support on
>      basis of the 64-bit one.

s/on basis of/using/g
s/one/time_t/g

>      The default 32-bit symbol will allocate and copy the shmid_ds
>      over multiple buffers, but this should be deprecated in favor
>      of the __shmctl64 anyway.
> 
> Checked on i686-linux-gnu and x86_64-linux-gnu.  I also did some sniff
> tests on powerpc, powerpc64, mips, mips64, armhf, sparcv9, and
> sparc64.
> ---
>  include/sys/shm.h                             |  16 ++
>  .../sysv/linux/bits/types/struct_shmid64_ds.h |  37 ++++
>  .../sysv/linux/bits/types/struct_shmid_ds.h   |   6 +-
>  .../linux/hppa/bits/types/struct_shmid_ds.h   |   6 +-
>  .../linux/hppa/struct_kernel_shmid64_ds.h     |  18 ++
>  .../linux/i386/struct_kernel_shmid64_ds.h     |  17 ++
>  .../linux/mips/bits/types/struct_shmid_ds.h   |   6 +-
>  .../linux/mips/struct_kernel_shmid64_ds.h     |  27 +++
>  .../powerpc/bits/types/struct_shmid_ds.h      |   6 +-
>  .../linux/powerpc/struct_kernel_shmid64_ds.h  |  24 +++
>  sysdeps/unix/sysv/linux/shmctl.c              | 180 ++++++++++++++----
>  .../linux/sparc/bits/types/struct_shmid_ds.h  |   6 +-
>  .../linux/sparc/struct_kernel_shmid64_ds.h    |  23 +++
>  .../sysv/linux/struct_kernel_shmid64_ds.h     |  23 +++
>  14 files changed, 346 insertions(+), 49 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h
> 
> diff --git a/include/sys/shm.h b/include/sys/shm.h
> index 1878fcc5be..530a1cdfc9 100644
> --- a/include/sys/shm.h
> +++ b/include/sys/shm.h
> @@ -1 +1,17 @@
> +#ifndef _SYS_SHM_H
>  #include <sysvipc/sys/shm.h>
> +
> +#ifndef _ISOMAC
> +
> +# include <bits/types/struct_shmid64_ds.h>
> +
> +# if __TIMESIZE == 64
> +#  define __shmctl64 __shmctl
> +# else
> +extern int __shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf);
> +libc_hidden_proto (__shmctl64);
> +# endif
> +
> +#endif /* _ISOMAC  */

OK.

> +
> +#endif /* _SYS_SHM_H  */
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h
> new file mode 100644
> index 0000000000..f71e0d28ff
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h
> @@ -0,0 +1,37 @@
> +/* Generic implementation of the shared memory struct shmid_ds.
> +   Copyright (C) 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_SHM_H
> +# error "Never include <bits/types/struct_shmid_ds.h> directly; use <sys/shm.h> instead."
> +#endif
> +
> +#if __TIMESIZE == 64
> +# define __shmid64_ds shmid_ds
> +#else
> +struct __shmid64_ds
> +{
> +  struct ipc_perm shm_perm;	/* operation permission struct */
> +  size_t shm_segsz;		/* size of segment in bytes */
> +  __time64_t shm_atime;		/* time of last shmat() */
> +  __time64_t shm_dtime;		/* time of last shmdt() */
> +  __time64_t shm_ctime;		/* time of last change by shmctl() */

OK.

> +  __pid_t shm_cpid;		/* pid of creator */
> +  __pid_t shm_lpid;		/* pid of last shmop */
> +  shmatt_t shm_nattch;		/* number of current attaches */
> +};
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
> index 61ed4a08c3..836a7d50e9 100644
> --- a/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
> @@ -27,11 +27,11 @@ struct shmid_ds
>      size_t shm_segsz;			/* size of segment in bytes */
>  #if __TIMESIZE == 32
>      __time_t shm_atime;			/* time of last shmat() */
> -    unsigned long int __glibc_reserved1;
> +    unsigned long int __shm_atime_high;
>      __time_t shm_dtime;			/* time of last shmdt() */
> -    unsigned long int __glibc_reserved2;
> +    unsigned long int __shm_dtime_high;
>      __time_t shm_ctime;			/* time of last change by shmctl() */
> -    unsigned long int __glibc_reserved3;
> +    unsigned long int __shm_ctime_high;

OK.

>  #else
>      __time_t shm_atime;			/* time of last shmat() */
>      __time_t shm_dtime;			/* time of last shmdt() */
> diff --git a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
> index 1ebf222eac..1abed1e149 100644
> --- a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
> +++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
> @@ -25,11 +25,11 @@ struct shmid_ds
>    {
>      struct ipc_perm shm_perm;		/* operation permission struct */
>  #if __TIMESIZE == 32
> -    unsigned long int __glibc_reserved1;
> +    unsigned long int __shm_atime_high;
>      __time_t shm_atime;			/* time of last shmat() */
> -    unsigned long int __glibc_reserved2;
> +    unsigned long int __shm_dtime_high;
>      __time_t shm_dtime;			/* time of last shmdt() */
> -    unsigned long int __glibc_reserved3;
> +    unsigned long int __shm_ctime_high;

OK.

>      __time_t shm_ctime;			/* time of last change by shmctl() */
>      unsigned long int __glibc_reserved4;
>  #else
> diff --git a/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h
> new file mode 100644
> index 0000000000..4d09fc7f62
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
> +struct kernel_shmid64_ds
> +{
> +  struct ipc_perm shm_perm;		/* operation permission struct */
> +  unsigned long int shm_atime_high;
> +  unsigned long int shm_atime;		/* time of last shmat() */
> +  unsigned long int shm_dtime_high;
> +  unsigned long int shm_dtime;		/* time of last shmdt() */
> +  unsigned long int shm_ctime_high;
> +  unsigned long int shm_ctime;		/* time of last change by shmctl() */

OK.

> +  unsigned long int __pad;
> +  size_t shm_segsz;			/* size of segment in bytes */
> +  __pid_t shm_cpid;			/* pid of creator */
> +  __pid_t shm_lpid;			/* pid of last shmop */
> +  shmatt_t shm_nattch;		/* number of current attaches */
> +  unsigned long int __unused1;
> +  unsigned long int __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h
> new file mode 100644
> index 0000000000..6a0a0d9c71
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h
> @@ -0,0 +1,17 @@
> +/* Analogous to kernel struct compat_shmid64_ds used on shmctl.  */
> +struct kernel_shmid64_ds
> +{
> +  struct ipc_perm shm_perm;
> +  size_t shm_segsz;
> +  unsigned long int shm_atime;
> +  unsigned long int shm_atime_high;
> +  unsigned long int shm_dtime;
> +  unsigned long int shm_dtime_high;
> +  unsigned long int shm_ctime;
> +  unsigned long int shm_ctime_high;

OK.

> +  __pid_t shm_cpid;
> +  __pid_t shm_lpid;
> +  unsigned long int shm_nattch;
> +  unsigned long int __unused4;
> +  unsigned long int __unused5;
> +};
> diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
> index 8e13928980..58090e2fcb 100644
> --- a/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
> +++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
> @@ -38,9 +38,9 @@ struct shmid_ds
>      __pid_t shm_lpid;			/* pid of last shmop */
>      shmatt_t shm_nattch;		/* number of current attaches */
>  #if __TIMESIZE == 32
> -    unsigned short int __glibc_reserved1;
> -    unsigned short int __glibc_reserved2;
> -    unsigned short int __glibc_reserved3;
> +    unsigned short int __shm_atime_high;
> +    unsigned short int __shm_dtime_high;
> +    unsigned short int __shm_ctime_high;

OK.

>      unsigned short int __glibc_reserved4;
>  #else
>      __syscall_ulong_t __glibc_reserved5;
> diff --git a/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h
> new file mode 100644
> index 0000000000..a4baa5614f
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h
> @@ -0,0 +1,27 @@
> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
> +struct kernel_shmid64_ds
> +{
> +  struct ipc_perm shm_perm;
> +  size_t shm_segsz;
> +#if __TIMESIZE == 64
> +  long int shm_atime;
> +  long int shm_dtime;
> +  long int shm_ctime;
> +#else
> +  unsigned long int shm_atime;
> +  unsigned long int shm_dtime;
> +  unsigned long int shm_ctime;
> +#endif
> +  __pid_t shm_cpid;
> +  __pid_t shm_lpid;
> +  unsigned long int shm_nattch;
> +#if __TIMESIZE == 64
> +  unsigned long int __unused1;
> +  unsigned long int __unused2;
> +#else
> +  unsigned short int shm_atime_high;
> +  unsigned short int shm_dtime_high;
> +  unsigned short int shm_ctime_high;

OK.

> +  unsigned short int __ununsed1;
> +#endif
> +};
> diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
> index b0816fb16a..39b3e5fd3e 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
> +++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
> @@ -25,11 +25,11 @@ struct shmid_ds
>    {
>      struct ipc_perm shm_perm;		/* operation permission struct */
>  #if __TIMESIZE == 32
> -    unsigned long int __glibc_reserved1;
> +    unsigned long int __shm_atime_high;
>      __time_t shm_atime;			/* time of last shmat() */
> -    unsigned long int __glibc_reserved2;
> +    unsigned long int __shm_dtime_high;
>      __time_t shm_dtime;			/* time of last shmdt() */
> -    unsigned long int __glibc_reserved3;
> +    unsigned long int __shm_ctime_high;

OK.

>      __time_t shm_ctime;			/* time of last change by shmctl() */
>      unsigned long int __glibc_reserved4;
>  #else
> diff --git a/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
> new file mode 100644
> index 0000000000..5533d44dee
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
> @@ -0,0 +1,24 @@
> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
> +struct kernel_shmid64_ds
> +{
> +  struct ipc_perm shm_perm;
> +#if __TIMESIZE == 64
> +  long int shm_atime;
> +  long int shm_atime;
> +  long int shm_atime;
> +#else
> +  unsigned long int shm_atime_high;
> +  unsigned long int shm_atime;
> +  unsigned long int shm_dtime_high;
> +  unsigned long int shm_dtime;
> +  unsigned long int shm_ctime_high;

OK.

> +  unsigned long int shm_ctime;
> +  unsigned long int __ununsed1;
> +#endif
> +  size_t shm_segsz;
> +  __pid_t shm_cpid;
> +  __pid_t shm_lpid;
> +  unsigned long int shm_nattch;
> +  unsigned long int __unused2;
> +  unsigned long int __unused3;
> +};
> diff --git a/sysdeps/unix/sysv/linux/shmctl.c b/sysdeps/unix/sysv/linux/shmctl.c
> index f41b359b8b..aaf3946054 100644
> --- a/sysdeps/unix/sysv/linux/shmctl.c
> +++ b/sysdeps/unix/sysv/linux/shmctl.c
> @@ -24,16 +24,55 @@
>  #include <errno.h>
>  #include <linux/posix_types.h>  /* For __kernel_mode_t.  */
>  
> -#ifndef DEFAULT_VERSION
> -# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -#  define DEFAULT_VERSION GLIBC_2_2
> -# else
> -#  define DEFAULT_VERSION GLIBC_2_31
> -# endif
> +/* POSIX states ipc_perm mode should have type of mode_t.  */
> +_Static_assert (sizeof ((struct shmid_ds){0}.shm_perm.mode)
> +		== sizeof (mode_t),
> +		"sizeof (shmid_ds.shm_perm.mode) != sizeof (mode_t)");
> +
> +#if __IPC_TIME64 == 0
> +typedef struct shmid_ds shmctl_arg_t;
> +#else
> +# include <struct_kernel_shmid64_ds.h>
> +
> +static void
> +shmid64_to_kshmid64 (const struct __shmid64_ds *shmid64,
> +		     struct kernel_shmid64_ds *kshmid)
> +{
> +  kshmid->shm_perm       = shmid64->shm_perm;
> +  kshmid->shm_segsz      = shmid64->shm_segsz;
> +  kshmid->shm_atime      = shmid64->shm_atime;
> +  kshmid->shm_atime_high = shmid64->shm_atime >> 32;
> +  kshmid->shm_dtime      = shmid64->shm_dtime;
> +  kshmid->shm_dtime_high = shmid64->shm_dtime >> 32;
> +  kshmid->shm_ctime      = shmid64->shm_ctime;
> +  kshmid->shm_ctime_high = shmid64->shm_ctime >> 32;
> +  kshmid->shm_cpid       = shmid64->shm_cpid;
> +  kshmid->shm_lpid       = shmid64->shm_lpid;
> +  kshmid->shm_nattch     = shmid64->shm_nattch;

OK.

> +}
> +
> +static void
> +kshmid64_to_shmid64 (const struct kernel_shmid64_ds *kshmid,
> +		     struct __shmid64_ds *shmid64)
> +{
> +  shmid64->shm_perm   = kshmid->shm_perm;
> +  shmid64->shm_segsz  = kshmid->shm_segsz;
> +  shmid64->shm_atime  = kshmid->shm_atime
> +		        | ((__time64_t) kshmid->shm_atime_high << 32);
> +  shmid64->shm_dtime  = kshmid->shm_dtime
> +		        | ((__time64_t) kshmid->shm_dtime_high << 32);
> +  shmid64->shm_ctime     = kshmid->shm_ctime
> +		        | ((__time64_t) kshmid->shm_ctime_high << 32);
> +  shmid64->shm_cpid   = kshmid->shm_cpid;
> +  shmid64->shm_lpid   = kshmid->shm_lpid;
> +  shmid64->shm_nattch = kshmid->shm_nattch;

OK.

> +}
> +
> +typedef struct kernel_shmid64_ds shmctl_arg_t;
>  #endif
>  
>  static int
> -shmctl_syscall (int shmid, int cmd, struct shmid_ds *buf)
> +shmctl_syscall (int shmid, int cmd, shmctl_arg_t *buf)
>  {
>  #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
>    return INLINE_SYSCALL_CALL (shmctl, shmid, cmd | __IPC_64, buf);
> @@ -45,46 +84,119 @@ shmctl_syscall (int shmid, int cmd, struct shmid_ds *buf)
>  
>  /* Provide operations to control over shared memory segments.  */
>  int
> -__new_shmctl (int shmid, int cmd, struct shmid_ds *buf)
> +__shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf)
>  {
> -  /* POSIX states ipc_perm mode should have type of mode_t.  */
> -  _Static_assert (sizeof ((struct shmid_ds){0}.shm_perm.mode)
> -		  == sizeof (mode_t),
> -		  "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");
> -
> -#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -  struct shmid_ds tmpds;
> -  if (cmd == IPC_SET)
> +#if __IPC_TIME64
> +  struct kernel_shmid64_ds kshmid, *arg = NULL;
> +  if (buf != NULL)
>      {
> -      tmpds = *buf;
> -      tmpds.shm_perm.mode *= 0x10000U;
> -      buf = &tmpds;
> +      shmid64_to_kshmid64 (buf, &kshmid);
> +      arg = &kshmid;
>      }
> +# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> +  if (cmd == IPC_SET)
> +      arg->shm_perm.mode *= 0x10000U;
> +# endif
> +#else
> +  shmctl_arg_t *arg = buf;
>  #endif
>  
> -  int ret = shmctl_syscall (shmid, cmd, buf);
> +  int ret = shmctl_syscall (shmid, cmd, arg);

OK.

> +  if (ret < 0)
> +    return ret;
>  
> -  if (ret >= 0)
> +  switch (cmd)
>      {
> -      switch (cmd)
> -	{
> -        case IPC_STAT:
> -        case SHM_STAT:
> -        case SHM_STAT_ANY:
> +      case IPC_STAT:
> +      case SHM_STAT:
> +      case SHM_STAT_ANY:
>  #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -          buf->shm_perm.mode >>= 16;
> +        arg->shm_perm.mode >>= 16;
>  #else
> -	  /* Old Linux kernel versions might not clear the mode padding.  */
> -	  if (sizeof ((struct shmid_ds){0}.shm_perm.mode)
> -	      != sizeof (__kernel_mode_t))
> -	    buf->shm_perm.mode &= 0xFFFF;
> +      /* Old Linux kernel versions might not clear the mode padding.  */
> +      if (sizeof ((struct shmid_ds){0}.shm_perm.mode)
> +	  != sizeof (__kernel_mode_t))
> +	arg->shm_perm.mode &= 0xFFFF;
> +#endif
> +
> +#if __IPC_TIME64
> +      kshmid64_to_shmid64 (arg, buf);
>  #endif
> -	}
>      }
>  
>    return ret;
>  }
> -versioned_symbol (libc, __new_shmctl, shmctl, DEFAULT_VERSION);
> +#if __TIMESIZE != 64
> +libc_hidden_def (__shmctl64)
> +
> +static void
> +shmid_to_shmid64 (struct __shmid64_ds *shm64, const struct shmid_ds *shm)
> +{
> +  shm64->shm_perm   = shm->shm_perm;
> +  shm64->shm_segsz  = shm->shm_segsz;
> +  shm64->shm_atime  = shm->shm_atime
> +		        | ((__time64_t) shm->__shm_atime_high << 32);
> +  shm64->shm_dtime  = shm->shm_dtime
> +		        | ((__time64_t) shm->__shm_dtime_high << 32);
> +  shm64->shm_ctime     = shm->shm_ctime
> +		        | ((__time64_t) shm->__shm_ctime_high << 32);
> +  shm64->shm_cpid   = shm->shm_cpid;
> +  shm64->shm_lpid   = shm->shm_lpid;
> +  shm64->shm_nattch = shm->shm_nattch;
> +}
> +
> +static void
> +shmid64_to_shmid (struct shmid_ds *shm, const struct __shmid64_ds *shm64)
> +{
> +  shm->shm_perm         = shm64->shm_perm;
> +  shm->shm_segsz        = shm64->shm_segsz;
> +  shm->shm_atime        = shm64->shm_atime;
> +  shm->__shm_atime_high = 0;
> +  shm->shm_dtime        = shm64->shm_dtime;
> +  shm->__shm_dtime_high = 0;
> +  shm->shm_ctime        = shm64->shm_ctime;
> +  shm->__shm_ctime_high = 0;
> +  shm->shm_cpid         = shm64->shm_cpid;
> +  shm->shm_lpid         = shm64->shm_lpid;
> +  shm->shm_nattch       = shm64->shm_nattch;
> +}

OK.

> +
> +int
> +__shmctl (int shmid, int cmd, struct shmid_ds *buf)
> +{
> +  struct __shmid64_ds shmid64, *buf64 = NULL;
> +  if (buf != NULL)
> +    {
> +      shmid_to_shmid64 (&shmid64, buf);
> +      buf64 = &shmid64;
> +    }
> +
> +  int ret = __shmctl64 (shmid, cmd, buf64);

OK.

> +  if (ret < 0)
> +    return ret;
> +
> +  switch (cmd)
> +    {
> +      case IPC_STAT:
> +      case SHM_STAT:
> +      case SHM_STAT_ANY:
> +	if (buf64 != NULL)
> +	  shmid64_to_shmid (buf, buf64);
> +    }
> +
> +  return ret;
> +}
> +#endif
> +
> +#ifndef DEFAULT_VERSION
> +# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
> +#  define DEFAULT_VERSION GLIBC_2_2
> +# else
> +#  define DEFAULT_VERSION GLIBC_2_31
> +# endif
> +#endif
> +
> +versioned_symbol (libc, __shmctl, shmctl, DEFAULT_VERSION);

OK.

>  
>  #if defined __ASSUME_SYSVIPC_BROKEN_MODE_T \
>      && SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_31)
> @@ -92,7 +204,7 @@ int
>  attribute_compat_text_section
>  __shmctl_mode16 (int shmid, int cmd, struct shmid_ds *buf)
>  {
> -  return shmctl_syscall (shmid, cmd, buf);
> +  return shmctl_syscall (shmid, cmd, (shmctl_arg_t *) buf);
>  }
>  compat_symbol (libc, __shmctl_mode16, shmctl, GLIBC_2_2);
>  #endif
> diff --git a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h
> index d5fb61d374..cab3a2686f 100644
> --- a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h
> +++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h
> @@ -25,11 +25,11 @@ struct shmid_ds
>    {
>      struct ipc_perm shm_perm;		/* operation permission struct */
>  #if __TIMESIZE == 32
> -    unsigned long int __glibc_reserved1;
> +    unsigned long int __shm_atime_high;
>      __time_t shm_atime;			/* time of last shmat() */
> -    unsigned long int __glibc_reserved2;
> +    unsigned long int __shm_dtime_high;
>      __time_t shm_dtime;			/* time of last shmdt() */
> -    unsigned long int __glibc_reserved3;
> +    unsigned long int __shm_ctime_high;
>      __time_t shm_ctime;			/* time of last change by shmctl() */
>  #else
>      __time_t shm_atime;			/* time of last shmat() */
> diff --git a/sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h
> new file mode 100644
> index 0000000000..c9ecd7b1e9
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h
> @@ -0,0 +1,23 @@
> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
> +struct kernel_shmid64_ds
> +{
> +  struct ipc_perm shm_perm;
> +#if __TIMESIZE == 64
> +  long int shm_atime;
> +  long int shm_atime;
> +  long int shm_atime;
> +#else
> +  unsigned long int shm_atime_high;
> +  unsigned long int shm_atime;
> +  unsigned long int shm_dtime_high;
> +  unsigned long int shm_dtime;
> +  unsigned long int shm_ctime_high;
> +  unsigned long int shm_ctime;

OK.

> +#endif
> +  size_t shm_segsz;
> +  __pid_t shm_cpid;
> +  __pid_t shm_lpid;
> +  unsigned long int shm_nattch;
> +  unsigned long int __unused1;
> +  unsigned long int __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h
> new file mode 100644
> index 0000000000..395b61e7b2
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h
> @@ -0,0 +1,23 @@
> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
> +struct kernel_shmid64_ds
> +{
> +  struct ipc_perm shm_perm;
> +  size_t shm_segsz;
> +#if __TIMESIZE == 64
> +  long int shm_atime;
> +  long int shm_atime;
> +  long int shm_atime;
> +#else
> +  unsigned long int shm_atime;
> +  unsigned long int shm_atime_high;
> +  unsigned long int shm_dtime;
> +  unsigned long int shm_dtime_high;
> +  unsigned long int shm_ctime;
> +  unsigned long int shm_ctime_high;
> +#endif
> +  __pid_t shm_cpid;
> +  __pid_t shm_lpid;
> +  unsigned long int shm_nattch;
> +  unsigned long int __unused1;
> +  unsigned long int __unused2;
> +};
> 

OK.


-- 
Cheers,
Carlos.


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

* [PATCH v2] sysv: linux: Add 64-bit time_t variant for semctl
  2020-07-07 14:09   ` Adhemerval Zanella
@ 2020-07-08 15:32     ` Adhemerval Zanella
  2020-07-08 17:04       ` Carlos O'Donell
  0 siblings, 1 reply; 41+ messages in thread
From: Adhemerval Zanella @ 2020-07-08 15:32 UTC (permalink / raw)
  To: libc-alpha; +Cc: Alistair Francis, Vineet Gupta, Carlos O'Donell

This is a small updated version that basically does:

  git mv include/sys/sem.h sysdeps/unix/sysv/linux/include/sys/sem.h

And it moves the Linux specific requirements (since Hurd uses the
generic semop definition that does not call semtimedop).

--

Different than others 64-bit time_t syscalls, the SysIPC interface
does not provide a new set of syscall for y2038 safeness.  Instead it
uses unused fields in semid_ds structure to return the high bits for
the timestamps.

To provide a y2038 safe interface a new symbol __semctl64 is added
and __semctl is change to call it instead (it adds some extra buffer
copy for the 32 bit time_t implementation).

Two new structures are added:

  1. kernel_semid64_ds: used internally only on 32-bit architectures
     to issue the syscall.  A handful of architectures (hppa, i386,
     mips, powerpc32, sparc32) require specific implementations due
     their kernel ABI.

  2. semid_ds64: this is only for __TIMESIZE != 64 to use along with
     the 64-bit semctl.  It is different than the kernel struct because
     the exported 64-bit time_t might require different alignment
     depending of the architecture ABI.

So the resulting implementation does:

  1. For 64-bit architectures it assumes semid_ds already contains
     64-bit time_t fields and will result in just the __semctl symbol
     using the __semctl64 code.  The semid_ds argument is passed as-is
     to the syscall.

  2. For 32-bit architectures with default 64-bit time_t (newer ABIs
     such riscv32 or arc), it will also result in only one exported
     symbol but with the required high/low handling.

     It might be possible to optimize it further to avoid the
     kernel_semid64_ds to semun transformation if the exported ABI
     for the architectures matches the expected kernel ABI, but the
     implementation is already complex enough and don't think this
     should be a hotspot in any case.

  3. Finally for 32-bit architecture with both 32-bit and 64-bit time_t
     support we follow the already set way to provide one symbol with
     64-bit time_t support and implement the 32-bit time_t support
     using the 64-bit one.

     The default 32-bit symbol will allocate and copy the semid_ds
     over multiple buffers, but this should be deprecated in favor
     of the __semctl64 anyway.

Checked on i686-linux-gnu and x86_64-linux-gnu.  I also did some sniff
tests on powerpc, powerpc64, mips, mips64, armhf, sparcv9, and
sparc64.

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Tested-by: Vineet Gupta <vgupta@synopsys.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Tested-by: Carlos O'Donell <carlos@redhat.com>
---
 include/sys/sem.h                             |   9 -
 .../sysv/linux/bits/types/struct_semid64_ds.h |  33 +++
 .../sysv/linux/bits/types/struct_semid_ds.h   |  21 +-
 .../linux/hppa/bits/types/struct_semid_ds.h   |   6 +-
 .../linux/hppa/struct_kernel_semid64_ds.h     |  12 +
 .../linux/i386/struct_kernel_semid64_ds.h     |  12 +
 sysdeps/unix/sysv/linux/include/sys/sem.h     |  16 ++
 sysdeps/unix/sysv/linux/ipc_priv.h            |  10 +
 .../linux/mips/bits/types/struct_semid_ds.h   |   4 +-
 .../linux/mips/struct_kernel_semid64_ds.h     |  10 +
 .../powerpc/bits/types/struct_semid_ds.h      |   4 +-
 .../powerpc32/struct_kernel_semid64_ds.h      |  12 +
 sysdeps/unix/sysv/linux/semctl.c              | 261 +++++++++++++++---
 .../linux/sparc/bits/types/struct_semid_ds.h  |   4 +-
 .../sparc/sparc32/struct_kernel_semid64_ds.h  |  12 +
 .../sysv/linux/struct_kernel_semid64_ds.h     |  12 +
 .../linux/x86/bits/types/struct_semid_ds.h    |   4 +-
 17 files changed, 368 insertions(+), 74 deletions(-)
 delete mode 100644 include/sys/sem.h
 create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_semid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/hppa/struct_kernel_semid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/i386/struct_kernel_semid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/include/sys/sem.h
 create mode 100644 sysdeps/unix/sysv/linux/mips/struct_kernel_semid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_semid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_semid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/struct_kernel_semid64_ds.h

diff --git a/include/sys/sem.h b/include/sys/sem.h
deleted file mode 100644
index 69fdf1f752..0000000000
--- a/include/sys/sem.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _SYS_SEM_H
-# include <sysvipc/sys/sem.h>
-
-# ifndef _ISOMAC
-
-__typeof__ (semtimedop) __semtimedop attribute_hidden;
-
-# endif
-#endif
diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_semid64_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_semid64_ds.h
new file mode 100644
index 0000000000..bda9eb4469
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/bits/types/struct_semid64_ds.h
@@ -0,0 +1,33 @@
+/* Generic implementation of the semaphore struct semid64_ds.
+   Copyright (C) 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 __TIMESIZE == 64
+# define __semid64_ds semid_ds
+#else
+struct __semid64_ds
+{
+  struct ipc_perm sem_perm;		/* operation permission struct */
+  __time64_t sem_otime;			/* last semop() time */
+  __time64_t sem_ctime;			/* last time changed by semctl() */
+  __syscall_ulong_t sem_nsems;		/* number of semaphores in set */
+};
+#endif
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 4222e6a59f..bc26d8be08 100644
--- a/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h
+++ b/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h
@@ -21,26 +21,19 @@
 #endif
 
 /* Data structure describing a set of semaphores.  */
-#if __TIMESIZE == 32
 struct semid_ds
 {
   struct ipc_perm sem_perm;        /* operation permission struct */
+#if __TIMESIZE == 32
   __time_t sem_otime;              /* last semop() time */
-  __syscall_ulong_t __glibc_reserved1;
+  __syscall_ulong_t __sem_otime_high;
   __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;
-};
+  __syscall_ulong_t __sem_ctime_high;
 #else
-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 */
+  __time_t sem_otime;
+  __time_t sem_ctime;
+#endif
+  __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/hppa/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_semid_ds.h
index d4c50b5ef8..68f9eca24c 100644
--- a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_semid_ds.h
+++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_semid_ds.h
@@ -21,16 +21,14 @@
 #endif
 
 /* 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;
+  __syscall_ulong_t __sem_otime_high;
   __time_t sem_otime;         /* last semop() time */
-  __syscall_ulong_t __glibc_reserved2;
+  __syscall_ulong_t __sem_ctime_high;
   __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/hppa/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/hppa/struct_kernel_semid64_ds.h
new file mode 100644
index 0000000000..2871030d0d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/hppa/struct_kernel_semid64_ds.h
@@ -0,0 +1,12 @@
+/* Analogous to kernel struct semid64_ds used on semctl.  */
+struct kernel_semid64_ds
+{
+  struct ipc_perm sem_perm;
+  unsigned long sem_otime_high;
+  unsigned long sem_otime;
+  unsigned long sem_ctime_high;
+  unsigned long sem_ctime;
+  unsigned long sem_nsems;
+  unsigned long __ununsed1;
+  unsigned long __ununsed2;
+};
diff --git a/sysdeps/unix/sysv/linux/i386/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/i386/struct_kernel_semid64_ds.h
new file mode 100644
index 0000000000..bab9cf63ba
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/struct_kernel_semid64_ds.h
@@ -0,0 +1,12 @@
+/* Analogous to kernel struct semid64_ds used on semctl.  */
+struct kernel_semid64_ds
+{
+  struct ipc_perm sem_perm;
+  unsigned long sem_otime;
+  unsigned long sem_otime_high;
+  unsigned long sem_ctime;
+  unsigned long sem_ctime_high;
+  __syscall_ulong_t sem_nsems;
+  __syscall_ulong_t __unused3;
+  __syscall_ulong_t __unused4;
+};
diff --git a/sysdeps/unix/sysv/linux/include/sys/sem.h b/sysdeps/unix/sysv/linux/include/sys/sem.h
new file mode 100644
index 0000000000..a9151e057d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/include/sys/sem.h
@@ -0,0 +1,16 @@
+#ifndef _SYS_SEM_H
+# include <sysvipc/sys/sem.h>
+
+# ifndef _ISOMAC
+
+__typeof__ (semtimedop) __semtimedop attribute_hidden;
+
+#if __TIMESIZE == 64
+# define __semctl64 __semctl
+#else
+extern int __semctl64 (int semid, int semnum, int cmd, ...);
+libc_hidden_proto (__semctl64);
+#endif
+
+# endif
+#endif
diff --git a/sysdeps/unix/sysv/linux/ipc_priv.h b/sysdeps/unix/sysv/linux/ipc_priv.h
index 15a6e683a4..0bd6105e7b 100644
--- a/sysdeps/unix/sysv/linux/ipc_priv.h
+++ b/sysdeps/unix/sysv/linux/ipc_priv.h
@@ -53,4 +53,14 @@ struct __old_ipc_perm
 #define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
   (__nsops), 0, (__sops), (__timeout)
 
+/* Linux SysV ipc does not provide new syscalls for 64-bit time support on
+   32-bit architectures, but rather split the timestamp into high and low;
+   storing the high value in previously unused fields.  */
+#if (__WORDSIZE == 32 \
+     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
+# define __IPC_TIME64 1
+#else
+# define __IPC_TIME64 0
+#endif
+
 #include <ipc_ops.h>
diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h
index 8954209a29..eec4a18cae 100644
--- a/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h
+++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h
@@ -27,6 +27,6 @@ struct semid_ds
   __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;
+  __syscall_ulong_t __sem_otime_high;
+  __syscall_ulong_t __sem_ctime_high;
 };
diff --git a/sysdeps/unix/sysv/linux/mips/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/mips/struct_kernel_semid64_ds.h
new file mode 100644
index 0000000000..76a9d83ea5
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/struct_kernel_semid64_ds.h
@@ -0,0 +1,10 @@
+/* Analogous to kernel struct semid64_ds used on semctl.  */
+struct kernel_semid64_ds
+{
+  struct ipc_perm sem_perm;
+  unsigned long sem_otime;
+  unsigned long sem_ctime;
+  unsigned long sem_nsems;
+  unsigned long sem_otime_high;
+  unsigned long sem_ctime_high;
+};
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
index 300a9b98e9..d382d93c52 100644
--- a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_semid_ds.h
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_semid_ds.h
@@ -25,9 +25,9 @@ struct semid_ds
 {
   struct ipc_perm sem_perm;   /* operation permission struct */
 #if __TIMESIZE == 32
-  __syscall_ulong_t __glibc_reserved1;
+  __syscall_ulong_t __sem_otime_high;
   __time_t sem_otime;         /* last semop() time */
-  __syscall_ulong_t __glibc_reserved2;
+  __syscall_ulong_t __sem_ctime_high;
   __time_t sem_ctime;        /* last time changed by semctl() */
 #else
   __time_t sem_otime;         /* last semop() time */
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_semid64_ds.h
new file mode 100644
index 0000000000..7fa4ef6424
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_semid64_ds.h
@@ -0,0 +1,12 @@
+/* Analogous to kernel struct semid64_ds used on semctl.  */
+struct kernel_semid64_ds
+{
+  struct ipc_perm sem_perm;
+  unsigned long sem_otime_high;
+  unsigned long sem_otime;
+  unsigned long sem_ctime_high;
+  unsigned long sem_ctime;
+  unsigned long sem_nsems;
+  unsigned long __unused3;
+  unsigned long __unused4;
+};
diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c
index 30571af49f..90460e6310 100644
--- a/sysdeps/unix/sysv/linux/semctl.c
+++ b/sysdeps/unix/sysv/linux/semctl.c
@@ -21,10 +21,13 @@
 #include <ipc_priv.h>
 #include <sysdep.h>
 #include <shlib-compat.h>
-#include <errno.h>
-#include <linux/posix_types.h>  /* For __kernel_mode_t.  */
+#include <bits/types/struct_semid64_ds.h>  /* For __semid64_ds.  */
+#include <linux/posix_types.h>             /* For __kernel_mode_t.  */
 
-/* Define a `union semun' suitable for Linux here.  */
+/* The struct used to issue the syscall.  For architectures that assume
+   64-bit time as default (!__ASSUME_TIME64_SYSCALLS) the syscall will
+   split the resulting 64-bit sem_{o,c}time in two fields (sem_{o,c}time
+   and __sem_{o,c}time_high).  */
 union semun
 {
   int val;			/* value for SETVAL */
@@ -33,16 +36,89 @@ union semun
   struct seminfo *__buf;	/* buffer for IPC_INFO */
 };
 
-#ifndef DEFAULT_VERSION
-# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
-#  define DEFAULT_VERSION GLIBC_2_2
+#if __IPC_TIME64 == 0
+# define semun64 semun
+typedef union semun semctl_arg_t;
+#else
+# include <struct_kernel_semid64_ds.h>
+
+union ksemun64
+{
+  int val;
+  struct kernel_semid64_ds *buf;
+  unsigned short int *array;
+  struct seminfo *__buf;
+};
+
+# if __TIMESIZE == 64
+#  define semun64 semun
 # else
-#  define DEFAULT_VERSION GLIBC_2_31
+/* The struct used when __semctl64 is called.  */
+union semun64
+{
+  int val;
+  struct __semid64_ds *buf;
+  unsigned short int *array;
+  struct seminfo *__buf;
+};
 # endif
+
+static void
+semid64_to_ksemid64 (const struct __semid64_ds *semid64,
+		     struct kernel_semid64_ds *ksemid)
+{
+  ksemid->sem_perm       = semid64->sem_perm;
+  ksemid->sem_otime      = semid64->sem_otime;
+  ksemid->sem_otime_high = semid64->sem_otime >> 32;
+  ksemid->sem_ctime      = semid64->sem_ctime;
+  ksemid->sem_ctime_high = semid64->sem_ctime >> 32;
+  ksemid->sem_nsems      = semid64->sem_nsems;
+}
+
+static void
+ksemid64_to_semid64 (const struct kernel_semid64_ds *ksemid,
+		     struct __semid64_ds *semid64)
+{
+  semid64->sem_perm  = ksemid->sem_perm;
+  semid64->sem_otime = ksemid->sem_otime
+		       | ((__time64_t) ksemid->sem_otime_high << 32);
+  semid64->sem_ctime = ksemid->sem_ctime
+		       | ((__time64_t) ksemid->sem_ctime_high << 32);
+  semid64->sem_nsems = ksemid->sem_nsems;
+}
+
+static union ksemun64
+semun64_to_ksemun64 (int cmd, union semun64 semun64,
+		     struct kernel_semid64_ds *buf)
+{
+  union ksemun64 r = { 0 };
+  switch (cmd)
+    {
+    case SETVAL:
+      r.val = semun64.val;
+      break;
+    case GETALL:
+    case SETALL:
+      r.array = semun64.array;
+      break;
+    case IPC_STAT:
+    case IPC_SET:
+      r.buf = buf;
+      semid64_to_ksemid64 (semun64.buf, r.buf);
+      break;
+    case IPC_INFO:
+    case SEM_INFO:
+      r.__buf = semun64.__buf;
+      break;
+    }
+  return r;
+}
+
+typedef union ksemun64 semctl_arg_t;
 #endif
 
 static int
-semctl_syscall (int semid, int semnum, int cmd, union semun arg)
+semctl_syscall (int semid, int semnum, int cmd, semctl_arg_t arg)
 {
 #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
   return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64,
@@ -53,15 +129,15 @@ semctl_syscall (int semid, int semnum, int cmd, union semun arg)
 #endif
 }
 
+/* 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)");
+
 int
-__new_semctl (int semid, int semnum, int cmd, ...)
+__semctl64 (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 };
+  union semun64 arg64 = { 0 };
   va_list ap;
 
   /* Get the argument only if required.  */
@@ -76,44 +152,151 @@ __new_semctl (int semid, int semnum, int cmd, ...)
     case IPC_INFO:      /* arg.__buf */
     case SEM_INFO:
       va_start (ap, cmd);
-      arg = va_arg (ap, union semun);
+      arg64 = va_arg (ap, union semun64);
       va_end (ap);
       break;
     }
 
-#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;
-    }
+#if __IPC_TIME64
+  struct kernel_semid64_ds ksemid;
+  union ksemun64 ksemun = semun64_to_ksemun64 (cmd, arg64, &ksemid);
+  union ksemun64 arg = ksemun;
+#else
+  union semun arg = arg64;
 #endif
 
   int ret = semctl_syscall (semid, semnum, cmd, arg);
+  if (ret < 0)
+    return ret;
 
-  if (ret >= 0)
+  switch (cmd)
     {
-      switch (cmd)
-	{
-        case IPC_STAT:
-        case SEM_STAT:
-        case SEM_STAT_ANY:
+    case IPC_STAT:
+    case SEM_STAT:
+    case SEM_STAT_ANY:
 #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
-          arg.buf->sem_perm.mode >>= 16;
+      arg.buf->sem_perm.mode >>= 16;
 #else
-	  /* Old Linux kernel versions might not clear the mode padding.  */
-	  if (sizeof ((struct semid_ds){0}.sem_perm.mode)
-	      != sizeof (__kernel_mode_t))
-	    arg.buf->sem_perm.mode &= 0xFFFF;
+      /* Old Linux kernel versions might not clear the mode padding.  */
+      if (sizeof ((struct semid_ds){0}.sem_perm.mode)
+	  != sizeof (__kernel_mode_t))
+	arg.buf->sem_perm.mode &= 0xFFFF;
 #endif
-	}
+
+#if __IPC_TIME64
+      ksemid64_to_semid64 (arg.buf, arg64.buf);
+#endif
+    }
+
+  return ret;
+}
+#if __TIMESIZE != 64
+libc_hidden_def (__semctl64)
+
+
+/* The 64-bit time_t semid_ds version might have a different layout and
+   internal field alignment.  */
+static void
+semid64_ds_to_semid_ds (struct semid_ds *ds, const struct __semid64_ds *ds64)
+{
+  ds->sem_perm = ds64->sem_perm;
+  ds->sem_otime = ds64->sem_otime;
+  ds->sem_ctime = ds64->sem_ctime;
+  ds->sem_nsems = ds64->sem_nsems;
+}
+
+static void
+semid_ds_to_semid64_ds (struct __semid64_ds *ds64, const struct semid_ds *ds)
+{
+  ds64->sem_perm = ds->sem_perm;
+  ds64->sem_otime = ds->sem_otime
+		    | ((__time64_t) ds->__sem_otime_high << 32);
+  ds64->sem_ctime = ds->sem_ctime
+		    | ((__time64_t) ds->__sem_ctime_high << 32);
+  ds64->sem_nsems = ds->sem_nsems;
+}
+
+static union semun64
+semun_to_semun64 (int cmd, union semun semun, struct __semid64_ds *semid64)
+{
+  union semun64 r = { 0 };
+  switch (cmd)
+    {
+    case SETVAL:
+      r.val = semun.val;
+      break;
+    case GETALL:
+    case SETALL:
+      r.array = semun.array;
+      break;
+    case IPC_STAT:
+    case IPC_SET:
+      r.buf = semid64;
+      semid_ds_to_semid64_ds (r.buf, semun.buf);
+# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
+      if (cmd == IPC_SET)
+	r.buf->sem_perm.mode *= 0x10000U;
+# endif
+      break;
+    case IPC_INFO:
+    case SEM_INFO:
+      r.__buf = semun.__buf;
+      break;
+    }
+  return r;
+}
+
+int
+__semctl (int semid, int semnum, int cmd, ...)
+{
+  union semun arg = { 0 };
+
+  va_list ap;
+
+  /* Get the argument only if required.  */
+  switch (cmd)
+    {
+    case SETVAL:        /* arg.val */
+    case GETALL:        /* arg.array */
+    case SETALL:
+    case IPC_STAT:      /* arg.buf */
+    case IPC_SET:
+    case SEM_STAT:
+    case IPC_INFO:      /* arg.__buf */
+    case SEM_INFO:
+      va_start (ap, cmd);
+      arg = va_arg (ap, union semun);
+      va_end (ap);
+      break;
+    }
+
+  struct __semid64_ds semid64;
+  union semun64 arg64 = semun_to_semun64 (cmd, arg, &semid64);
+
+  int ret = __semctl64 (semid, semnum, cmd, arg64);
+  if (ret < 0)
+    return ret;
+
+  switch (cmd)
+    {
+    case IPC_STAT:
+    case SEM_STAT:
+    case SEM_STAT_ANY:
+      semid64_ds_to_semid_ds (arg.buf, arg64.buf);
     }
 
   return ret;
 }
-versioned_symbol (libc, __new_semctl, semctl, DEFAULT_VERSION);
+#endif
+
+#ifndef DEFAULT_VERSION
+# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
+#  define DEFAULT_VERSION GLIBC_2_2
+# else
+#  define DEFAULT_VERSION GLIBC_2_31
+# endif
+#endif
+versioned_symbol (libc, __semctl, semctl, DEFAULT_VERSION);
 
 #if defined __ASSUME_SYSVIPC_BROKEN_MODE_T \
     && SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_31)
@@ -121,7 +304,7 @@ int
 attribute_compat_text_section
 __semctl_mode16 (int semid, int semnum, int cmd, ...)
 {
-  union semun arg = { 0 };
+  semctl_arg_t arg = { 0 };
   va_list ap;
 
   /* Get the argument only if required.  */
@@ -136,7 +319,7 @@ __semctl_mode16 (int semid, int semnum, int cmd, ...)
     case IPC_INFO:      /* arg.__buf */
     case SEM_INFO:
       va_start (ap, cmd);
-      arg = va_arg (ap, union semun);
+      arg = va_arg (ap, semctl_arg_t);
       va_end (ap);
       break;
     }
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
index 46fcd79fb6..0110c1a940 100644
--- a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_semid_ds.h
+++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_semid_ds.h
@@ -25,9 +25,9 @@ struct semid_ds
 {
   struct ipc_perm sem_perm;   /* operation permission struct */
 #if __TIMESIZE == 32
-  __syscall_ulong_t __glibc_reserved1;
+  __syscall_ulong_t __sem_otime_high;
   __time_t sem_otime;         /* last semop() time */
-  __syscall_ulong_t __glibc_reserved2;
+  __syscall_ulong_t __sem_ctime_high;
   __time_t sem_ctime;        /* last time changed by semctl() */
 #else
   __time_t sem_otime;         /* last semop() time */
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_semid64_ds.h
new file mode 100644
index 0000000000..8c4697f9ab
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_semid64_ds.h
@@ -0,0 +1,12 @@
+/* Analogous to kernel struct semid64_ds used on semctl.  */
+struct kernel_semid64_ds
+{
+  struct ipc_perm sem_perm;
+  unsigned long sem_otime_high;
+  unsigned long sem_otime;
+  unsigned long sem_ctime_high;
+  unsigned long sem_ctime;
+  unsigned long sem_nsems;
+  unsigned long __unused1;
+  unsigned long __unused2;
+};
diff --git a/sysdeps/unix/sysv/linux/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/struct_kernel_semid64_ds.h
new file mode 100644
index 0000000000..f9edf0f76f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/struct_kernel_semid64_ds.h
@@ -0,0 +1,12 @@
+/* Analogous to kernel struct semid64_ds used on semctl.  */
+struct kernel_semid64_ds
+{
+  struct ipc_perm sem_perm;
+  unsigned long sem_otime;
+  unsigned long sem_otime_high;
+  unsigned long sem_ctime;
+  unsigned long sem_ctime_high;
+  unsigned long sem_nsems;
+  unsigned long __unused1;
+  unsigned long __unused2;
+};
diff --git a/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h
index f7ec89d115..c3f2fde9fd 100644
--- a/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h
+++ b/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h
@@ -25,9 +25,9 @@ struct semid_ds
 {
   struct ipc_perm sem_perm;   /* operation permission struct */
   __time_t sem_otime;  /* last semop() time */
-  __syscall_ulong_t __glibc_reserved1;
+  __syscall_ulong_t __sem_otime_high;
   __time_t sem_ctime;  /* last time changed by semctl() */
-  __syscall_ulong_t __glibc_reserved2;
+  __syscall_ulong_t __sem_ctime_high;
   __syscall_ulong_t sem_nsems;    /* number of semaphores in set */
   __syscall_ulong_t __glibc_reserved3;
   __syscall_ulong_t __glibc_reserved4;
-- 
2.25.1


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

* [PATCH v2] sysv: linux: Add 64-bit time_t variant for msgctl
  2020-07-07 19:51   ` Carlos O'Donell
@ 2020-07-08 15:32     ` Adhemerval Zanella
  2020-07-08 17:04       ` Carlos O'Donell
  2020-07-08 17:56       ` Alistair Francis
  0 siblings, 2 replies; 41+ messages in thread
From: Adhemerval Zanella @ 2020-07-08 15:32 UTC (permalink / raw)
  To: libc-alpha

This is a small updated version that basically does:

  git mv include/sys/msg.h sysdeps/unix/sysv/linux/include/sys/msg.h

It moves the sysvipc to be Linux specific, since the generic version
does implement _libc_msgsnd or __libc_msgrcv; and avoid a build failure
on Hurd (since it does not provide struct_msqid64_ds.h).

---

To provide a y2038 safe interface a new symbol __msgctl64 is added
and __msgctl is change to call it instead (it adds some extra buffer
coping for the 32 bit time_t implementation).

Two new structures are added:

  1. kernel_msqid64_ds: used internally only on 32-bit architectures
     to issue the syscall.  A handful of architectures (hppa, i386, mips,
     powerpc32, and sparc32) require specific implementations due to
     their kernel ABI.

  2. msqid_ds64: this is only for __TIMESIZE != 64 to use along with
     the 64-bit semctl.  It is different than the kernel struct because
     the exported 64-bit time_t might require different alignment
     depending on the architecture ABI.

So the resulting implementation does:

  1. For 64-bit architectures it assumes msqid_ds already contains
     64-bit time_t fields and will result in just the __msgctl symbol
     using the __msgctl64 code.  The msgid_ds argument is passed as-is
     to the syscall.

  2. For 32-bit architectures with default 64-bit time_t (newer ABIs
     such riscv32 or arc), it will also result in only one exported
     symbol but with the required high/low time handling.

  3. Finally for 32-bit architecture with both 32-bit and 64-bit time_t
     support we follow the already set way to provide one symbol with
     64-bit time_t support and implement the 32-bit time_t support using
     the 64-bit time_t.

     The default 32-bit symbol will allocate and copy the msqid_ds
     over multiple buffers, but this should be deprecated in favor
     of the __msgctl64 anyway.

Checked on i686-linux-gnu and x86_64-linux-gnu.  I also did some sniff
tests on powerpc, powerpc64, mips, mips64, armhf, sparcv9, and
sparc64.

Tested-by: Carlos O'Donell <carlos@redhat.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
---
 .../sysv/linux/bits/types/struct_msqid64_ds.h |  38 ++++
 .../sysv/linux/bits/types/struct_msqid_ds.h   |   6 +-
 .../linux/hppa/bits/types/struct_msqid_ds.h   |   6 +-
 .../linux/hppa/struct_kernel_msqid64_ds.h     |  18 ++
 .../linux/i386/struct_kernel_msqid64_ds.h     |  18 ++
 .../unix/sysv/linux/include}/sys/msg.h        |  10 +
 .../linux/mips/bits/types/struct_msqid_ds.h   |  12 +-
 .../linux/mips/struct_kernel_msqid64_ds.h     |  33 ++++
 sysdeps/unix/sysv/linux/msgctl.c              | 179 ++++++++++++++----
 .../powerpc/bits/types/struct_msqid_ds.h      |   6 +-
 .../powerpc32/struct_kernel_msqid64_ds.h      |  18 ++
 sysdeps/unix/sysv/linux/semctl.c              |  27 +--
 .../linux/sparc/bits/types/struct_msqid_ds.h  |   6 +-
 .../sparc/sparc32/struct_kernel_msqid64_ds.h  |  18 ++
 .../sysv/linux/struct_kernel_msqid64_ds.h     |  19 ++
 15 files changed, 350 insertions(+), 64 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h
 rename {include => sysdeps/unix/sysv/linux/include}/sys/msg.h (55%)
 create mode 100644 sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h

diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h
new file mode 100644
index 0000000000..3536c8ea62
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h
@@ -0,0 +1,38 @@
+/* Generic implementation of the SysV message struct msqid64_ds.
+   Copyright (C) 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_MSG_H
+# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
+#endif
+
+#if __TIMESIZE == 64
+# define __msqid64_ds msqid_ds
+#else
+struct __msqid64_ds
+{
+  struct ipc_perm msg_perm;	/* structure describing operation permission */
+  __time64_t msg_stime;		/* time of last msgsnd command */
+  __time64_t msg_rtime;		/* time of last msgsnd command */
+  __time64_t msg_ctime;		/* time of last change */
+  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
+  msgqnum_t msg_qnum;		/* number of messages currently on queue */
+  msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
+  __pid_t msg_lspid;		/* pid of last msgsnd() */
+  __pid_t msg_lrpid;		/* pid of last msgrcv() */
+};
+#endif
diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
index 32173a7b60..43b38175ad 100644
--- a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
+++ b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
@@ -27,11 +27,11 @@ struct msqid_ds
   struct ipc_perm msg_perm;	/* structure describing operation permission */
 #if __TIMESIZE == 32
   __time_t msg_stime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved1;
+  unsigned long int __msg_stime_high;
   __time_t msg_rtime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved2;
+  unsigned long int __msg_rtime_high;
   __time_t msg_ctime;		/* time of last change */
-  unsigned long int __glibc_reserved3;
+  unsigned long int __msg_ctime_high;
 #else
   __time_t msg_stime;		/* time of last msgsnd command */
   __time_t msg_rtime;		/* time of last msgsnd command */
diff --git a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
index 3cf70e36c4..16eac46941 100644
--- a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
+++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
@@ -26,11 +26,11 @@ struct msqid_ds
 {
   struct ipc_perm msg_perm;	/* structure describing operation permission */
 #if __TIMESIZE == 32
-  unsigned long int __glibc_reserved1;
+  unsigned long int __msg_stime_high;
   __time_t msg_stime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved2;
+  unsigned long int __msg_rtime_high;
   __time_t msg_rtime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved3;
+  unsigned long int __msg_ctime_high;
   __time_t msg_ctime;		/* time of last change */
 #else
   __time_t msg_stime;		/* time of last msgsnd command */
diff --git a/sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h
new file mode 100644
index 0000000000..69a63ee27a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h
@@ -0,0 +1,18 @@
+/* Analogous to kernel struct msqid64_ds used on msgctl.  */
+struct kernel_msqid64_ds
+{
+  struct ipc_perm msg_perm;
+  unsigned long msg_stime_high;
+  unsigned long msg_stime;
+  unsigned long msg_rtime_high;
+  unsigned long msg_rtime;
+  unsigned long msg_ctime_high;
+  unsigned long msg_ctime;
+  unsigned long msg_cbytes;
+  unsigned long msg_qnum;
+  unsigned long msg_qbytes;
+  __pid_t msg_lspid;
+  __pid_t msg_lrpid;
+  unsigned long __unused1;
+  unsigned long __unused2;
+};
diff --git a/sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h
new file mode 100644
index 0000000000..65b940567b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h
@@ -0,0 +1,18 @@
+/* Analogous to kernel struct compat_msqid64_ds used on msgctl.  */
+struct kernel_msqid64_ds
+{
+  struct ipc_perm msg_perm;
+  unsigned long msg_stime;
+  unsigned long msg_stime_high;
+  unsigned long msg_rtime;
+  unsigned long msg_rtime_high;
+  unsigned long msg_ctime;
+  unsigned long msg_ctime_high;
+  unsigned long msg_cbytes;
+  unsigned long msg_qnum;
+  unsigned long msg_qbytes;
+  __pid_t msg_lspid;
+  __pid_t msg_lrpid;
+  unsigned long __unused1;
+  unsigned long __unused2;
+};
diff --git a/include/sys/msg.h b/sysdeps/unix/sysv/linux/include/sys/msg.h
similarity index 55%
rename from include/sys/msg.h
rename to sysdeps/unix/sysv/linux/include/sys/msg.h
index 43ec5b9472..522903f818 100644
--- a/include/sys/msg.h
+++ b/sysdeps/unix/sysv/linux/include/sys/msg.h
@@ -6,6 +6,16 @@ extern ssize_t __libc_msgrcv (int msqid, void *msgp, size_t msgsz,
 			      long int msgtyp, int msgflg);
 extern int __libc_msgsnd (int msqid, const void *msgp, size_t msgsz,
 			  int msgflg);
+
+# include <bits/types/struct_msqid64_ds.h>
+
+# if __TIMESIZE == 64
+#  define __msgctl64 __msgctl
+# else
+extern int __msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf);
+libc_hidden_proto (__msgctl64);
+# endif
+
 #endif
 
 #endif
diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
index 85fdeef274..9ff010c763 100644
--- a/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
+++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
@@ -28,17 +28,17 @@ struct msqid_ds
 #if __TIMESIZE == 32
 # ifdef __MIPSEL__
   __time_t msg_stime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved1;
+  unsigned long int __msg_stime_high;
   __time_t msg_rtime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved2;
+  unsigned long int __msg_rtime_high;
   __time_t msg_ctime;		/* time of last change */
-  unsigned long int __glibc_reserved3;
+  unsigned long int __msg_ctime_high;
 # else
-  unsigned long int __glibc_reserved1;
+  unsigned long int __msg_stime_high;
   __time_t msg_stime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved2;
+  unsigned long int __msg_rtime_high;
   __time_t msg_rtime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved3;
+  unsigned long int __msg_ctime_high;
   __time_t msg_ctime;		/* time of last change */
 # endif
 #else
diff --git a/sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h
new file mode 100644
index 0000000000..9cfd5a0dfe
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h
@@ -0,0 +1,33 @@
+/* Analogous to kernel struct msqid64_ds used on msgctl.  */
+struct kernel_msqid64_ds
+{
+  struct ipc_perm msg_perm;
+#if __TIMESIZE == 32
+# ifdef __MIPSEL__
+  unsigned long int msg_stime;
+  unsigned long int msg_stime_high;
+  unsigned long int msg_rtime;
+  unsigned long int msg_rtime_high;
+  unsigned long int msg_ctime;
+  unsigned long int msg_ctime_high;
+# else
+  unsigned long int msg_stime_high;
+  unsigned long int msg_stime;
+  unsigned long int msg_rtime_high;
+  unsigned long int msg_rtime;
+  unsigned long int msg_ctime_high;
+  unsigned long int msg_ctime;
+# endif
+#else
+  unsigned long int msg_stime;
+  unsigned long int msg_rtime;
+  unsigned long int msg_ctime;
+#endif
+  unsigned long int msg_cbytes;
+  unsigned long int msg_qnum;
+  unsigned long int msg_qbytes;
+  __pid_t msg_lspid;
+  __pid_t msg_lrpid;
+  unsigned long int __unused1;
+  unsigned long int __unused2;
+};
diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c
index fd46aec1a0..a7f7651280 100644
--- a/sysdeps/unix/sysv/linux/msgctl.c
+++ b/sysdeps/unix/sysv/linux/msgctl.c
@@ -23,16 +23,55 @@
 #include <errno.h>
 #include <linux/posix_types.h>  /* For __kernel_mode_t.  */
 
-#ifndef DEFAULT_VERSION
-# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
-#  define DEFAULT_VERSION GLIBC_2_2
-# else
-#  define DEFAULT_VERSION GLIBC_2_31
-# endif
+/* POSIX states ipc_perm mode should have type of mode_t.  */
+_Static_assert (sizeof ((struct msqid_ds){0}.msg_perm.mode)
+		== sizeof (mode_t),
+		"sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");
+
+#if __IPC_TIME64 == 0
+typedef struct msqid_ds msgctl_arg_t;
+#else
+# include <struct_kernel_msqid64_ds.h>
+
+static void
+msqid64_to_kmsqid64 (const struct __msqid64_ds *msqid64,
+		     struct kernel_msqid64_ds *kmsqid)
+{
+  kmsqid->msg_perm       = msqid64->msg_perm;
+  kmsqid->msg_stime      = msqid64->msg_stime;
+  kmsqid->msg_stime_high = msqid64->msg_stime >> 32;
+  kmsqid->msg_rtime      = msqid64->msg_rtime;
+  kmsqid->msg_rtime_high = msqid64->msg_rtime >> 32;
+  kmsqid->msg_ctime      = msqid64->msg_ctime;
+  kmsqid->msg_ctime_high = msqid64->msg_ctime >> 32;
+  kmsqid->msg_qnum       = msqid64->msg_qnum;
+  kmsqid->msg_qbytes     = msqid64->msg_qbytes;
+  kmsqid->msg_lspid      = msqid64->msg_lspid;
+  kmsqid->msg_lrpid      = msqid64->msg_lrpid;
+}
+
+static void
+kmsqid64_to_msqid64 (const struct kernel_msqid64_ds *kmsqid,
+		     struct __msqid64_ds *msqid64)
+{
+  msqid64->msg_perm   = kmsqid->msg_perm;
+  msqid64->msg_stime  = kmsqid->msg_stime
+		        | ((__time64_t) kmsqid->msg_stime_high << 32);
+  msqid64->msg_rtime  = kmsqid->msg_rtime
+		        | ((__time64_t) kmsqid->msg_rtime_high << 32);
+  msqid64->msg_ctime  = kmsqid->msg_ctime
+		        | ((__time64_t) kmsqid->msg_ctime_high << 32);
+  msqid64->msg_qnum   = kmsqid->msg_qnum;
+  msqid64->msg_qbytes = kmsqid->msg_qbytes;
+  msqid64->msg_lspid  = kmsqid->msg_lspid;
+  msqid64->msg_lrpid  = kmsqid->msg_lrpid;
+}
+
+typedef struct kernel_msqid64_ds msgctl_arg_t;
 #endif
 
 static int
-msgctl_syscall (int msqid, int cmd, struct msqid_ds *buf)
+msgctl_syscall (int msqid, int cmd, msgctl_arg_t *buf)
 {
 #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
   return INLINE_SYSCALL_CALL (msgctl, msqid, cmd | __IPC_64, buf);
@@ -43,46 +82,118 @@ msgctl_syscall (int msqid, int cmd, struct msqid_ds *buf)
 }
 
 int
-__new_msgctl (int msqid, int cmd, struct msqid_ds *buf)
+__msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf)
 {
-  /* POSIX states ipc_perm mode should have type of mode_t.  */
-  _Static_assert (sizeof ((struct msqid_ds){0}.msg_perm.mode)
-		  == sizeof (mode_t),
-		  "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");
-
-#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
-  struct msqid_ds tmpds;
-  if (cmd == IPC_SET)
+#if __IPC_TIME64
+  struct kernel_msqid64_ds ksemid, *arg = NULL;
+  if (buf != NULL)
     {
-      tmpds = *buf;
-      tmpds.msg_perm.mode *= 0x10000U;
-      buf = &tmpds;
+      msqid64_to_kmsqid64 (buf, &ksemid);
+      arg = &ksemid;
     }
+# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
+  if (cmd == IPC_SET)
+    arg->msg_perm.mode *= 0x10000U;
+# endif
+#else
+  msgctl_arg_t *arg = buf;
 #endif
 
-  int ret = msgctl_syscall (msqid, cmd, buf);
+  int ret = msgctl_syscall (msqid, cmd, arg);
+  if (ret < 0)
+    return ret;
 
-  if (ret >= 0)
+  switch (cmd)
     {
-      switch (cmd)
-	{
-	case IPC_STAT:
-	case MSG_STAT:
-	case MSG_STAT_ANY:
+    case IPC_STAT:
+    case MSG_STAT:
+    case MSG_STAT_ANY:
 #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
-	  buf->msg_perm.mode >>= 16;
+      arg->msg_perm.mode >>= 16;
 #else
-	  /* Old Linux kernel versions might not clear the mode padding.  */
-	  if (sizeof ((struct msqid_ds){0}.msg_perm.mode)
-	      != sizeof (__kernel_mode_t))
-	    buf->msg_perm.mode &= 0xFFFF;
+      /* Old Linux kernel versions might not clear the mode padding.  */
+      if (sizeof ((struct msqid_ds){0}.msg_perm.mode)
+          != sizeof (__kernel_mode_t))
+	arg->msg_perm.mode &= 0xFFFF;
+#endif
+
+#if __IPC_TIME64
+      kmsqid64_to_msqid64 (arg, buf);
 #endif
-	}
     }
 
   return ret;
 }
-versioned_symbol (libc, __new_msgctl, msgctl, DEFAULT_VERSION);
+#if __TIMESIZE != 64
+libc_hidden_def (__msgctl64)
+
+static void
+msqid_to_msqid64 (struct __msqid64_ds *mq64, const struct msqid_ds *mq)
+{
+  mq64->msg_perm   = mq->msg_perm;
+  mq64->msg_stime  = mq->msg_stime
+		     | ((__time64_t) mq->__msg_stime_high << 32);
+  mq64->msg_rtime  = mq->msg_rtime
+		     | ((__time64_t) mq->__msg_rtime_high << 32);
+  mq64->msg_ctime  = mq->msg_ctime
+		     | ((__time64_t) mq->__msg_ctime_high << 32);
+  mq64->msg_qnum   = mq->msg_qnum;
+  mq64->msg_qbytes = mq->msg_qbytes;
+  mq64->msg_lspid  = mq->msg_lspid;
+  mq64->msg_lrpid  = mq->msg_lrpid;
+}
+
+static void
+msqid64_to_msqid (struct msqid_ds *mq, const struct __msqid64_ds *mq64)
+{
+  mq->msg_perm         = mq64->msg_perm;
+  mq->msg_stime        = mq64->msg_stime;
+  mq->__msg_stime_high = 0;
+  mq->msg_rtime        = mq64->msg_rtime;
+  mq->__msg_rtime_high = 0;
+  mq->msg_ctime        = mq64->msg_ctime;
+  mq->__msg_ctime_high = 0;
+  mq->msg_qnum         = mq64->msg_qnum;
+  mq->msg_qbytes       = mq64->msg_qbytes;
+  mq->msg_lspid        = mq64->msg_lspid;
+  mq->msg_lrpid        = mq64->msg_lrpid;
+}
+
+int
+__msgctl (int msqid, int cmd, struct msqid_ds *buf)
+{
+  struct __msqid64_ds msqid64, *buf64 = NULL;
+  if (buf != NULL)
+    {
+      msqid_to_msqid64 (&msqid64, buf);
+      buf64 = &msqid64;
+    }
+
+  int ret = __msgctl64 (msqid, cmd, buf64);
+  if (ret < 0)
+    return ret;
+
+  switch (cmd)
+    {
+    case IPC_STAT:
+    case MSG_STAT:
+    case MSG_STAT_ANY:
+      if (buf64 != NULL)
+        msqid64_to_msqid (buf, buf64);
+    }
+
+  return ret;
+}
+#endif
+
+#ifndef DEFAULT_VERSION
+# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
+#  define DEFAULT_VERSION GLIBC_2_2
+# else
+#  define DEFAULT_VERSION GLIBC_2_31
+# endif
+#endif
+versioned_symbol (libc, __msgctl, msgctl, DEFAULT_VERSION);
 
 #if defined __ASSUME_SYSVIPC_BROKEN_MODE_T \
     && SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_31)
@@ -90,7 +201,7 @@ int
 attribute_compat_text_section
 __msgctl_mode16 (int msqid, int cmd, struct msqid_ds *buf)
 {
-  return msgctl_syscall (msqid, cmd, buf);
+  return msgctl_syscall (msqid, cmd, (msgctl_arg_t *) buf);
 }
 compat_symbol (libc, __msgctl_mode16, msgctl, GLIBC_2_2);
 #endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
index 4ae2fbcbdc..35cc51f733 100644
--- a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
@@ -26,11 +26,11 @@ struct msqid_ds
 {
   struct ipc_perm msg_perm;	/* structure describing operation permission */
 #if __TIMESIZE == 32
-  unsigned long int __glibc_reserved1;
+  unsigned long int __msg_stime_high;
   __time_t msg_stime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved2;
+  unsigned long int __msg_rtime_high;
   __time_t msg_rtime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved3;
+  unsigned long int __msg_ctime_high;
   __time_t msg_ctime;		/* time of last change */
 #else
   __time_t msg_stime;		/* time of last msgsnd command */
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h
new file mode 100644
index 0000000000..69a63ee27a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h
@@ -0,0 +1,18 @@
+/* Analogous to kernel struct msqid64_ds used on msgctl.  */
+struct kernel_msqid64_ds
+{
+  struct ipc_perm msg_perm;
+  unsigned long msg_stime_high;
+  unsigned long msg_stime;
+  unsigned long msg_rtime_high;
+  unsigned long msg_rtime;
+  unsigned long msg_ctime_high;
+  unsigned long msg_ctime;
+  unsigned long msg_cbytes;
+  unsigned long msg_qnum;
+  unsigned long msg_qbytes;
+  __pid_t msg_lspid;
+  __pid_t msg_lrpid;
+  unsigned long __unused1;
+  unsigned long __unused2;
+};
diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c
index 90460e6310..005c00ea75 100644
--- a/sysdeps/unix/sysv/linux/semctl.c
+++ b/sysdeps/unix/sysv/linux/semctl.c
@@ -196,19 +196,11 @@ libc_hidden_def (__semctl64)
 
 /* The 64-bit time_t semid_ds version might have a different layout and
    internal field alignment.  */
-static void
-semid64_ds_to_semid_ds (struct semid_ds *ds, const struct __semid64_ds *ds64)
-{
-  ds->sem_perm = ds64->sem_perm;
-  ds->sem_otime = ds64->sem_otime;
-  ds->sem_ctime = ds64->sem_ctime;
-  ds->sem_nsems = ds64->sem_nsems;
-}
 
 static void
-semid_ds_to_semid64_ds (struct __semid64_ds *ds64, const struct semid_ds *ds)
+semid_to_semid64 (struct __semid64_ds *ds64, const struct semid_ds *ds)
 {
-  ds64->sem_perm = ds->sem_perm;
+  ds64->sem_perm  = ds->sem_perm;
   ds64->sem_otime = ds->sem_otime
 		    | ((__time64_t) ds->__sem_otime_high << 32);
   ds64->sem_ctime = ds->sem_ctime
@@ -216,6 +208,17 @@ semid_ds_to_semid64_ds (struct __semid64_ds *ds64, const struct semid_ds *ds)
   ds64->sem_nsems = ds->sem_nsems;
 }
 
+static void
+semid64_to_semid (struct semid_ds *ds, const struct __semid64_ds *ds64)
+{
+  ds->sem_perm         = ds64->sem_perm;
+  ds->sem_otime        = ds64->sem_otime;
+  ds->__sem_otime_high = 0;
+  ds->sem_ctime        = ds64->sem_ctime;
+  ds->__sem_ctime_high = 0;
+  ds->sem_nsems        = ds64->sem_nsems;
+}
+
 static union semun64
 semun_to_semun64 (int cmd, union semun semun, struct __semid64_ds *semid64)
 {
@@ -232,7 +235,7 @@ semun_to_semun64 (int cmd, union semun semun, struct __semid64_ds *semid64)
     case IPC_STAT:
     case IPC_SET:
       r.buf = semid64;
-      semid_ds_to_semid64_ds (r.buf, semun.buf);
+      semid_to_semid64 (r.buf, semun.buf);
 # ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
       if (cmd == IPC_SET)
 	r.buf->sem_perm.mode *= 0x10000U;
@@ -282,7 +285,7 @@ __semctl (int semid, int semnum, int cmd, ...)
     case IPC_STAT:
     case SEM_STAT:
     case SEM_STAT_ANY:
-      semid64_ds_to_semid_ds (arg.buf, arg64.buf);
+      semid64_to_semid (arg.buf, arg64.buf);
     }
 
   return ret;
diff --git a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
index 71980839c7..502c23d91e 100644
--- a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
+++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
@@ -26,11 +26,11 @@ struct msqid_ds
 {
   struct ipc_perm msg_perm;	/* structure describing operation permission */
 #if __TIMESIZE == 32
-  unsigned long int __glibc_reserved1;
+  unsigned long int __msg_stime_high;
   __time_t msg_stime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved2;
+  unsigned long int __msg_rtime_high;
   __time_t msg_rtime;		/* time of last msgsnd command */
-  unsigned long int __glibc_reserved3;
+  unsigned long int __msg_ctime_high;
   __time_t msg_ctime;		/* time of last change */
 #else
   __time_t msg_stime;		/* time of last msgsnd command */
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h
new file mode 100644
index 0000000000..69a63ee27a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h
@@ -0,0 +1,18 @@
+/* Analogous to kernel struct msqid64_ds used on msgctl.  */
+struct kernel_msqid64_ds
+{
+  struct ipc_perm msg_perm;
+  unsigned long msg_stime_high;
+  unsigned long msg_stime;
+  unsigned long msg_rtime_high;
+  unsigned long msg_rtime;
+  unsigned long msg_ctime_high;
+  unsigned long msg_ctime;
+  unsigned long msg_cbytes;
+  unsigned long msg_qnum;
+  unsigned long msg_qbytes;
+  __pid_t msg_lspid;
+  __pid_t msg_lrpid;
+  unsigned long __unused1;
+  unsigned long __unused2;
+};
diff --git a/sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h
new file mode 100644
index 0000000000..b88d910adc
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h
@@ -0,0 +1,19 @@
+/* Analogous to kernel struct msqid64_ds used on msgctl.  It is only used
+   for 32-bit architectures on 64-bit time_t msgctl64 implementation.  */
+struct kernel_msqid64_ds
+{
+  struct ipc_perm msg_perm;
+  unsigned long int msg_stime;
+  unsigned long int msg_stime_high;
+  unsigned long int msg_rtime;
+  unsigned long int msg_rtime_high;
+  unsigned long int msg_ctime;
+  unsigned long int msg_ctime_high;
+  unsigned long int msg_cbytes;
+  unsigned long int msg_qnum;
+  unsigned long int msg_qbytes;
+  __pid_t msg_lspid;
+  __pid_t msg_lrpid;
+  unsigned long int __unused4;
+  unsigned long int __unused5;
+};
-- 
2.25.1


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

* [PATCH v2] sysv: linux: Add 64-bit time_t variant for shmctl
  2020-07-07 21:33   ` Carlos O'Donell
@ 2020-07-08 15:32     ` Adhemerval Zanella
  2020-07-08 17:02       ` Carlos O'Donell
                         ` (2 more replies)
  0 siblings, 3 replies; 41+ messages in thread
From: Adhemerval Zanella @ 2020-07-08 15:32 UTC (permalink / raw)
  To: libc-alpha

This is a small updated version that basically does:

  git mv include/sys/shm.h sysdeps/unix/sysv/linux/include/sys/shm.h

It basically avoids a build failure on Hurd (since it does not provide
struct_shmid64_ds.h).

---

To provide a y2038 safe interface a new symbol __shmctl64 is added
and __shmctl is change to call it instead (it adds some extra buffer
coping for the 32 bit time_t implementation).

Two two new structures are added:

  1. kernel_shmid64_ds: used internally only on 32-bit architectures
     to issue the syscall.  A handful of architectures (hppa, i386,
     mips, powerpc32, and sparc32) require specific implementations
     due to their kernel ABI.

  2. shmid_ds64: this is only for __TIMESIZE != 64 to use along with
     the 64-bit semctl.  It is different than the kernel struct because
     the exported 64-bit time_t might require different alignment
     depending on the architecture ABI.

So the resulting implementation does:

  1. For 64-bit architectures it assumes shmid_ds already contains
     64-bit time_t fields and will result in just the __shmctl symbol
     using the __shmctl64 code.  The shmid_ds argument is passed as-is
     to the syscall.

  2. For 32-bit architectures with default 64-bit time_t (newer ABIs
     such riscv32 or arc), it will also result in only one exported
     symbol but with the required high/low time handling.

  3. Finally for 32-bit architecture with both 32-bit and 64-bit time_t
     support we follow the already set way to provide one symbol with
     64-bit time_t support and implement the 32-bit time_t support
     using of the 64-bit one.

     The default 32-bit symbol will allocate and copy the shmid_ds
     over multiple buffers, but this should be deprecated in favor
     of the __shmctl64 anyway.

Checked on i686-linux-gnu and x86_64-linux-gnu.  I also did some sniff
tests on powerpc, powerpc64, mips, mips64, armhf, sparcv9, and
sparc64.

Tested-by: Carlos O'Donell <carlos@redhat.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
---
 include/sys/shm.h                             |   1 -
 .../sysv/linux/bits/types/struct_shmid64_ds.h |  37 ++++
 .../sysv/linux/bits/types/struct_shmid_ds.h   |   6 +-
 .../linux/hppa/bits/types/struct_shmid_ds.h   |   6 +-
 .../linux/hppa/struct_kernel_shmid64_ds.h     |  18 ++
 .../linux/i386/struct_kernel_shmid64_ds.h     |  17 ++
 sysdeps/unix/sysv/linux/include/sys/shm.h     |  17 ++
 .../linux/mips/bits/types/struct_shmid_ds.h   |   6 +-
 .../linux/mips/struct_kernel_shmid64_ds.h     |  27 +++
 .../powerpc/bits/types/struct_shmid_ds.h      |   6 +-
 .../linux/powerpc/struct_kernel_shmid64_ds.h  |  18 ++
 sysdeps/unix/sysv/linux/shmctl.c              | 180 ++++++++++++++----
 .../linux/sparc/bits/types/struct_shmid_ds.h  |   6 +-
 .../linux/sparc/struct_kernel_shmid64_ds.h    |  17 ++
 .../sysv/linux/struct_kernel_shmid64_ds.h     |  17 ++
 15 files changed, 329 insertions(+), 50 deletions(-)
 delete mode 100644 include/sys/shm.h
 create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/include/sys/shm.h
 create mode 100644 sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h
 create mode 100644 sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h

diff --git a/include/sys/shm.h b/include/sys/shm.h
deleted file mode 100644
index 1878fcc5be..0000000000
--- a/include/sys/shm.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysvipc/sys/shm.h>
diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h
new file mode 100644
index 0000000000..f71e0d28ff
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h
@@ -0,0 +1,37 @@
+/* Generic implementation of the shared memory struct shmid_ds.
+   Copyright (C) 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_SHM_H
+# error "Never include <bits/types/struct_shmid_ds.h> directly; use <sys/shm.h> instead."
+#endif
+
+#if __TIMESIZE == 64
+# define __shmid64_ds shmid_ds
+#else
+struct __shmid64_ds
+{
+  struct ipc_perm shm_perm;	/* operation permission struct */
+  size_t shm_segsz;		/* size of segment in bytes */
+  __time64_t shm_atime;		/* time of last shmat() */
+  __time64_t shm_dtime;		/* time of last shmdt() */
+  __time64_t shm_ctime;		/* time of last change by shmctl() */
+  __pid_t shm_cpid;		/* pid of creator */
+  __pid_t shm_lpid;		/* pid of last shmop */
+  shmatt_t shm_nattch;		/* number of current attaches */
+};
+#endif
diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
index 61ed4a08c3..836a7d50e9 100644
--- a/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
+++ b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
@@ -27,11 +27,11 @@ struct shmid_ds
     size_t shm_segsz;			/* size of segment in bytes */
 #if __TIMESIZE == 32
     __time_t shm_atime;			/* time of last shmat() */
-    unsigned long int __glibc_reserved1;
+    unsigned long int __shm_atime_high;
     __time_t shm_dtime;			/* time of last shmdt() */
-    unsigned long int __glibc_reserved2;
+    unsigned long int __shm_dtime_high;
     __time_t shm_ctime;			/* time of last change by shmctl() */
-    unsigned long int __glibc_reserved3;
+    unsigned long int __shm_ctime_high;
 #else
     __time_t shm_atime;			/* time of last shmat() */
     __time_t shm_dtime;			/* time of last shmdt() */
diff --git a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
index 1ebf222eac..1abed1e149 100644
--- a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
+++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
@@ -25,11 +25,11 @@ struct shmid_ds
   {
     struct ipc_perm shm_perm;		/* operation permission struct */
 #if __TIMESIZE == 32
-    unsigned long int __glibc_reserved1;
+    unsigned long int __shm_atime_high;
     __time_t shm_atime;			/* time of last shmat() */
-    unsigned long int __glibc_reserved2;
+    unsigned long int __shm_dtime_high;
     __time_t shm_dtime;			/* time of last shmdt() */
-    unsigned long int __glibc_reserved3;
+    unsigned long int __shm_ctime_high;
     __time_t shm_ctime;			/* time of last change by shmctl() */
     unsigned long int __glibc_reserved4;
 #else
diff --git a/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h
new file mode 100644
index 0000000000..4d09fc7f62
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h
@@ -0,0 +1,18 @@
+/* Analogous to kernel struct shmid64_ds used on shmctl.  */
+struct kernel_shmid64_ds
+{
+  struct ipc_perm shm_perm;		/* operation permission struct */
+  unsigned long int shm_atime_high;
+  unsigned long int shm_atime;		/* time of last shmat() */
+  unsigned long int shm_dtime_high;
+  unsigned long int shm_dtime;		/* time of last shmdt() */
+  unsigned long int shm_ctime_high;
+  unsigned long int shm_ctime;		/* time of last change by shmctl() */
+  unsigned long int __pad;
+  size_t shm_segsz;			/* size of segment in bytes */
+  __pid_t shm_cpid;			/* pid of creator */
+  __pid_t shm_lpid;			/* pid of last shmop */
+  shmatt_t shm_nattch;		/* number of current attaches */
+  unsigned long int __unused1;
+  unsigned long int __unused2;
+};
diff --git a/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h
new file mode 100644
index 0000000000..6a0a0d9c71
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h
@@ -0,0 +1,17 @@
+/* Analogous to kernel struct compat_shmid64_ds used on shmctl.  */
+struct kernel_shmid64_ds
+{
+  struct ipc_perm shm_perm;
+  size_t shm_segsz;
+  unsigned long int shm_atime;
+  unsigned long int shm_atime_high;
+  unsigned long int shm_dtime;
+  unsigned long int shm_dtime_high;
+  unsigned long int shm_ctime;
+  unsigned long int shm_ctime_high;
+  __pid_t shm_cpid;
+  __pid_t shm_lpid;
+  unsigned long int shm_nattch;
+  unsigned long int __unused4;
+  unsigned long int __unused5;
+};
diff --git a/sysdeps/unix/sysv/linux/include/sys/shm.h b/sysdeps/unix/sysv/linux/include/sys/shm.h
new file mode 100644
index 0000000000..530a1cdfc9
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/include/sys/shm.h
@@ -0,0 +1,17 @@
+#ifndef _SYS_SHM_H
+#include <sysvipc/sys/shm.h>
+
+#ifndef _ISOMAC
+
+# include <bits/types/struct_shmid64_ds.h>
+
+# if __TIMESIZE == 64
+#  define __shmctl64 __shmctl
+# else
+extern int __shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf);
+libc_hidden_proto (__shmctl64);
+# endif
+
+#endif /* _ISOMAC  */
+
+#endif /* _SYS_SHM_H  */
diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
index 8e13928980..58090e2fcb 100644
--- a/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
+++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
@@ -38,9 +38,9 @@ struct shmid_ds
     __pid_t shm_lpid;			/* pid of last shmop */
     shmatt_t shm_nattch;		/* number of current attaches */
 #if __TIMESIZE == 32
-    unsigned short int __glibc_reserved1;
-    unsigned short int __glibc_reserved2;
-    unsigned short int __glibc_reserved3;
+    unsigned short int __shm_atime_high;
+    unsigned short int __shm_dtime_high;
+    unsigned short int __shm_ctime_high;
     unsigned short int __glibc_reserved4;
 #else
     __syscall_ulong_t __glibc_reserved5;
diff --git a/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h
new file mode 100644
index 0000000000..a4baa5614f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h
@@ -0,0 +1,27 @@
+/* Analogous to kernel struct shmid64_ds used on shmctl.  */
+struct kernel_shmid64_ds
+{
+  struct ipc_perm shm_perm;
+  size_t shm_segsz;
+#if __TIMESIZE == 64
+  long int shm_atime;
+  long int shm_dtime;
+  long int shm_ctime;
+#else
+  unsigned long int shm_atime;
+  unsigned long int shm_dtime;
+  unsigned long int shm_ctime;
+#endif
+  __pid_t shm_cpid;
+  __pid_t shm_lpid;
+  unsigned long int shm_nattch;
+#if __TIMESIZE == 64
+  unsigned long int __unused1;
+  unsigned long int __unused2;
+#else
+  unsigned short int shm_atime_high;
+  unsigned short int shm_dtime_high;
+  unsigned short int shm_ctime_high;
+  unsigned short int __ununsed1;
+#endif
+};
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
index b0816fb16a..39b3e5fd3e 100644
--- a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
@@ -25,11 +25,11 @@ struct shmid_ds
   {
     struct ipc_perm shm_perm;		/* operation permission struct */
 #if __TIMESIZE == 32
-    unsigned long int __glibc_reserved1;
+    unsigned long int __shm_atime_high;
     __time_t shm_atime;			/* time of last shmat() */
-    unsigned long int __glibc_reserved2;
+    unsigned long int __shm_dtime_high;
     __time_t shm_dtime;			/* time of last shmdt() */
-    unsigned long int __glibc_reserved3;
+    unsigned long int __shm_ctime_high;
     __time_t shm_ctime;			/* time of last change by shmctl() */
     unsigned long int __glibc_reserved4;
 #else
diff --git a/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
new file mode 100644
index 0000000000..ae3f3987ac
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
@@ -0,0 +1,18 @@
+/* Analogous to kernel struct shmid64_ds used on shmctl.  */
+struct kernel_shmid64_ds
+{
+  struct ipc_perm shm_perm;
+  unsigned long int shm_atime_high;
+  unsigned long int shm_atime;
+  unsigned long int shm_dtime_high;
+  unsigned long int shm_dtime;
+  unsigned long int shm_ctime_high;
+  unsigned long int shm_ctime;
+  unsigned long int __ununsed1;
+  size_t shm_segsz;
+  __pid_t shm_cpid;
+  __pid_t shm_lpid;
+  unsigned long int shm_nattch;
+  unsigned long int __unused2;
+  unsigned long int __unused3;
+};
diff --git a/sysdeps/unix/sysv/linux/shmctl.c b/sysdeps/unix/sysv/linux/shmctl.c
index f41b359b8b..aaf3946054 100644
--- a/sysdeps/unix/sysv/linux/shmctl.c
+++ b/sysdeps/unix/sysv/linux/shmctl.c
@@ -24,16 +24,55 @@
 #include <errno.h>
 #include <linux/posix_types.h>  /* For __kernel_mode_t.  */
 
-#ifndef DEFAULT_VERSION
-# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
-#  define DEFAULT_VERSION GLIBC_2_2
-# else
-#  define DEFAULT_VERSION GLIBC_2_31
-# endif
+/* POSIX states ipc_perm mode should have type of mode_t.  */
+_Static_assert (sizeof ((struct shmid_ds){0}.shm_perm.mode)
+		== sizeof (mode_t),
+		"sizeof (shmid_ds.shm_perm.mode) != sizeof (mode_t)");
+
+#if __IPC_TIME64 == 0
+typedef struct shmid_ds shmctl_arg_t;
+#else
+# include <struct_kernel_shmid64_ds.h>
+
+static void
+shmid64_to_kshmid64 (const struct __shmid64_ds *shmid64,
+		     struct kernel_shmid64_ds *kshmid)
+{
+  kshmid->shm_perm       = shmid64->shm_perm;
+  kshmid->shm_segsz      = shmid64->shm_segsz;
+  kshmid->shm_atime      = shmid64->shm_atime;
+  kshmid->shm_atime_high = shmid64->shm_atime >> 32;
+  kshmid->shm_dtime      = shmid64->shm_dtime;
+  kshmid->shm_dtime_high = shmid64->shm_dtime >> 32;
+  kshmid->shm_ctime      = shmid64->shm_ctime;
+  kshmid->shm_ctime_high = shmid64->shm_ctime >> 32;
+  kshmid->shm_cpid       = shmid64->shm_cpid;
+  kshmid->shm_lpid       = shmid64->shm_lpid;
+  kshmid->shm_nattch     = shmid64->shm_nattch;
+}
+
+static void
+kshmid64_to_shmid64 (const struct kernel_shmid64_ds *kshmid,
+		     struct __shmid64_ds *shmid64)
+{
+  shmid64->shm_perm   = kshmid->shm_perm;
+  shmid64->shm_segsz  = kshmid->shm_segsz;
+  shmid64->shm_atime  = kshmid->shm_atime
+		        | ((__time64_t) kshmid->shm_atime_high << 32);
+  shmid64->shm_dtime  = kshmid->shm_dtime
+		        | ((__time64_t) kshmid->shm_dtime_high << 32);
+  shmid64->shm_ctime     = kshmid->shm_ctime
+		        | ((__time64_t) kshmid->shm_ctime_high << 32);
+  shmid64->shm_cpid   = kshmid->shm_cpid;
+  shmid64->shm_lpid   = kshmid->shm_lpid;
+  shmid64->shm_nattch = kshmid->shm_nattch;
+}
+
+typedef struct kernel_shmid64_ds shmctl_arg_t;
 #endif
 
 static int
-shmctl_syscall (int shmid, int cmd, struct shmid_ds *buf)
+shmctl_syscall (int shmid, int cmd, shmctl_arg_t *buf)
 {
 #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
   return INLINE_SYSCALL_CALL (shmctl, shmid, cmd | __IPC_64, buf);
@@ -45,46 +84,119 @@ shmctl_syscall (int shmid, int cmd, struct shmid_ds *buf)
 
 /* Provide operations to control over shared memory segments.  */
 int
-__new_shmctl (int shmid, int cmd, struct shmid_ds *buf)
+__shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf)
 {
-  /* POSIX states ipc_perm mode should have type of mode_t.  */
-  _Static_assert (sizeof ((struct shmid_ds){0}.shm_perm.mode)
-		  == sizeof (mode_t),
-		  "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");
-
-#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
-  struct shmid_ds tmpds;
-  if (cmd == IPC_SET)
+#if __IPC_TIME64
+  struct kernel_shmid64_ds kshmid, *arg = NULL;
+  if (buf != NULL)
     {
-      tmpds = *buf;
-      tmpds.shm_perm.mode *= 0x10000U;
-      buf = &tmpds;
+      shmid64_to_kshmid64 (buf, &kshmid);
+      arg = &kshmid;
     }
+# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
+  if (cmd == IPC_SET)
+      arg->shm_perm.mode *= 0x10000U;
+# endif
+#else
+  shmctl_arg_t *arg = buf;
 #endif
 
-  int ret = shmctl_syscall (shmid, cmd, buf);
+  int ret = shmctl_syscall (shmid, cmd, arg);
+  if (ret < 0)
+    return ret;
 
-  if (ret >= 0)
+  switch (cmd)
     {
-      switch (cmd)
-	{
-        case IPC_STAT:
-        case SHM_STAT:
-        case SHM_STAT_ANY:
+      case IPC_STAT:
+      case SHM_STAT:
+      case SHM_STAT_ANY:
 #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
-          buf->shm_perm.mode >>= 16;
+        arg->shm_perm.mode >>= 16;
 #else
-	  /* Old Linux kernel versions might not clear the mode padding.  */
-	  if (sizeof ((struct shmid_ds){0}.shm_perm.mode)
-	      != sizeof (__kernel_mode_t))
-	    buf->shm_perm.mode &= 0xFFFF;
+      /* Old Linux kernel versions might not clear the mode padding.  */
+      if (sizeof ((struct shmid_ds){0}.shm_perm.mode)
+	  != sizeof (__kernel_mode_t))
+	arg->shm_perm.mode &= 0xFFFF;
+#endif
+
+#if __IPC_TIME64
+      kshmid64_to_shmid64 (arg, buf);
 #endif
-	}
     }
 
   return ret;
 }
-versioned_symbol (libc, __new_shmctl, shmctl, DEFAULT_VERSION);
+#if __TIMESIZE != 64
+libc_hidden_def (__shmctl64)
+
+static void
+shmid_to_shmid64 (struct __shmid64_ds *shm64, const struct shmid_ds *shm)
+{
+  shm64->shm_perm   = shm->shm_perm;
+  shm64->shm_segsz  = shm->shm_segsz;
+  shm64->shm_atime  = shm->shm_atime
+		        | ((__time64_t) shm->__shm_atime_high << 32);
+  shm64->shm_dtime  = shm->shm_dtime
+		        | ((__time64_t) shm->__shm_dtime_high << 32);
+  shm64->shm_ctime     = shm->shm_ctime
+		        | ((__time64_t) shm->__shm_ctime_high << 32);
+  shm64->shm_cpid   = shm->shm_cpid;
+  shm64->shm_lpid   = shm->shm_lpid;
+  shm64->shm_nattch = shm->shm_nattch;
+}
+
+static void
+shmid64_to_shmid (struct shmid_ds *shm, const struct __shmid64_ds *shm64)
+{
+  shm->shm_perm         = shm64->shm_perm;
+  shm->shm_segsz        = shm64->shm_segsz;
+  shm->shm_atime        = shm64->shm_atime;
+  shm->__shm_atime_high = 0;
+  shm->shm_dtime        = shm64->shm_dtime;
+  shm->__shm_dtime_high = 0;
+  shm->shm_ctime        = shm64->shm_ctime;
+  shm->__shm_ctime_high = 0;
+  shm->shm_cpid         = shm64->shm_cpid;
+  shm->shm_lpid         = shm64->shm_lpid;
+  shm->shm_nattch       = shm64->shm_nattch;
+}
+
+int
+__shmctl (int shmid, int cmd, struct shmid_ds *buf)
+{
+  struct __shmid64_ds shmid64, *buf64 = NULL;
+  if (buf != NULL)
+    {
+      shmid_to_shmid64 (&shmid64, buf);
+      buf64 = &shmid64;
+    }
+
+  int ret = __shmctl64 (shmid, cmd, buf64);
+  if (ret < 0)
+    return ret;
+
+  switch (cmd)
+    {
+      case IPC_STAT:
+      case SHM_STAT:
+      case SHM_STAT_ANY:
+	if (buf64 != NULL)
+	  shmid64_to_shmid (buf, buf64);
+    }
+
+  return ret;
+}
+#endif
+
+#ifndef DEFAULT_VERSION
+# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
+#  define DEFAULT_VERSION GLIBC_2_2
+# else
+#  define DEFAULT_VERSION GLIBC_2_31
+# endif
+#endif
+
+versioned_symbol (libc, __shmctl, shmctl, DEFAULT_VERSION);
 
 #if defined __ASSUME_SYSVIPC_BROKEN_MODE_T \
     && SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_31)
@@ -92,7 +204,7 @@ int
 attribute_compat_text_section
 __shmctl_mode16 (int shmid, int cmd, struct shmid_ds *buf)
 {
-  return shmctl_syscall (shmid, cmd, buf);
+  return shmctl_syscall (shmid, cmd, (shmctl_arg_t *) buf);
 }
 compat_symbol (libc, __shmctl_mode16, shmctl, GLIBC_2_2);
 #endif
diff --git a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h
index d5fb61d374..cab3a2686f 100644
--- a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h
+++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h
@@ -25,11 +25,11 @@ struct shmid_ds
   {
     struct ipc_perm shm_perm;		/* operation permission struct */
 #if __TIMESIZE == 32
-    unsigned long int __glibc_reserved1;
+    unsigned long int __shm_atime_high;
     __time_t shm_atime;			/* time of last shmat() */
-    unsigned long int __glibc_reserved2;
+    unsigned long int __shm_dtime_high;
     __time_t shm_dtime;			/* time of last shmdt() */
-    unsigned long int __glibc_reserved3;
+    unsigned long int __shm_ctime_high;
     __time_t shm_ctime;			/* time of last change by shmctl() */
 #else
     __time_t shm_atime;			/* time of last shmat() */
diff --git a/sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h
new file mode 100644
index 0000000000..333a410641
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h
@@ -0,0 +1,17 @@
+/* Analogous to kernel struct shmid64_ds used on shmctl.  */
+struct kernel_shmid64_ds
+{
+  struct ipc_perm shm_perm;
+  unsigned long int shm_atime_high;
+  unsigned long int shm_atime;
+  unsigned long int shm_dtime_high;
+  unsigned long int shm_dtime;
+  unsigned long int shm_ctime_high;
+  unsigned long int shm_ctime;
+  size_t shm_segsz;
+  __pid_t shm_cpid;
+  __pid_t shm_lpid;
+  unsigned long int shm_nattch;
+  unsigned long int __unused1;
+  unsigned long int __unused2;
+};
diff --git a/sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h
new file mode 100644
index 0000000000..6fe67afccb
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h
@@ -0,0 +1,17 @@
+/* Analogous to kernel struct shmid64_ds used on shmctl.  */
+struct kernel_shmid64_ds
+{
+  struct ipc_perm shm_perm;
+  size_t shm_segsz;
+  unsigned long int shm_atime;
+  unsigned long int shm_atime_high;
+  unsigned long int shm_dtime;
+  unsigned long int shm_dtime_high;
+  unsigned long int shm_ctime;
+  unsigned long int shm_ctime_high;
+  __pid_t shm_cpid;
+  __pid_t shm_lpid;
+  unsigned long int shm_nattch;
+  unsigned long int __unused1;
+  unsigned long int __unused2;
+};
-- 
2.25.1


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

* Re: [PATCH v2] sysv: linux: Add 64-bit time_t variant for shmctl
  2020-07-08 15:32     ` [PATCH v2] " Adhemerval Zanella
@ 2020-07-08 17:02       ` Carlos O'Donell
  2020-07-08 18:01       ` Alistair Francis
  2020-07-10 17:13       ` Joseph Myers
  2 siblings, 0 replies; 41+ messages in thread
From: Carlos O'Donell @ 2020-07-08 17:02 UTC (permalink / raw)
  To: Adhemerval Zanella, libc-alpha

On 7/8/20 11:32 AM, Adhemerval Zanella wrote:
> This is a small updated version that basically does:
> 
>   git mv include/sys/shm.h sysdeps/unix/sysv/linux/include/sys/shm.h
> 
> It basically avoids a build failure on Hurd (since it does not provide
> struct_shmid64_ds.h).

OK for master with all previous commit message and textual changes made.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> ---
> 
> To provide a y2038 safe interface a new symbol __shmctl64 is added
> and __shmctl is change to call it instead (it adds some extra buffer
> coping for the 32 bit time_t implementation).
> 
> Two two new structures are added:
> 
>   1. kernel_shmid64_ds: used internally only on 32-bit architectures
>      to issue the syscall.  A handful of architectures (hppa, i386,
>      mips, powerpc32, and sparc32) require specific implementations
>      due to their kernel ABI.
> 
>   2. shmid_ds64: this is only for __TIMESIZE != 64 to use along with
>      the 64-bit semctl.  It is different than the kernel struct because
>      the exported 64-bit time_t might require different alignment
>      depending on the architecture ABI.
> 
> So the resulting implementation does:
> 
>   1. For 64-bit architectures it assumes shmid_ds already contains
>      64-bit time_t fields and will result in just the __shmctl symbol
>      using the __shmctl64 code.  The shmid_ds argument is passed as-is
>      to the syscall.
> 
>   2. For 32-bit architectures with default 64-bit time_t (newer ABIs
>      such riscv32 or arc), it will also result in only one exported
>      symbol but with the required high/low time handling.
> 
>   3. Finally for 32-bit architecture with both 32-bit and 64-bit time_t
>      support we follow the already set way to provide one symbol with
>      64-bit time_t support and implement the 32-bit time_t support
>      using of the 64-bit one.
> 
>      The default 32-bit symbol will allocate and copy the shmid_ds
>      over multiple buffers, but this should be deprecated in favor
>      of the __shmctl64 anyway.
> 
> Checked on i686-linux-gnu and x86_64-linux-gnu.  I also did some sniff
> tests on powerpc, powerpc64, mips, mips64, armhf, sparcv9, and
> sparc64.
> 
> Tested-by: Carlos O'Donell <carlos@redhat.com>
> Reviewed-by: Carlos O'Donell <carlos@redhat.com>
> ---
>  include/sys/shm.h                             |   1 -
>  .../sysv/linux/bits/types/struct_shmid64_ds.h |  37 ++++
>  .../sysv/linux/bits/types/struct_shmid_ds.h   |   6 +-
>  .../linux/hppa/bits/types/struct_shmid_ds.h   |   6 +-
>  .../linux/hppa/struct_kernel_shmid64_ds.h     |  18 ++
>  .../linux/i386/struct_kernel_shmid64_ds.h     |  17 ++
>  sysdeps/unix/sysv/linux/include/sys/shm.h     |  17 ++
>  .../linux/mips/bits/types/struct_shmid_ds.h   |   6 +-
>  .../linux/mips/struct_kernel_shmid64_ds.h     |  27 +++
>  .../powerpc/bits/types/struct_shmid_ds.h      |   6 +-
>  .../linux/powerpc/struct_kernel_shmid64_ds.h  |  18 ++
>  sysdeps/unix/sysv/linux/shmctl.c              | 180 ++++++++++++++----
>  .../linux/sparc/bits/types/struct_shmid_ds.h  |   6 +-
>  .../linux/sparc/struct_kernel_shmid64_ds.h    |  17 ++
>  .../sysv/linux/struct_kernel_shmid64_ds.h     |  17 ++
>  15 files changed, 329 insertions(+), 50 deletions(-)
>  delete mode 100644 include/sys/shm.h
>  create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/include/sys/shm.h
>  create mode 100644 sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h
> 
> diff --git a/include/sys/shm.h b/include/sys/shm.h
> deleted file mode 100644
> index 1878fcc5be..0000000000
> --- a/include/sys/shm.h
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysvipc/sys/shm.h>
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h
> new file mode 100644
> index 0000000000..f71e0d28ff
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h
> @@ -0,0 +1,37 @@
> +/* Generic implementation of the shared memory struct shmid_ds.
> +   Copyright (C) 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_SHM_H
> +# error "Never include <bits/types/struct_shmid_ds.h> directly; use <sys/shm.h> instead."
> +#endif
> +
> +#if __TIMESIZE == 64
> +# define __shmid64_ds shmid_ds
> +#else
> +struct __shmid64_ds
> +{
> +  struct ipc_perm shm_perm;	/* operation permission struct */
> +  size_t shm_segsz;		/* size of segment in bytes */
> +  __time64_t shm_atime;		/* time of last shmat() */
> +  __time64_t shm_dtime;		/* time of last shmdt() */
> +  __time64_t shm_ctime;		/* time of last change by shmctl() */
> +  __pid_t shm_cpid;		/* pid of creator */
> +  __pid_t shm_lpid;		/* pid of last shmop */
> +  shmatt_t shm_nattch;		/* number of current attaches */
> +};
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
> index 61ed4a08c3..836a7d50e9 100644
> --- a/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
> @@ -27,11 +27,11 @@ struct shmid_ds
>      size_t shm_segsz;			/* size of segment in bytes */
>  #if __TIMESIZE == 32
>      __time_t shm_atime;			/* time of last shmat() */
> -    unsigned long int __glibc_reserved1;
> +    unsigned long int __shm_atime_high;
>      __time_t shm_dtime;			/* time of last shmdt() */
> -    unsigned long int __glibc_reserved2;
> +    unsigned long int __shm_dtime_high;
>      __time_t shm_ctime;			/* time of last change by shmctl() */
> -    unsigned long int __glibc_reserved3;
> +    unsigned long int __shm_ctime_high;
>  #else
>      __time_t shm_atime;			/* time of last shmat() */
>      __time_t shm_dtime;			/* time of last shmdt() */
> diff --git a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
> index 1ebf222eac..1abed1e149 100644
> --- a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
> +++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
> @@ -25,11 +25,11 @@ struct shmid_ds
>    {
>      struct ipc_perm shm_perm;		/* operation permission struct */
>  #if __TIMESIZE == 32
> -    unsigned long int __glibc_reserved1;
> +    unsigned long int __shm_atime_high;
>      __time_t shm_atime;			/* time of last shmat() */
> -    unsigned long int __glibc_reserved2;
> +    unsigned long int __shm_dtime_high;
>      __time_t shm_dtime;			/* time of last shmdt() */
> -    unsigned long int __glibc_reserved3;
> +    unsigned long int __shm_ctime_high;
>      __time_t shm_ctime;			/* time of last change by shmctl() */
>      unsigned long int __glibc_reserved4;
>  #else
> diff --git a/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h
> new file mode 100644
> index 0000000000..4d09fc7f62
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
> +struct kernel_shmid64_ds
> +{
> +  struct ipc_perm shm_perm;		/* operation permission struct */
> +  unsigned long int shm_atime_high;
> +  unsigned long int shm_atime;		/* time of last shmat() */
> +  unsigned long int shm_dtime_high;
> +  unsigned long int shm_dtime;		/* time of last shmdt() */
> +  unsigned long int shm_ctime_high;
> +  unsigned long int shm_ctime;		/* time of last change by shmctl() */
> +  unsigned long int __pad;
> +  size_t shm_segsz;			/* size of segment in bytes */
> +  __pid_t shm_cpid;			/* pid of creator */
> +  __pid_t shm_lpid;			/* pid of last shmop */
> +  shmatt_t shm_nattch;		/* number of current attaches */
> +  unsigned long int __unused1;
> +  unsigned long int __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h
> new file mode 100644
> index 0000000000..6a0a0d9c71
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h
> @@ -0,0 +1,17 @@
> +/* Analogous to kernel struct compat_shmid64_ds used on shmctl.  */
> +struct kernel_shmid64_ds
> +{
> +  struct ipc_perm shm_perm;
> +  size_t shm_segsz;
> +  unsigned long int shm_atime;
> +  unsigned long int shm_atime_high;
> +  unsigned long int shm_dtime;
> +  unsigned long int shm_dtime_high;
> +  unsigned long int shm_ctime;
> +  unsigned long int shm_ctime_high;
> +  __pid_t shm_cpid;
> +  __pid_t shm_lpid;
> +  unsigned long int shm_nattch;
> +  unsigned long int __unused4;
> +  unsigned long int __unused5;
> +};
> diff --git a/sysdeps/unix/sysv/linux/include/sys/shm.h b/sysdeps/unix/sysv/linux/include/sys/shm.h
> new file mode 100644
> index 0000000000..530a1cdfc9
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/include/sys/shm.h
> @@ -0,0 +1,17 @@
> +#ifndef _SYS_SHM_H
> +#include <sysvipc/sys/shm.h>
> +
> +#ifndef _ISOMAC
> +
> +# include <bits/types/struct_shmid64_ds.h>
> +
> +# if __TIMESIZE == 64
> +#  define __shmctl64 __shmctl
> +# else
> +extern int __shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf);
> +libc_hidden_proto (__shmctl64);
> +# endif
> +
> +#endif /* _ISOMAC  */
> +
> +#endif /* _SYS_SHM_H  */
> diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
> index 8e13928980..58090e2fcb 100644
> --- a/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
> +++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
> @@ -38,9 +38,9 @@ struct shmid_ds
>      __pid_t shm_lpid;			/* pid of last shmop */
>      shmatt_t shm_nattch;		/* number of current attaches */
>  #if __TIMESIZE == 32
> -    unsigned short int __glibc_reserved1;
> -    unsigned short int __glibc_reserved2;
> -    unsigned short int __glibc_reserved3;
> +    unsigned short int __shm_atime_high;
> +    unsigned short int __shm_dtime_high;
> +    unsigned short int __shm_ctime_high;
>      unsigned short int __glibc_reserved4;
>  #else
>      __syscall_ulong_t __glibc_reserved5;
> diff --git a/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h
> new file mode 100644
> index 0000000000..a4baa5614f
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h
> @@ -0,0 +1,27 @@
> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
> +struct kernel_shmid64_ds
> +{
> +  struct ipc_perm shm_perm;
> +  size_t shm_segsz;
> +#if __TIMESIZE == 64
> +  long int shm_atime;
> +  long int shm_dtime;
> +  long int shm_ctime;
> +#else
> +  unsigned long int shm_atime;
> +  unsigned long int shm_dtime;
> +  unsigned long int shm_ctime;
> +#endif
> +  __pid_t shm_cpid;
> +  __pid_t shm_lpid;
> +  unsigned long int shm_nattch;
> +#if __TIMESIZE == 64
> +  unsigned long int __unused1;
> +  unsigned long int __unused2;
> +#else
> +  unsigned short int shm_atime_high;
> +  unsigned short int shm_dtime_high;
> +  unsigned short int shm_ctime_high;
> +  unsigned short int __ununsed1;
> +#endif
> +};
> diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
> index b0816fb16a..39b3e5fd3e 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
> +++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
> @@ -25,11 +25,11 @@ struct shmid_ds
>    {
>      struct ipc_perm shm_perm;		/* operation permission struct */
>  #if __TIMESIZE == 32
> -    unsigned long int __glibc_reserved1;
> +    unsigned long int __shm_atime_high;
>      __time_t shm_atime;			/* time of last shmat() */
> -    unsigned long int __glibc_reserved2;
> +    unsigned long int __shm_dtime_high;
>      __time_t shm_dtime;			/* time of last shmdt() */
> -    unsigned long int __glibc_reserved3;
> +    unsigned long int __shm_ctime_high;
>      __time_t shm_ctime;			/* time of last change by shmctl() */
>      unsigned long int __glibc_reserved4;
>  #else
> diff --git a/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
> new file mode 100644
> index 0000000000..ae3f3987ac
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
> +struct kernel_shmid64_ds
> +{
> +  struct ipc_perm shm_perm;
> +  unsigned long int shm_atime_high;
> +  unsigned long int shm_atime;
> +  unsigned long int shm_dtime_high;
> +  unsigned long int shm_dtime;
> +  unsigned long int shm_ctime_high;
> +  unsigned long int shm_ctime;
> +  unsigned long int __ununsed1;
> +  size_t shm_segsz;
> +  __pid_t shm_cpid;
> +  __pid_t shm_lpid;
> +  unsigned long int shm_nattch;
> +  unsigned long int __unused2;
> +  unsigned long int __unused3;
> +};
> diff --git a/sysdeps/unix/sysv/linux/shmctl.c b/sysdeps/unix/sysv/linux/shmctl.c
> index f41b359b8b..aaf3946054 100644
> --- a/sysdeps/unix/sysv/linux/shmctl.c
> +++ b/sysdeps/unix/sysv/linux/shmctl.c
> @@ -24,16 +24,55 @@
>  #include <errno.h>
>  #include <linux/posix_types.h>  /* For __kernel_mode_t.  */
>  
> -#ifndef DEFAULT_VERSION
> -# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -#  define DEFAULT_VERSION GLIBC_2_2
> -# else
> -#  define DEFAULT_VERSION GLIBC_2_31
> -# endif
> +/* POSIX states ipc_perm mode should have type of mode_t.  */
> +_Static_assert (sizeof ((struct shmid_ds){0}.shm_perm.mode)
> +		== sizeof (mode_t),
> +		"sizeof (shmid_ds.shm_perm.mode) != sizeof (mode_t)");
> +
> +#if __IPC_TIME64 == 0
> +typedef struct shmid_ds shmctl_arg_t;
> +#else
> +# include <struct_kernel_shmid64_ds.h>
> +
> +static void
> +shmid64_to_kshmid64 (const struct __shmid64_ds *shmid64,
> +		     struct kernel_shmid64_ds *kshmid)
> +{
> +  kshmid->shm_perm       = shmid64->shm_perm;
> +  kshmid->shm_segsz      = shmid64->shm_segsz;
> +  kshmid->shm_atime      = shmid64->shm_atime;
> +  kshmid->shm_atime_high = shmid64->shm_atime >> 32;
> +  kshmid->shm_dtime      = shmid64->shm_dtime;
> +  kshmid->shm_dtime_high = shmid64->shm_dtime >> 32;
> +  kshmid->shm_ctime      = shmid64->shm_ctime;
> +  kshmid->shm_ctime_high = shmid64->shm_ctime >> 32;
> +  kshmid->shm_cpid       = shmid64->shm_cpid;
> +  kshmid->shm_lpid       = shmid64->shm_lpid;
> +  kshmid->shm_nattch     = shmid64->shm_nattch;
> +}
> +
> +static void
> +kshmid64_to_shmid64 (const struct kernel_shmid64_ds *kshmid,
> +		     struct __shmid64_ds *shmid64)
> +{
> +  shmid64->shm_perm   = kshmid->shm_perm;
> +  shmid64->shm_segsz  = kshmid->shm_segsz;
> +  shmid64->shm_atime  = kshmid->shm_atime
> +		        | ((__time64_t) kshmid->shm_atime_high << 32);
> +  shmid64->shm_dtime  = kshmid->shm_dtime
> +		        | ((__time64_t) kshmid->shm_dtime_high << 32);
> +  shmid64->shm_ctime     = kshmid->shm_ctime
> +		        | ((__time64_t) kshmid->shm_ctime_high << 32);
> +  shmid64->shm_cpid   = kshmid->shm_cpid;
> +  shmid64->shm_lpid   = kshmid->shm_lpid;
> +  shmid64->shm_nattch = kshmid->shm_nattch;
> +}
> +
> +typedef struct kernel_shmid64_ds shmctl_arg_t;
>  #endif
>  
>  static int
> -shmctl_syscall (int shmid, int cmd, struct shmid_ds *buf)
> +shmctl_syscall (int shmid, int cmd, shmctl_arg_t *buf)
>  {
>  #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
>    return INLINE_SYSCALL_CALL (shmctl, shmid, cmd | __IPC_64, buf);
> @@ -45,46 +84,119 @@ shmctl_syscall (int shmid, int cmd, struct shmid_ds *buf)
>  
>  /* Provide operations to control over shared memory segments.  */
>  int
> -__new_shmctl (int shmid, int cmd, struct shmid_ds *buf)
> +__shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf)
>  {
> -  /* POSIX states ipc_perm mode should have type of mode_t.  */
> -  _Static_assert (sizeof ((struct shmid_ds){0}.shm_perm.mode)
> -		  == sizeof (mode_t),
> -		  "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");
> -
> -#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -  struct shmid_ds tmpds;
> -  if (cmd == IPC_SET)
> +#if __IPC_TIME64
> +  struct kernel_shmid64_ds kshmid, *arg = NULL;
> +  if (buf != NULL)
>      {
> -      tmpds = *buf;
> -      tmpds.shm_perm.mode *= 0x10000U;
> -      buf = &tmpds;
> +      shmid64_to_kshmid64 (buf, &kshmid);
> +      arg = &kshmid;
>      }
> +# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> +  if (cmd == IPC_SET)
> +      arg->shm_perm.mode *= 0x10000U;
> +# endif
> +#else
> +  shmctl_arg_t *arg = buf;
>  #endif
>  
> -  int ret = shmctl_syscall (shmid, cmd, buf);
> +  int ret = shmctl_syscall (shmid, cmd, arg);
> +  if (ret < 0)
> +    return ret;
>  
> -  if (ret >= 0)
> +  switch (cmd)
>      {
> -      switch (cmd)
> -	{
> -        case IPC_STAT:
> -        case SHM_STAT:
> -        case SHM_STAT_ANY:
> +      case IPC_STAT:
> +      case SHM_STAT:
> +      case SHM_STAT_ANY:
>  #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -          buf->shm_perm.mode >>= 16;
> +        arg->shm_perm.mode >>= 16;
>  #else
> -	  /* Old Linux kernel versions might not clear the mode padding.  */
> -	  if (sizeof ((struct shmid_ds){0}.shm_perm.mode)
> -	      != sizeof (__kernel_mode_t))
> -	    buf->shm_perm.mode &= 0xFFFF;
> +      /* Old Linux kernel versions might not clear the mode padding.  */
> +      if (sizeof ((struct shmid_ds){0}.shm_perm.mode)
> +	  != sizeof (__kernel_mode_t))
> +	arg->shm_perm.mode &= 0xFFFF;
> +#endif
> +
> +#if __IPC_TIME64
> +      kshmid64_to_shmid64 (arg, buf);
>  #endif
> -	}
>      }
>  
>    return ret;
>  }
> -versioned_symbol (libc, __new_shmctl, shmctl, DEFAULT_VERSION);
> +#if __TIMESIZE != 64
> +libc_hidden_def (__shmctl64)
> +
> +static void
> +shmid_to_shmid64 (struct __shmid64_ds *shm64, const struct shmid_ds *shm)
> +{
> +  shm64->shm_perm   = shm->shm_perm;
> +  shm64->shm_segsz  = shm->shm_segsz;
> +  shm64->shm_atime  = shm->shm_atime
> +		        | ((__time64_t) shm->__shm_atime_high << 32);
> +  shm64->shm_dtime  = shm->shm_dtime
> +		        | ((__time64_t) shm->__shm_dtime_high << 32);
> +  shm64->shm_ctime     = shm->shm_ctime
> +		        | ((__time64_t) shm->__shm_ctime_high << 32);
> +  shm64->shm_cpid   = shm->shm_cpid;
> +  shm64->shm_lpid   = shm->shm_lpid;
> +  shm64->shm_nattch = shm->shm_nattch;
> +}
> +
> +static void
> +shmid64_to_shmid (struct shmid_ds *shm, const struct __shmid64_ds *shm64)
> +{
> +  shm->shm_perm         = shm64->shm_perm;
> +  shm->shm_segsz        = shm64->shm_segsz;
> +  shm->shm_atime        = shm64->shm_atime;
> +  shm->__shm_atime_high = 0;
> +  shm->shm_dtime        = shm64->shm_dtime;
> +  shm->__shm_dtime_high = 0;
> +  shm->shm_ctime        = shm64->shm_ctime;
> +  shm->__shm_ctime_high = 0;
> +  shm->shm_cpid         = shm64->shm_cpid;
> +  shm->shm_lpid         = shm64->shm_lpid;
> +  shm->shm_nattch       = shm64->shm_nattch;
> +}
> +
> +int
> +__shmctl (int shmid, int cmd, struct shmid_ds *buf)
> +{
> +  struct __shmid64_ds shmid64, *buf64 = NULL;
> +  if (buf != NULL)
> +    {
> +      shmid_to_shmid64 (&shmid64, buf);
> +      buf64 = &shmid64;
> +    }
> +
> +  int ret = __shmctl64 (shmid, cmd, buf64);
> +  if (ret < 0)
> +    return ret;
> +
> +  switch (cmd)
> +    {
> +      case IPC_STAT:
> +      case SHM_STAT:
> +      case SHM_STAT_ANY:
> +	if (buf64 != NULL)
> +	  shmid64_to_shmid (buf, buf64);
> +    }
> +
> +  return ret;
> +}
> +#endif
> +
> +#ifndef DEFAULT_VERSION
> +# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
> +#  define DEFAULT_VERSION GLIBC_2_2
> +# else
> +#  define DEFAULT_VERSION GLIBC_2_31
> +# endif
> +#endif
> +
> +versioned_symbol (libc, __shmctl, shmctl, DEFAULT_VERSION);
>  
>  #if defined __ASSUME_SYSVIPC_BROKEN_MODE_T \
>      && SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_31)
> @@ -92,7 +204,7 @@ int
>  attribute_compat_text_section
>  __shmctl_mode16 (int shmid, int cmd, struct shmid_ds *buf)
>  {
> -  return shmctl_syscall (shmid, cmd, buf);
> +  return shmctl_syscall (shmid, cmd, (shmctl_arg_t *) buf);
>  }
>  compat_symbol (libc, __shmctl_mode16, shmctl, GLIBC_2_2);
>  #endif
> diff --git a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h
> index d5fb61d374..cab3a2686f 100644
> --- a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h
> +++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h
> @@ -25,11 +25,11 @@ struct shmid_ds
>    {
>      struct ipc_perm shm_perm;		/* operation permission struct */
>  #if __TIMESIZE == 32
> -    unsigned long int __glibc_reserved1;
> +    unsigned long int __shm_atime_high;
>      __time_t shm_atime;			/* time of last shmat() */
> -    unsigned long int __glibc_reserved2;
> +    unsigned long int __shm_dtime_high;
>      __time_t shm_dtime;			/* time of last shmdt() */
> -    unsigned long int __glibc_reserved3;
> +    unsigned long int __shm_ctime_high;
>      __time_t shm_ctime;			/* time of last change by shmctl() */
>  #else
>      __time_t shm_atime;			/* time of last shmat() */
> diff --git a/sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h
> new file mode 100644
> index 0000000000..333a410641
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h
> @@ -0,0 +1,17 @@
> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
> +struct kernel_shmid64_ds
> +{
> +  struct ipc_perm shm_perm;
> +  unsigned long int shm_atime_high;
> +  unsigned long int shm_atime;
> +  unsigned long int shm_dtime_high;
> +  unsigned long int shm_dtime;
> +  unsigned long int shm_ctime_high;
> +  unsigned long int shm_ctime;
> +  size_t shm_segsz;
> +  __pid_t shm_cpid;
> +  __pid_t shm_lpid;
> +  unsigned long int shm_nattch;
> +  unsigned long int __unused1;
> +  unsigned long int __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h
> new file mode 100644
> index 0000000000..6fe67afccb
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h
> @@ -0,0 +1,17 @@
> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
> +struct kernel_shmid64_ds
> +{
> +  struct ipc_perm shm_perm;
> +  size_t shm_segsz;
> +  unsigned long int shm_atime;
> +  unsigned long int shm_atime_high;
> +  unsigned long int shm_dtime;
> +  unsigned long int shm_dtime_high;
> +  unsigned long int shm_ctime;
> +  unsigned long int shm_ctime_high;
> +  __pid_t shm_cpid;
> +  __pid_t shm_lpid;
> +  unsigned long int shm_nattch;
> +  unsigned long int __unused1;
> +  unsigned long int __unused2;
> +};
> 


-- 
Cheers,
Carlos.


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

* Re: [PATCH v2] sysv: linux: Add 64-bit time_t variant for semctl
  2020-07-08 15:32     ` [PATCH v2] " Adhemerval Zanella
@ 2020-07-08 17:04       ` Carlos O'Donell
  0 siblings, 0 replies; 41+ messages in thread
From: Carlos O'Donell @ 2020-07-08 17:04 UTC (permalink / raw)
  To: Adhemerval Zanella, libc-alpha; +Cc: Alistair Francis, Vineet Gupta

On 7/8/20 11:32 AM, Adhemerval Zanella wrote:
> This is a small updated version that basically does:
> 
>   git mv include/sys/sem.h sysdeps/unix/sysv/linux/include/sys/sem.h
> 
> And it moves the Linux specific requirements (since Hurd uses the
> generic semop definition that does not call semtimedop).

OK for 2.32.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
 
> --
> 
> Different than others 64-bit time_t syscalls, the SysIPC interface
> does not provide a new set of syscall for y2038 safeness.  Instead it
> uses unused fields in semid_ds structure to return the high bits for
> the timestamps.
> 
> To provide a y2038 safe interface a new symbol __semctl64 is added
> and __semctl is change to call it instead (it adds some extra buffer
> copy for the 32 bit time_t implementation).
> 
> Two new structures are added:
> 
>   1. kernel_semid64_ds: used internally only on 32-bit architectures
>      to issue the syscall.  A handful of architectures (hppa, i386,
>      mips, powerpc32, sparc32) require specific implementations due
>      their kernel ABI.
> 
>   2. semid_ds64: this is only for __TIMESIZE != 64 to use along with
>      the 64-bit semctl.  It is different than the kernel struct because
>      the exported 64-bit time_t might require different alignment
>      depending of the architecture ABI.
> 
> So the resulting implementation does:
> 
>   1. For 64-bit architectures it assumes semid_ds already contains
>      64-bit time_t fields and will result in just the __semctl symbol
>      using the __semctl64 code.  The semid_ds argument is passed as-is
>      to the syscall.
> 
>   2. For 32-bit architectures with default 64-bit time_t (newer ABIs
>      such riscv32 or arc), it will also result in only one exported
>      symbol but with the required high/low handling.
> 
>      It might be possible to optimize it further to avoid the
>      kernel_semid64_ds to semun transformation if the exported ABI
>      for the architectures matches the expected kernel ABI, but the
>      implementation is already complex enough and don't think this
>      should be a hotspot in any case.
> 
>   3. Finally for 32-bit architecture with both 32-bit and 64-bit time_t
>      support we follow the already set way to provide one symbol with
>      64-bit time_t support and implement the 32-bit time_t support
>      using the 64-bit one.
> 
>      The default 32-bit symbol will allocate and copy the semid_ds
>      over multiple buffers, but this should be deprecated in favor
>      of the __semctl64 anyway.
> 
> Checked on i686-linux-gnu and x86_64-linux-gnu.  I also did some sniff
> tests on powerpc, powerpc64, mips, mips64, armhf, sparcv9, and
> sparc64.
> 
> Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
> Tested-by: Vineet Gupta <vgupta@synopsys.com>
> Reviewed-by: Carlos O'Donell <carlos@redhat.com>
> Tested-by: Carlos O'Donell <carlos@redhat.com>
> ---
>  include/sys/sem.h                             |   9 -
>  .../sysv/linux/bits/types/struct_semid64_ds.h |  33 +++
>  .../sysv/linux/bits/types/struct_semid_ds.h   |  21 +-
>  .../linux/hppa/bits/types/struct_semid_ds.h   |   6 +-
>  .../linux/hppa/struct_kernel_semid64_ds.h     |  12 +
>  .../linux/i386/struct_kernel_semid64_ds.h     |  12 +
>  sysdeps/unix/sysv/linux/include/sys/sem.h     |  16 ++
>  sysdeps/unix/sysv/linux/ipc_priv.h            |  10 +
>  .../linux/mips/bits/types/struct_semid_ds.h   |   4 +-
>  .../linux/mips/struct_kernel_semid64_ds.h     |  10 +
>  .../powerpc/bits/types/struct_semid_ds.h      |   4 +-
>  .../powerpc32/struct_kernel_semid64_ds.h      |  12 +
>  sysdeps/unix/sysv/linux/semctl.c              | 261 +++++++++++++++---
>  .../linux/sparc/bits/types/struct_semid_ds.h  |   4 +-
>  .../sparc/sparc32/struct_kernel_semid64_ds.h  |  12 +
>  .../sysv/linux/struct_kernel_semid64_ds.h     |  12 +
>  .../linux/x86/bits/types/struct_semid_ds.h    |   4 +-
>  17 files changed, 368 insertions(+), 74 deletions(-)
>  delete mode 100644 include/sys/sem.h
>  create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_semid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/hppa/struct_kernel_semid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/i386/struct_kernel_semid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/include/sys/sem.h
>  create mode 100644 sysdeps/unix/sysv/linux/mips/struct_kernel_semid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_semid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_semid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/struct_kernel_semid64_ds.h
> 
> diff --git a/include/sys/sem.h b/include/sys/sem.h
> deleted file mode 100644
> index 69fdf1f752..0000000000
> --- a/include/sys/sem.h
> +++ /dev/null
> @@ -1,9 +0,0 @@
> -#ifndef _SYS_SEM_H
> -# include <sysvipc/sys/sem.h>
> -
> -# ifndef _ISOMAC
> -
> -__typeof__ (semtimedop) __semtimedop attribute_hidden;
> -
> -# endif
> -#endif
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_semid64_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_semid64_ds.h
> new file mode 100644
> index 0000000000..bda9eb4469
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_semid64_ds.h
> @@ -0,0 +1,33 @@
> +/* Generic implementation of the semaphore struct semid64_ds.
> +   Copyright (C) 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 __TIMESIZE == 64
> +# define __semid64_ds semid_ds
> +#else
> +struct __semid64_ds
> +{
> +  struct ipc_perm sem_perm;		/* operation permission struct */
> +  __time64_t sem_otime;			/* last semop() time */
> +  __time64_t sem_ctime;			/* last time changed by semctl() */
> +  __syscall_ulong_t sem_nsems;		/* number of semaphores in set */
> +};
> +#endif
> 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 4222e6a59f..bc26d8be08 100644
> --- a/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h
> @@ -21,26 +21,19 @@
>  #endif
>  
>  /* Data structure describing a set of semaphores.  */
> -#if __TIMESIZE == 32
>  struct semid_ds
>  {
>    struct ipc_perm sem_perm;        /* operation permission struct */
> +#if __TIMESIZE == 32
>    __time_t sem_otime;              /* last semop() time */
> -  __syscall_ulong_t __glibc_reserved1;
> +  __syscall_ulong_t __sem_otime_high;
>    __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;
> -};
> +  __syscall_ulong_t __sem_ctime_high;
>  #else
> -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 */
> +  __time_t sem_otime;
> +  __time_t sem_ctime;
> +#endif
> +  __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/hppa/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_semid_ds.h
> index d4c50b5ef8..68f9eca24c 100644
> --- a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_semid_ds.h
> +++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_semid_ds.h
> @@ -21,16 +21,14 @@
>  #endif
>  
>  /* 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;
> +  __syscall_ulong_t __sem_otime_high;
>    __time_t sem_otime;         /* last semop() time */
> -  __syscall_ulong_t __glibc_reserved2;
> +  __syscall_ulong_t __sem_ctime_high;
>    __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/hppa/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/hppa/struct_kernel_semid64_ds.h
> new file mode 100644
> index 0000000000..2871030d0d
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/hppa/struct_kernel_semid64_ds.h
> @@ -0,0 +1,12 @@
> +/* Analogous to kernel struct semid64_ds used on semctl.  */
> +struct kernel_semid64_ds
> +{
> +  struct ipc_perm sem_perm;
> +  unsigned long sem_otime_high;
> +  unsigned long sem_otime;
> +  unsigned long sem_ctime_high;
> +  unsigned long sem_ctime;
> +  unsigned long sem_nsems;
> +  unsigned long __ununsed1;
> +  unsigned long __ununsed2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/i386/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/i386/struct_kernel_semid64_ds.h
> new file mode 100644
> index 0000000000..bab9cf63ba
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/i386/struct_kernel_semid64_ds.h
> @@ -0,0 +1,12 @@
> +/* Analogous to kernel struct semid64_ds used on semctl.  */
> +struct kernel_semid64_ds
> +{
> +  struct ipc_perm sem_perm;
> +  unsigned long sem_otime;
> +  unsigned long sem_otime_high;
> +  unsigned long sem_ctime;
> +  unsigned long sem_ctime_high;
> +  __syscall_ulong_t sem_nsems;
> +  __syscall_ulong_t __unused3;
> +  __syscall_ulong_t __unused4;
> +};
> diff --git a/sysdeps/unix/sysv/linux/include/sys/sem.h b/sysdeps/unix/sysv/linux/include/sys/sem.h
> new file mode 100644
> index 0000000000..a9151e057d
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/include/sys/sem.h
> @@ -0,0 +1,16 @@
> +#ifndef _SYS_SEM_H
> +# include <sysvipc/sys/sem.h>
> +
> +# ifndef _ISOMAC
> +
> +__typeof__ (semtimedop) __semtimedop attribute_hidden;
> +
> +#if __TIMESIZE == 64
> +# define __semctl64 __semctl
> +#else
> +extern int __semctl64 (int semid, int semnum, int cmd, ...);
> +libc_hidden_proto (__semctl64);
> +#endif
> +
> +# endif
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/ipc_priv.h b/sysdeps/unix/sysv/linux/ipc_priv.h
> index 15a6e683a4..0bd6105e7b 100644
> --- a/sysdeps/unix/sysv/linux/ipc_priv.h
> +++ b/sysdeps/unix/sysv/linux/ipc_priv.h
> @@ -53,4 +53,14 @@ struct __old_ipc_perm
>  #define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
>    (__nsops), 0, (__sops), (__timeout)
>  
> +/* Linux SysV ipc does not provide new syscalls for 64-bit time support on
> +   32-bit architectures, but rather split the timestamp into high and low;
> +   storing the high value in previously unused fields.  */
> +#if (__WORDSIZE == 32 \
> +     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
> +# define __IPC_TIME64 1
> +#else
> +# define __IPC_TIME64 0
> +#endif
> +
>  #include <ipc_ops.h>
> diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h
> index 8954209a29..eec4a18cae 100644
> --- a/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h
> +++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h
> @@ -27,6 +27,6 @@ struct semid_ds
>    __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;
> +  __syscall_ulong_t __sem_otime_high;
> +  __syscall_ulong_t __sem_ctime_high;
>  };
> diff --git a/sysdeps/unix/sysv/linux/mips/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/mips/struct_kernel_semid64_ds.h
> new file mode 100644
> index 0000000000..76a9d83ea5
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/struct_kernel_semid64_ds.h
> @@ -0,0 +1,10 @@
> +/* Analogous to kernel struct semid64_ds used on semctl.  */
> +struct kernel_semid64_ds
> +{
> +  struct ipc_perm sem_perm;
> +  unsigned long sem_otime;
> +  unsigned long sem_ctime;
> +  unsigned long sem_nsems;
> +  unsigned long sem_otime_high;
> +  unsigned long sem_ctime_high;
> +};
> 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
> index 300a9b98e9..d382d93c52 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_semid_ds.h
> +++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_semid_ds.h
> @@ -25,9 +25,9 @@ struct semid_ds
>  {
>    struct ipc_perm sem_perm;   /* operation permission struct */
>  #if __TIMESIZE == 32
> -  __syscall_ulong_t __glibc_reserved1;
> +  __syscall_ulong_t __sem_otime_high;
>    __time_t sem_otime;         /* last semop() time */
> -  __syscall_ulong_t __glibc_reserved2;
> +  __syscall_ulong_t __sem_ctime_high;
>    __time_t sem_ctime;        /* last time changed by semctl() */
>  #else
>    __time_t sem_otime;         /* last semop() time */
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_semid64_ds.h
> new file mode 100644
> index 0000000000..7fa4ef6424
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_semid64_ds.h
> @@ -0,0 +1,12 @@
> +/* Analogous to kernel struct semid64_ds used on semctl.  */
> +struct kernel_semid64_ds
> +{
> +  struct ipc_perm sem_perm;
> +  unsigned long sem_otime_high;
> +  unsigned long sem_otime;
> +  unsigned long sem_ctime_high;
> +  unsigned long sem_ctime;
> +  unsigned long sem_nsems;
> +  unsigned long __unused3;
> +  unsigned long __unused4;
> +};
> diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c
> index 30571af49f..90460e6310 100644
> --- a/sysdeps/unix/sysv/linux/semctl.c
> +++ b/sysdeps/unix/sysv/linux/semctl.c
> @@ -21,10 +21,13 @@
>  #include <ipc_priv.h>
>  #include <sysdep.h>
>  #include <shlib-compat.h>
> -#include <errno.h>
> -#include <linux/posix_types.h>  /* For __kernel_mode_t.  */
> +#include <bits/types/struct_semid64_ds.h>  /* For __semid64_ds.  */
> +#include <linux/posix_types.h>             /* For __kernel_mode_t.  */
>  
> -/* Define a `union semun' suitable for Linux here.  */
> +/* The struct used to issue the syscall.  For architectures that assume
> +   64-bit time as default (!__ASSUME_TIME64_SYSCALLS) the syscall will
> +   split the resulting 64-bit sem_{o,c}time in two fields (sem_{o,c}time
> +   and __sem_{o,c}time_high).  */
>  union semun
>  {
>    int val;			/* value for SETVAL */
> @@ -33,16 +36,89 @@ union semun
>    struct seminfo *__buf;	/* buffer for IPC_INFO */
>  };
>  
> -#ifndef DEFAULT_VERSION
> -# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -#  define DEFAULT_VERSION GLIBC_2_2
> +#if __IPC_TIME64 == 0
> +# define semun64 semun
> +typedef union semun semctl_arg_t;
> +#else
> +# include <struct_kernel_semid64_ds.h>
> +
> +union ksemun64
> +{
> +  int val;
> +  struct kernel_semid64_ds *buf;
> +  unsigned short int *array;
> +  struct seminfo *__buf;
> +};
> +
> +# if __TIMESIZE == 64
> +#  define semun64 semun
>  # else
> -#  define DEFAULT_VERSION GLIBC_2_31
> +/* The struct used when __semctl64 is called.  */
> +union semun64
> +{
> +  int val;
> +  struct __semid64_ds *buf;
> +  unsigned short int *array;
> +  struct seminfo *__buf;
> +};
>  # endif
> +
> +static void
> +semid64_to_ksemid64 (const struct __semid64_ds *semid64,
> +		     struct kernel_semid64_ds *ksemid)
> +{
> +  ksemid->sem_perm       = semid64->sem_perm;
> +  ksemid->sem_otime      = semid64->sem_otime;
> +  ksemid->sem_otime_high = semid64->sem_otime >> 32;
> +  ksemid->sem_ctime      = semid64->sem_ctime;
> +  ksemid->sem_ctime_high = semid64->sem_ctime >> 32;
> +  ksemid->sem_nsems      = semid64->sem_nsems;
> +}
> +
> +static void
> +ksemid64_to_semid64 (const struct kernel_semid64_ds *ksemid,
> +		     struct __semid64_ds *semid64)
> +{
> +  semid64->sem_perm  = ksemid->sem_perm;
> +  semid64->sem_otime = ksemid->sem_otime
> +		       | ((__time64_t) ksemid->sem_otime_high << 32);
> +  semid64->sem_ctime = ksemid->sem_ctime
> +		       | ((__time64_t) ksemid->sem_ctime_high << 32);
> +  semid64->sem_nsems = ksemid->sem_nsems;
> +}
> +
> +static union ksemun64
> +semun64_to_ksemun64 (int cmd, union semun64 semun64,
> +		     struct kernel_semid64_ds *buf)
> +{
> +  union ksemun64 r = { 0 };
> +  switch (cmd)
> +    {
> +    case SETVAL:
> +      r.val = semun64.val;
> +      break;
> +    case GETALL:
> +    case SETALL:
> +      r.array = semun64.array;
> +      break;
> +    case IPC_STAT:
> +    case IPC_SET:
> +      r.buf = buf;
> +      semid64_to_ksemid64 (semun64.buf, r.buf);
> +      break;
> +    case IPC_INFO:
> +    case SEM_INFO:
> +      r.__buf = semun64.__buf;
> +      break;
> +    }
> +  return r;
> +}
> +
> +typedef union ksemun64 semctl_arg_t;
>  #endif
>  
>  static int
> -semctl_syscall (int semid, int semnum, int cmd, union semun arg)
> +semctl_syscall (int semid, int semnum, int cmd, semctl_arg_t arg)
>  {
>  #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
>    return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64,
> @@ -53,15 +129,15 @@ semctl_syscall (int semid, int semnum, int cmd, union semun arg)
>  #endif
>  }
>  
> +/* 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)");
> +
>  int
> -__new_semctl (int semid, int semnum, int cmd, ...)
> +__semctl64 (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 };
> +  union semun64 arg64 = { 0 };
>    va_list ap;
>  
>    /* Get the argument only if required.  */
> @@ -76,44 +152,151 @@ __new_semctl (int semid, int semnum, int cmd, ...)
>      case IPC_INFO:      /* arg.__buf */
>      case SEM_INFO:
>        va_start (ap, cmd);
> -      arg = va_arg (ap, union semun);
> +      arg64 = va_arg (ap, union semun64);
>        va_end (ap);
>        break;
>      }
>  
> -#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;
> -    }
> +#if __IPC_TIME64
> +  struct kernel_semid64_ds ksemid;
> +  union ksemun64 ksemun = semun64_to_ksemun64 (cmd, arg64, &ksemid);
> +  union ksemun64 arg = ksemun;
> +#else
> +  union semun arg = arg64;
>  #endif
>  
>    int ret = semctl_syscall (semid, semnum, cmd, arg);
> +  if (ret < 0)
> +    return ret;
>  
> -  if (ret >= 0)
> +  switch (cmd)
>      {
> -      switch (cmd)
> -	{
> -        case IPC_STAT:
> -        case SEM_STAT:
> -        case SEM_STAT_ANY:
> +    case IPC_STAT:
> +    case SEM_STAT:
> +    case SEM_STAT_ANY:
>  #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -          arg.buf->sem_perm.mode >>= 16;
> +      arg.buf->sem_perm.mode >>= 16;
>  #else
> -	  /* Old Linux kernel versions might not clear the mode padding.  */
> -	  if (sizeof ((struct semid_ds){0}.sem_perm.mode)
> -	      != sizeof (__kernel_mode_t))
> -	    arg.buf->sem_perm.mode &= 0xFFFF;
> +      /* Old Linux kernel versions might not clear the mode padding.  */
> +      if (sizeof ((struct semid_ds){0}.sem_perm.mode)
> +	  != sizeof (__kernel_mode_t))
> +	arg.buf->sem_perm.mode &= 0xFFFF;
>  #endif
> -	}
> +
> +#if __IPC_TIME64
> +      ksemid64_to_semid64 (arg.buf, arg64.buf);
> +#endif
> +    }
> +
> +  return ret;
> +}
> +#if __TIMESIZE != 64
> +libc_hidden_def (__semctl64)
> +
> +
> +/* The 64-bit time_t semid_ds version might have a different layout and
> +   internal field alignment.  */
> +static void
> +semid64_ds_to_semid_ds (struct semid_ds *ds, const struct __semid64_ds *ds64)
> +{
> +  ds->sem_perm = ds64->sem_perm;
> +  ds->sem_otime = ds64->sem_otime;
> +  ds->sem_ctime = ds64->sem_ctime;
> +  ds->sem_nsems = ds64->sem_nsems;
> +}
> +
> +static void
> +semid_ds_to_semid64_ds (struct __semid64_ds *ds64, const struct semid_ds *ds)
> +{
> +  ds64->sem_perm = ds->sem_perm;
> +  ds64->sem_otime = ds->sem_otime
> +		    | ((__time64_t) ds->__sem_otime_high << 32);
> +  ds64->sem_ctime = ds->sem_ctime
> +		    | ((__time64_t) ds->__sem_ctime_high << 32);
> +  ds64->sem_nsems = ds->sem_nsems;
> +}
> +
> +static union semun64
> +semun_to_semun64 (int cmd, union semun semun, struct __semid64_ds *semid64)
> +{
> +  union semun64 r = { 0 };
> +  switch (cmd)
> +    {
> +    case SETVAL:
> +      r.val = semun.val;
> +      break;
> +    case GETALL:
> +    case SETALL:
> +      r.array = semun.array;
> +      break;
> +    case IPC_STAT:
> +    case IPC_SET:
> +      r.buf = semid64;
> +      semid_ds_to_semid64_ds (r.buf, semun.buf);
> +# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> +      if (cmd == IPC_SET)
> +	r.buf->sem_perm.mode *= 0x10000U;
> +# endif
> +      break;
> +    case IPC_INFO:
> +    case SEM_INFO:
> +      r.__buf = semun.__buf;
> +      break;
> +    }
> +  return r;
> +}
> +
> +int
> +__semctl (int semid, int semnum, int cmd, ...)
> +{
> +  union semun arg = { 0 };
> +
> +  va_list ap;
> +
> +  /* Get the argument only if required.  */
> +  switch (cmd)
> +    {
> +    case SETVAL:        /* arg.val */
> +    case GETALL:        /* arg.array */
> +    case SETALL:
> +    case IPC_STAT:      /* arg.buf */
> +    case IPC_SET:
> +    case SEM_STAT:
> +    case IPC_INFO:      /* arg.__buf */
> +    case SEM_INFO:
> +      va_start (ap, cmd);
> +      arg = va_arg (ap, union semun);
> +      va_end (ap);
> +      break;
> +    }
> +
> +  struct __semid64_ds semid64;
> +  union semun64 arg64 = semun_to_semun64 (cmd, arg, &semid64);
> +
> +  int ret = __semctl64 (semid, semnum, cmd, arg64);
> +  if (ret < 0)
> +    return ret;
> +
> +  switch (cmd)
> +    {
> +    case IPC_STAT:
> +    case SEM_STAT:
> +    case SEM_STAT_ANY:
> +      semid64_ds_to_semid_ds (arg.buf, arg64.buf);
>      }
>  
>    return ret;
>  }
> -versioned_symbol (libc, __new_semctl, semctl, DEFAULT_VERSION);
> +#endif
> +
> +#ifndef DEFAULT_VERSION
> +# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
> +#  define DEFAULT_VERSION GLIBC_2_2
> +# else
> +#  define DEFAULT_VERSION GLIBC_2_31
> +# endif
> +#endif
> +versioned_symbol (libc, __semctl, semctl, DEFAULT_VERSION);
>  
>  #if defined __ASSUME_SYSVIPC_BROKEN_MODE_T \
>      && SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_31)
> @@ -121,7 +304,7 @@ int
>  attribute_compat_text_section
>  __semctl_mode16 (int semid, int semnum, int cmd, ...)
>  {
> -  union semun arg = { 0 };
> +  semctl_arg_t arg = { 0 };
>    va_list ap;
>  
>    /* Get the argument only if required.  */
> @@ -136,7 +319,7 @@ __semctl_mode16 (int semid, int semnum, int cmd, ...)
>      case IPC_INFO:      /* arg.__buf */
>      case SEM_INFO:
>        va_start (ap, cmd);
> -      arg = va_arg (ap, union semun);
> +      arg = va_arg (ap, semctl_arg_t);
>        va_end (ap);
>        break;
>      }
> 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
> index 46fcd79fb6..0110c1a940 100644
> --- a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_semid_ds.h
> +++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_semid_ds.h
> @@ -25,9 +25,9 @@ struct semid_ds
>  {
>    struct ipc_perm sem_perm;   /* operation permission struct */
>  #if __TIMESIZE == 32
> -  __syscall_ulong_t __glibc_reserved1;
> +  __syscall_ulong_t __sem_otime_high;
>    __time_t sem_otime;         /* last semop() time */
> -  __syscall_ulong_t __glibc_reserved2;
> +  __syscall_ulong_t __sem_ctime_high;
>    __time_t sem_ctime;        /* last time changed by semctl() */
>  #else
>    __time_t sem_otime;         /* last semop() time */
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_semid64_ds.h
> new file mode 100644
> index 0000000000..8c4697f9ab
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_semid64_ds.h
> @@ -0,0 +1,12 @@
> +/* Analogous to kernel struct semid64_ds used on semctl.  */
> +struct kernel_semid64_ds
> +{
> +  struct ipc_perm sem_perm;
> +  unsigned long sem_otime_high;
> +  unsigned long sem_otime;
> +  unsigned long sem_ctime_high;
> +  unsigned long sem_ctime;
> +  unsigned long sem_nsems;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/struct_kernel_semid64_ds.h b/sysdeps/unix/sysv/linux/struct_kernel_semid64_ds.h
> new file mode 100644
> index 0000000000..f9edf0f76f
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/struct_kernel_semid64_ds.h
> @@ -0,0 +1,12 @@
> +/* Analogous to kernel struct semid64_ds used on semctl.  */
> +struct kernel_semid64_ds
> +{
> +  struct ipc_perm sem_perm;
> +  unsigned long sem_otime;
> +  unsigned long sem_otime_high;
> +  unsigned long sem_ctime;
> +  unsigned long sem_ctime_high;
> +  unsigned long sem_nsems;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h
> index f7ec89d115..c3f2fde9fd 100644
> --- a/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h
> +++ b/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h
> @@ -25,9 +25,9 @@ struct semid_ds
>  {
>    struct ipc_perm sem_perm;   /* operation permission struct */
>    __time_t sem_otime;  /* last semop() time */
> -  __syscall_ulong_t __glibc_reserved1;
> +  __syscall_ulong_t __sem_otime_high;
>    __time_t sem_ctime;  /* last time changed by semctl() */
> -  __syscall_ulong_t __glibc_reserved2;
> +  __syscall_ulong_t __sem_ctime_high;
>    __syscall_ulong_t sem_nsems;    /* number of semaphores in set */
>    __syscall_ulong_t __glibc_reserved3;
>    __syscall_ulong_t __glibc_reserved4;
> 


-- 
Cheers,
Carlos.


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

* Re: [PATCH v2] sysv: linux: Add 64-bit time_t variant for msgctl
  2020-07-08 15:32     ` [PATCH v2] " Adhemerval Zanella
@ 2020-07-08 17:04       ` Carlos O'Donell
  2020-07-08 17:56       ` Alistair Francis
  1 sibling, 0 replies; 41+ messages in thread
From: Carlos O'Donell @ 2020-07-08 17:04 UTC (permalink / raw)
  To: Adhemerval Zanella, libc-alpha

On 7/8/20 11:32 AM, Adhemerval Zanella wrote:
> This is a small updated version that basically does:
> 
>   git mv include/sys/msg.h sysdeps/unix/sysv/linux/include/sys/msg.h
> 
> It moves the sysvipc to be Linux specific, since the generic version
> does implement _libc_msgsnd or __libc_msgrcv; and avoid a build failure
> on Hurd (since it does not provide struct_msqid64_ds.h).

OK for 2.32.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
 
> ---
> 
> To provide a y2038 safe interface a new symbol __msgctl64 is added
> and __msgctl is change to call it instead (it adds some extra buffer
> coping for the 32 bit time_t implementation).
> 
> Two new structures are added:
> 
>   1. kernel_msqid64_ds: used internally only on 32-bit architectures
>      to issue the syscall.  A handful of architectures (hppa, i386, mips,
>      powerpc32, and sparc32) require specific implementations due to
>      their kernel ABI.
> 
>   2. msqid_ds64: this is only for __TIMESIZE != 64 to use along with
>      the 64-bit semctl.  It is different than the kernel struct because
>      the exported 64-bit time_t might require different alignment
>      depending on the architecture ABI.
> 
> So the resulting implementation does:
> 
>   1. For 64-bit architectures it assumes msqid_ds already contains
>      64-bit time_t fields and will result in just the __msgctl symbol
>      using the __msgctl64 code.  The msgid_ds argument is passed as-is
>      to the syscall.
> 
>   2. For 32-bit architectures with default 64-bit time_t (newer ABIs
>      such riscv32 or arc), it will also result in only one exported
>      symbol but with the required high/low time handling.
> 
>   3. Finally for 32-bit architecture with both 32-bit and 64-bit time_t
>      support we follow the already set way to provide one symbol with
>      64-bit time_t support and implement the 32-bit time_t support using
>      the 64-bit time_t.
> 
>      The default 32-bit symbol will allocate and copy the msqid_ds
>      over multiple buffers, but this should be deprecated in favor
>      of the __msgctl64 anyway.
> 
> Checked on i686-linux-gnu and x86_64-linux-gnu.  I also did some sniff
> tests on powerpc, powerpc64, mips, mips64, armhf, sparcv9, and
> sparc64.
> 
> Tested-by: Carlos O'Donell <carlos@redhat.com>
> Reviewed-by: Carlos O'Donell <carlos@redhat.com>
> ---
>  .../sysv/linux/bits/types/struct_msqid64_ds.h |  38 ++++
>  .../sysv/linux/bits/types/struct_msqid_ds.h   |   6 +-
>  .../linux/hppa/bits/types/struct_msqid_ds.h   |   6 +-
>  .../linux/hppa/struct_kernel_msqid64_ds.h     |  18 ++
>  .../linux/i386/struct_kernel_msqid64_ds.h     |  18 ++
>  .../unix/sysv/linux/include}/sys/msg.h        |  10 +
>  .../linux/mips/bits/types/struct_msqid_ds.h   |  12 +-
>  .../linux/mips/struct_kernel_msqid64_ds.h     |  33 ++++
>  sysdeps/unix/sysv/linux/msgctl.c              | 179 ++++++++++++++----
>  .../powerpc/bits/types/struct_msqid_ds.h      |   6 +-
>  .../powerpc32/struct_kernel_msqid64_ds.h      |  18 ++
>  sysdeps/unix/sysv/linux/semctl.c              |  27 +--
>  .../linux/sparc/bits/types/struct_msqid_ds.h  |   6 +-
>  .../sparc/sparc32/struct_kernel_msqid64_ds.h  |  18 ++
>  .../sysv/linux/struct_kernel_msqid64_ds.h     |  19 ++
>  15 files changed, 350 insertions(+), 64 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h
>  rename {include => sysdeps/unix/sysv/linux/include}/sys/msg.h (55%)
>  create mode 100644 sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h
> 
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h
> new file mode 100644
> index 0000000000..3536c8ea62
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h
> @@ -0,0 +1,38 @@
> +/* Generic implementation of the SysV message struct msqid64_ds.
> +   Copyright (C) 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_MSG_H
> +# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
> +#endif
> +
> +#if __TIMESIZE == 64
> +# define __msqid64_ds msqid_ds
> +#else
> +struct __msqid64_ds
> +{
> +  struct ipc_perm msg_perm;	/* structure describing operation permission */
> +  __time64_t msg_stime;		/* time of last msgsnd command */
> +  __time64_t msg_rtime;		/* time of last msgsnd command */
> +  __time64_t msg_ctime;		/* time of last change */
> +  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
> +  msgqnum_t msg_qnum;		/* number of messages currently on queue */
> +  msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
> +  __pid_t msg_lspid;		/* pid of last msgsnd() */
> +  __pid_t msg_lrpid;		/* pid of last msgrcv() */
> +};
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> index 32173a7b60..43b38175ad 100644
> --- a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> @@ -27,11 +27,11 @@ struct msqid_ds
>    struct ipc_perm msg_perm;	/* structure describing operation permission */
>  #if __TIMESIZE == 32
>    __time_t msg_stime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_rtime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_ctime;		/* time of last change */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>  #else
>    __time_t msg_stime;		/* time of last msgsnd command */
>    __time_t msg_rtime;		/* time of last msgsnd command */
> diff --git a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
> index 3cf70e36c4..16eac46941 100644
> --- a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
> @@ -26,11 +26,11 @@ struct msqid_ds
>  {
>    struct ipc_perm msg_perm;	/* structure describing operation permission */
>  #if __TIMESIZE == 32
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_stime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_rtime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>    __time_t msg_ctime;		/* time of last change */
>  #else
>    __time_t msg_stime;		/* time of last msgsnd command */
> diff --git a/sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..69a63ee27a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long msg_stime_high;
> +  unsigned long msg_stime;
> +  unsigned long msg_rtime_high;
> +  unsigned long msg_rtime;
> +  unsigned long msg_ctime_high;
> +  unsigned long msg_ctime;
> +  unsigned long msg_cbytes;
> +  unsigned long msg_qnum;
> +  unsigned long msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..65b940567b
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct compat_msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long msg_stime;
> +  unsigned long msg_stime_high;
> +  unsigned long msg_rtime;
> +  unsigned long msg_rtime_high;
> +  unsigned long msg_ctime;
> +  unsigned long msg_ctime_high;
> +  unsigned long msg_cbytes;
> +  unsigned long msg_qnum;
> +  unsigned long msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/include/sys/msg.h b/sysdeps/unix/sysv/linux/include/sys/msg.h
> similarity index 55%
> rename from include/sys/msg.h
> rename to sysdeps/unix/sysv/linux/include/sys/msg.h
> index 43ec5b9472..522903f818 100644
> --- a/include/sys/msg.h
> +++ b/sysdeps/unix/sysv/linux/include/sys/msg.h
> @@ -6,6 +6,16 @@ extern ssize_t __libc_msgrcv (int msqid, void *msgp, size_t msgsz,
>  			      long int msgtyp, int msgflg);
>  extern int __libc_msgsnd (int msqid, const void *msgp, size_t msgsz,
>  			  int msgflg);
> +
> +# include <bits/types/struct_msqid64_ds.h>
> +
> +# if __TIMESIZE == 64
> +#  define __msgctl64 __msgctl
> +# else
> +extern int __msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf);
> +libc_hidden_proto (__msgctl64);
> +# endif
> +
>  #endif
>  
>  #endif
> diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
> index 85fdeef274..9ff010c763 100644
> --- a/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
> @@ -28,17 +28,17 @@ struct msqid_ds
>  #if __TIMESIZE == 32
>  # ifdef __MIPSEL__
>    __time_t msg_stime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_rtime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_ctime;		/* time of last change */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>  # else
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_stime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_rtime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>    __time_t msg_ctime;		/* time of last change */
>  # endif
>  #else
> diff --git a/sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..9cfd5a0dfe
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,33 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +#if __TIMESIZE == 32
> +# ifdef __MIPSEL__
> +  unsigned long int msg_stime;
> +  unsigned long int msg_stime_high;
> +  unsigned long int msg_rtime;
> +  unsigned long int msg_rtime_high;
> +  unsigned long int msg_ctime;
> +  unsigned long int msg_ctime_high;
> +# else
> +  unsigned long int msg_stime_high;
> +  unsigned long int msg_stime;
> +  unsigned long int msg_rtime_high;
> +  unsigned long int msg_rtime;
> +  unsigned long int msg_ctime_high;
> +  unsigned long int msg_ctime;
> +# endif
> +#else
> +  unsigned long int msg_stime;
> +  unsigned long int msg_rtime;
> +  unsigned long int msg_ctime;
> +#endif
> +  unsigned long int msg_cbytes;
> +  unsigned long int msg_qnum;
> +  unsigned long int msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long int __unused1;
> +  unsigned long int __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c
> index fd46aec1a0..a7f7651280 100644
> --- a/sysdeps/unix/sysv/linux/msgctl.c
> +++ b/sysdeps/unix/sysv/linux/msgctl.c
> @@ -23,16 +23,55 @@
>  #include <errno.h>
>  #include <linux/posix_types.h>  /* For __kernel_mode_t.  */
>  
> -#ifndef DEFAULT_VERSION
> -# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -#  define DEFAULT_VERSION GLIBC_2_2
> -# else
> -#  define DEFAULT_VERSION GLIBC_2_31
> -# endif
> +/* POSIX states ipc_perm mode should have type of mode_t.  */
> +_Static_assert (sizeof ((struct msqid_ds){0}.msg_perm.mode)
> +		== sizeof (mode_t),
> +		"sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");
> +
> +#if __IPC_TIME64 == 0
> +typedef struct msqid_ds msgctl_arg_t;
> +#else
> +# include <struct_kernel_msqid64_ds.h>
> +
> +static void
> +msqid64_to_kmsqid64 (const struct __msqid64_ds *msqid64,
> +		     struct kernel_msqid64_ds *kmsqid)
> +{
> +  kmsqid->msg_perm       = msqid64->msg_perm;
> +  kmsqid->msg_stime      = msqid64->msg_stime;
> +  kmsqid->msg_stime_high = msqid64->msg_stime >> 32;
> +  kmsqid->msg_rtime      = msqid64->msg_rtime;
> +  kmsqid->msg_rtime_high = msqid64->msg_rtime >> 32;
> +  kmsqid->msg_ctime      = msqid64->msg_ctime;
> +  kmsqid->msg_ctime_high = msqid64->msg_ctime >> 32;
> +  kmsqid->msg_qnum       = msqid64->msg_qnum;
> +  kmsqid->msg_qbytes     = msqid64->msg_qbytes;
> +  kmsqid->msg_lspid      = msqid64->msg_lspid;
> +  kmsqid->msg_lrpid      = msqid64->msg_lrpid;
> +}
> +
> +static void
> +kmsqid64_to_msqid64 (const struct kernel_msqid64_ds *kmsqid,
> +		     struct __msqid64_ds *msqid64)
> +{
> +  msqid64->msg_perm   = kmsqid->msg_perm;
> +  msqid64->msg_stime  = kmsqid->msg_stime
> +		        | ((__time64_t) kmsqid->msg_stime_high << 32);
> +  msqid64->msg_rtime  = kmsqid->msg_rtime
> +		        | ((__time64_t) kmsqid->msg_rtime_high << 32);
> +  msqid64->msg_ctime  = kmsqid->msg_ctime
> +		        | ((__time64_t) kmsqid->msg_ctime_high << 32);
> +  msqid64->msg_qnum   = kmsqid->msg_qnum;
> +  msqid64->msg_qbytes = kmsqid->msg_qbytes;
> +  msqid64->msg_lspid  = kmsqid->msg_lspid;
> +  msqid64->msg_lrpid  = kmsqid->msg_lrpid;
> +}
> +
> +typedef struct kernel_msqid64_ds msgctl_arg_t;
>  #endif
>  
>  static int
> -msgctl_syscall (int msqid, int cmd, struct msqid_ds *buf)
> +msgctl_syscall (int msqid, int cmd, msgctl_arg_t *buf)
>  {
>  #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
>    return INLINE_SYSCALL_CALL (msgctl, msqid, cmd | __IPC_64, buf);
> @@ -43,46 +82,118 @@ msgctl_syscall (int msqid, int cmd, struct msqid_ds *buf)
>  }
>  
>  int
> -__new_msgctl (int msqid, int cmd, struct msqid_ds *buf)
> +__msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf)
>  {
> -  /* POSIX states ipc_perm mode should have type of mode_t.  */
> -  _Static_assert (sizeof ((struct msqid_ds){0}.msg_perm.mode)
> -		  == sizeof (mode_t),
> -		  "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");
> -
> -#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -  struct msqid_ds tmpds;
> -  if (cmd == IPC_SET)
> +#if __IPC_TIME64
> +  struct kernel_msqid64_ds ksemid, *arg = NULL;
> +  if (buf != NULL)
>      {
> -      tmpds = *buf;
> -      tmpds.msg_perm.mode *= 0x10000U;
> -      buf = &tmpds;
> +      msqid64_to_kmsqid64 (buf, &ksemid);
> +      arg = &ksemid;
>      }
> +# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> +  if (cmd == IPC_SET)
> +    arg->msg_perm.mode *= 0x10000U;
> +# endif
> +#else
> +  msgctl_arg_t *arg = buf;
>  #endif
>  
> -  int ret = msgctl_syscall (msqid, cmd, buf);
> +  int ret = msgctl_syscall (msqid, cmd, arg);
> +  if (ret < 0)
> +    return ret;
>  
> -  if (ret >= 0)
> +  switch (cmd)
>      {
> -      switch (cmd)
> -	{
> -	case IPC_STAT:
> -	case MSG_STAT:
> -	case MSG_STAT_ANY:
> +    case IPC_STAT:
> +    case MSG_STAT:
> +    case MSG_STAT_ANY:
>  #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -	  buf->msg_perm.mode >>= 16;
> +      arg->msg_perm.mode >>= 16;
>  #else
> -	  /* Old Linux kernel versions might not clear the mode padding.  */
> -	  if (sizeof ((struct msqid_ds){0}.msg_perm.mode)
> -	      != sizeof (__kernel_mode_t))
> -	    buf->msg_perm.mode &= 0xFFFF;
> +      /* Old Linux kernel versions might not clear the mode padding.  */
> +      if (sizeof ((struct msqid_ds){0}.msg_perm.mode)
> +          != sizeof (__kernel_mode_t))
> +	arg->msg_perm.mode &= 0xFFFF;
> +#endif
> +
> +#if __IPC_TIME64
> +      kmsqid64_to_msqid64 (arg, buf);
>  #endif
> -	}
>      }
>  
>    return ret;
>  }
> -versioned_symbol (libc, __new_msgctl, msgctl, DEFAULT_VERSION);
> +#if __TIMESIZE != 64
> +libc_hidden_def (__msgctl64)
> +
> +static void
> +msqid_to_msqid64 (struct __msqid64_ds *mq64, const struct msqid_ds *mq)
> +{
> +  mq64->msg_perm   = mq->msg_perm;
> +  mq64->msg_stime  = mq->msg_stime
> +		     | ((__time64_t) mq->__msg_stime_high << 32);
> +  mq64->msg_rtime  = mq->msg_rtime
> +		     | ((__time64_t) mq->__msg_rtime_high << 32);
> +  mq64->msg_ctime  = mq->msg_ctime
> +		     | ((__time64_t) mq->__msg_ctime_high << 32);
> +  mq64->msg_qnum   = mq->msg_qnum;
> +  mq64->msg_qbytes = mq->msg_qbytes;
> +  mq64->msg_lspid  = mq->msg_lspid;
> +  mq64->msg_lrpid  = mq->msg_lrpid;
> +}
> +
> +static void
> +msqid64_to_msqid (struct msqid_ds *mq, const struct __msqid64_ds *mq64)
> +{
> +  mq->msg_perm         = mq64->msg_perm;
> +  mq->msg_stime        = mq64->msg_stime;
> +  mq->__msg_stime_high = 0;
> +  mq->msg_rtime        = mq64->msg_rtime;
> +  mq->__msg_rtime_high = 0;
> +  mq->msg_ctime        = mq64->msg_ctime;
> +  mq->__msg_ctime_high = 0;
> +  mq->msg_qnum         = mq64->msg_qnum;
> +  mq->msg_qbytes       = mq64->msg_qbytes;
> +  mq->msg_lspid        = mq64->msg_lspid;
> +  mq->msg_lrpid        = mq64->msg_lrpid;
> +}
> +
> +int
> +__msgctl (int msqid, int cmd, struct msqid_ds *buf)
> +{
> +  struct __msqid64_ds msqid64, *buf64 = NULL;
> +  if (buf != NULL)
> +    {
> +      msqid_to_msqid64 (&msqid64, buf);
> +      buf64 = &msqid64;
> +    }
> +
> +  int ret = __msgctl64 (msqid, cmd, buf64);
> +  if (ret < 0)
> +    return ret;
> +
> +  switch (cmd)
> +    {
> +    case IPC_STAT:
> +    case MSG_STAT:
> +    case MSG_STAT_ANY:
> +      if (buf64 != NULL)
> +        msqid64_to_msqid (buf, buf64);
> +    }
> +
> +  return ret;
> +}
> +#endif
> +
> +#ifndef DEFAULT_VERSION
> +# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
> +#  define DEFAULT_VERSION GLIBC_2_2
> +# else
> +#  define DEFAULT_VERSION GLIBC_2_31
> +# endif
> +#endif
> +versioned_symbol (libc, __msgctl, msgctl, DEFAULT_VERSION);
>  
>  #if defined __ASSUME_SYSVIPC_BROKEN_MODE_T \
>      && SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_31)
> @@ -90,7 +201,7 @@ int
>  attribute_compat_text_section
>  __msgctl_mode16 (int msqid, int cmd, struct msqid_ds *buf)
>  {
> -  return msgctl_syscall (msqid, cmd, buf);
> +  return msgctl_syscall (msqid, cmd, (msgctl_arg_t *) buf);
>  }
>  compat_symbol (libc, __msgctl_mode16, msgctl, GLIBC_2_2);
>  #endif
> diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
> index 4ae2fbcbdc..35cc51f733 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
> @@ -26,11 +26,11 @@ struct msqid_ds
>  {
>    struct ipc_perm msg_perm;	/* structure describing operation permission */
>  #if __TIMESIZE == 32
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_stime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_rtime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>    __time_t msg_ctime;		/* time of last change */
>  #else
>    __time_t msg_stime;		/* time of last msgsnd command */
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..69a63ee27a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long msg_stime_high;
> +  unsigned long msg_stime;
> +  unsigned long msg_rtime_high;
> +  unsigned long msg_rtime;
> +  unsigned long msg_ctime_high;
> +  unsigned long msg_ctime;
> +  unsigned long msg_cbytes;
> +  unsigned long msg_qnum;
> +  unsigned long msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c
> index 90460e6310..005c00ea75 100644
> --- a/sysdeps/unix/sysv/linux/semctl.c
> +++ b/sysdeps/unix/sysv/linux/semctl.c
> @@ -196,19 +196,11 @@ libc_hidden_def (__semctl64)
>  
>  /* The 64-bit time_t semid_ds version might have a different layout and
>     internal field alignment.  */
> -static void
> -semid64_ds_to_semid_ds (struct semid_ds *ds, const struct __semid64_ds *ds64)
> -{
> -  ds->sem_perm = ds64->sem_perm;
> -  ds->sem_otime = ds64->sem_otime;
> -  ds->sem_ctime = ds64->sem_ctime;
> -  ds->sem_nsems = ds64->sem_nsems;
> -}
>  
>  static void
> -semid_ds_to_semid64_ds (struct __semid64_ds *ds64, const struct semid_ds *ds)
> +semid_to_semid64 (struct __semid64_ds *ds64, const struct semid_ds *ds)
>  {
> -  ds64->sem_perm = ds->sem_perm;
> +  ds64->sem_perm  = ds->sem_perm;
>    ds64->sem_otime = ds->sem_otime
>  		    | ((__time64_t) ds->__sem_otime_high << 32);
>    ds64->sem_ctime = ds->sem_ctime
> @@ -216,6 +208,17 @@ semid_ds_to_semid64_ds (struct __semid64_ds *ds64, const struct semid_ds *ds)
>    ds64->sem_nsems = ds->sem_nsems;
>  }
>  
> +static void
> +semid64_to_semid (struct semid_ds *ds, const struct __semid64_ds *ds64)
> +{
> +  ds->sem_perm         = ds64->sem_perm;
> +  ds->sem_otime        = ds64->sem_otime;
> +  ds->__sem_otime_high = 0;
> +  ds->sem_ctime        = ds64->sem_ctime;
> +  ds->__sem_ctime_high = 0;
> +  ds->sem_nsems        = ds64->sem_nsems;
> +}
> +
>  static union semun64
>  semun_to_semun64 (int cmd, union semun semun, struct __semid64_ds *semid64)
>  {
> @@ -232,7 +235,7 @@ semun_to_semun64 (int cmd, union semun semun, struct __semid64_ds *semid64)
>      case IPC_STAT:
>      case IPC_SET:
>        r.buf = semid64;
> -      semid_ds_to_semid64_ds (r.buf, semun.buf);
> +      semid_to_semid64 (r.buf, semun.buf);
>  # ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
>        if (cmd == IPC_SET)
>  	r.buf->sem_perm.mode *= 0x10000U;
> @@ -282,7 +285,7 @@ __semctl (int semid, int semnum, int cmd, ...)
>      case IPC_STAT:
>      case SEM_STAT:
>      case SEM_STAT_ANY:
> -      semid64_ds_to_semid_ds (arg.buf, arg64.buf);
> +      semid64_to_semid (arg.buf, arg64.buf);
>      }
>  
>    return ret;
> diff --git a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
> index 71980839c7..502c23d91e 100644
> --- a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
> @@ -26,11 +26,11 @@ struct msqid_ds
>  {
>    struct ipc_perm msg_perm;	/* structure describing operation permission */
>  #if __TIMESIZE == 32
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_stime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_rtime;		/* time of last msgsnd command */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>    __time_t msg_ctime;		/* time of last change */
>  #else
>    __time_t msg_stime;		/* time of last msgsnd command */
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..69a63ee27a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long msg_stime_high;
> +  unsigned long msg_stime;
> +  unsigned long msg_rtime_high;
> +  unsigned long msg_rtime;
> +  unsigned long msg_ctime_high;
> +  unsigned long msg_ctime;
> +  unsigned long msg_cbytes;
> +  unsigned long msg_qnum;
> +  unsigned long msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..b88d910adc
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,19 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  It is only used
> +   for 32-bit architectures on 64-bit time_t msgctl64 implementation.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long int msg_stime;
> +  unsigned long int msg_stime_high;
> +  unsigned long int msg_rtime;
> +  unsigned long int msg_rtime_high;
> +  unsigned long int msg_ctime;
> +  unsigned long int msg_ctime_high;
> +  unsigned long int msg_cbytes;
> +  unsigned long int msg_qnum;
> +  unsigned long int msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long int __unused4;
> +  unsigned long int __unused5;
> +};
> 


-- 
Cheers,
Carlos.


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

* Re: [PATCH v2] sysv: linux: Add 64-bit time_t variant for msgctl
  2020-07-08 15:32     ` [PATCH v2] " Adhemerval Zanella
  2020-07-08 17:04       ` Carlos O'Donell
@ 2020-07-08 17:56       ` Alistair Francis
  1 sibling, 0 replies; 41+ messages in thread
From: Alistair Francis @ 2020-07-08 17:56 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: GNU C Library

On Wed, Jul 8, 2020 at 8:33 AM Adhemerval Zanella via Libc-alpha
<libc-alpha@sourceware.org> wrote:
>
> This is a small updated version that basically does:
>
>   git mv include/sys/msg.h sysdeps/unix/sysv/linux/include/sys/msg.h
>
> It moves the sysvipc to be Linux specific, since the generic version
> does implement _libc_msgsnd or __libc_msgrcv; and avoid a build failure
> on Hurd (since it does not provide struct_msqid64_ds.h).
>
> ---
>
> To provide a y2038 safe interface a new symbol __msgctl64 is added
> and __msgctl is change to call it instead (it adds some extra buffer
> coping for the 32 bit time_t implementation).
>
> Two new structures are added:
>
>   1. kernel_msqid64_ds: used internally only on 32-bit architectures
>      to issue the syscall.  A handful of architectures (hppa, i386, mips,
>      powerpc32, and sparc32) require specific implementations due to
>      their kernel ABI.
>
>   2. msqid_ds64: this is only for __TIMESIZE != 64 to use along with
>      the 64-bit semctl.  It is different than the kernel struct because
>      the exported 64-bit time_t might require different alignment
>      depending on the architecture ABI.
>
> So the resulting implementation does:
>
>   1. For 64-bit architectures it assumes msqid_ds already contains
>      64-bit time_t fields and will result in just the __msgctl symbol
>      using the __msgctl64 code.  The msgid_ds argument is passed as-is
>      to the syscall.
>
>   2. For 32-bit architectures with default 64-bit time_t (newer ABIs
>      such riscv32 or arc), it will also result in only one exported
>      symbol but with the required high/low time handling.
>
>   3. Finally for 32-bit architecture with both 32-bit and 64-bit time_t
>      support we follow the already set way to provide one symbol with
>      64-bit time_t support and implement the 32-bit time_t support using
>      the 64-bit time_t.
>
>      The default 32-bit symbol will allocate and copy the msqid_ds
>      over multiple buffers, but this should be deprecated in favor
>      of the __msgctl64 anyway.
>
> Checked on i686-linux-gnu and x86_64-linux-gnu.  I also did some sniff
> tests on powerpc, powerpc64, mips, mips64, armhf, sparcv9, and
> sparc64.
>
> Tested-by: Carlos O'Donell <carlos@redhat.com>
> Reviewed-by: Carlos O'Donell <carlos@redhat.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  .../sysv/linux/bits/types/struct_msqid64_ds.h |  38 ++++
>  .../sysv/linux/bits/types/struct_msqid_ds.h   |   6 +-
>  .../linux/hppa/bits/types/struct_msqid_ds.h   |   6 +-
>  .../linux/hppa/struct_kernel_msqid64_ds.h     |  18 ++
>  .../linux/i386/struct_kernel_msqid64_ds.h     |  18 ++
>  .../unix/sysv/linux/include}/sys/msg.h        |  10 +
>  .../linux/mips/bits/types/struct_msqid_ds.h   |  12 +-
>  .../linux/mips/struct_kernel_msqid64_ds.h     |  33 ++++
>  sysdeps/unix/sysv/linux/msgctl.c              | 179 ++++++++++++++----
>  .../powerpc/bits/types/struct_msqid_ds.h      |   6 +-
>  .../powerpc32/struct_kernel_msqid64_ds.h      |  18 ++
>  sysdeps/unix/sysv/linux/semctl.c              |  27 +--
>  .../linux/sparc/bits/types/struct_msqid_ds.h  |   6 +-
>  .../sparc/sparc32/struct_kernel_msqid64_ds.h  |  18 ++
>  .../sysv/linux/struct_kernel_msqid64_ds.h     |  19 ++
>  15 files changed, 350 insertions(+), 64 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h
>  rename {include => sysdeps/unix/sysv/linux/include}/sys/msg.h (55%)
>  create mode 100644 sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h
>
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h
> new file mode 100644
> index 0000000000..3536c8ea62
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h
> @@ -0,0 +1,38 @@
> +/* Generic implementation of the SysV message struct msqid64_ds.
> +   Copyright (C) 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_MSG_H
> +# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
> +#endif
> +
> +#if __TIMESIZE == 64
> +# define __msqid64_ds msqid_ds
> +#else
> +struct __msqid64_ds
> +{
> +  struct ipc_perm msg_perm;    /* structure describing operation permission */
> +  __time64_t msg_stime;                /* time of last msgsnd command */
> +  __time64_t msg_rtime;                /* time of last msgsnd command */
> +  __time64_t msg_ctime;                /* time of last change */
> +  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
> +  msgqnum_t msg_qnum;          /* number of messages currently on queue */
> +  msglen_t msg_qbytes;         /* max number of bytes allowed on queue */
> +  __pid_t msg_lspid;           /* pid of last msgsnd() */
> +  __pid_t msg_lrpid;           /* pid of last msgrcv() */
> +};
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> index 32173a7b60..43b38175ad 100644
> --- a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> @@ -27,11 +27,11 @@ struct msqid_ds
>    struct ipc_perm msg_perm;    /* structure describing operation permission */
>  #if __TIMESIZE == 32
>    __time_t msg_stime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_rtime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_ctime;          /* time of last change */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>  #else
>    __time_t msg_stime;          /* time of last msgsnd command */
>    __time_t msg_rtime;          /* time of last msgsnd command */
> diff --git a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
> index 3cf70e36c4..16eac46941 100644
> --- a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
> @@ -26,11 +26,11 @@ struct msqid_ds
>  {
>    struct ipc_perm msg_perm;    /* structure describing operation permission */
>  #if __TIMESIZE == 32
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_stime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_rtime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>    __time_t msg_ctime;          /* time of last change */
>  #else
>    __time_t msg_stime;          /* time of last msgsnd command */
> diff --git a/sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..69a63ee27a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long msg_stime_high;
> +  unsigned long msg_stime;
> +  unsigned long msg_rtime_high;
> +  unsigned long msg_rtime;
> +  unsigned long msg_ctime_high;
> +  unsigned long msg_ctime;
> +  unsigned long msg_cbytes;
> +  unsigned long msg_qnum;
> +  unsigned long msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..65b940567b
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct compat_msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long msg_stime;
> +  unsigned long msg_stime_high;
> +  unsigned long msg_rtime;
> +  unsigned long msg_rtime_high;
> +  unsigned long msg_ctime;
> +  unsigned long msg_ctime_high;
> +  unsigned long msg_cbytes;
> +  unsigned long msg_qnum;
> +  unsigned long msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/include/sys/msg.h b/sysdeps/unix/sysv/linux/include/sys/msg.h
> similarity index 55%
> rename from include/sys/msg.h
> rename to sysdeps/unix/sysv/linux/include/sys/msg.h
> index 43ec5b9472..522903f818 100644
> --- a/include/sys/msg.h
> +++ b/sysdeps/unix/sysv/linux/include/sys/msg.h
> @@ -6,6 +6,16 @@ extern ssize_t __libc_msgrcv (int msqid, void *msgp, size_t msgsz,
>                               long int msgtyp, int msgflg);
>  extern int __libc_msgsnd (int msqid, const void *msgp, size_t msgsz,
>                           int msgflg);
> +
> +# include <bits/types/struct_msqid64_ds.h>
> +
> +# if __TIMESIZE == 64
> +#  define __msgctl64 __msgctl
> +# else
> +extern int __msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf);
> +libc_hidden_proto (__msgctl64);
> +# endif
> +
>  #endif
>
>  #endif
> diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
> index 85fdeef274..9ff010c763 100644
> --- a/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
> @@ -28,17 +28,17 @@ struct msqid_ds
>  #if __TIMESIZE == 32
>  # ifdef __MIPSEL__
>    __time_t msg_stime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_rtime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_ctime;          /* time of last change */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>  # else
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_stime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_rtime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>    __time_t msg_ctime;          /* time of last change */
>  # endif
>  #else
> diff --git a/sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..9cfd5a0dfe
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,33 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +#if __TIMESIZE == 32
> +# ifdef __MIPSEL__
> +  unsigned long int msg_stime;
> +  unsigned long int msg_stime_high;
> +  unsigned long int msg_rtime;
> +  unsigned long int msg_rtime_high;
> +  unsigned long int msg_ctime;
> +  unsigned long int msg_ctime_high;
> +# else
> +  unsigned long int msg_stime_high;
> +  unsigned long int msg_stime;
> +  unsigned long int msg_rtime_high;
> +  unsigned long int msg_rtime;
> +  unsigned long int msg_ctime_high;
> +  unsigned long int msg_ctime;
> +# endif
> +#else
> +  unsigned long int msg_stime;
> +  unsigned long int msg_rtime;
> +  unsigned long int msg_ctime;
> +#endif
> +  unsigned long int msg_cbytes;
> +  unsigned long int msg_qnum;
> +  unsigned long int msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long int __unused1;
> +  unsigned long int __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c
> index fd46aec1a0..a7f7651280 100644
> --- a/sysdeps/unix/sysv/linux/msgctl.c
> +++ b/sysdeps/unix/sysv/linux/msgctl.c
> @@ -23,16 +23,55 @@
>  #include <errno.h>
>  #include <linux/posix_types.h>  /* For __kernel_mode_t.  */
>
> -#ifndef DEFAULT_VERSION
> -# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -#  define DEFAULT_VERSION GLIBC_2_2
> -# else
> -#  define DEFAULT_VERSION GLIBC_2_31
> -# endif
> +/* POSIX states ipc_perm mode should have type of mode_t.  */
> +_Static_assert (sizeof ((struct msqid_ds){0}.msg_perm.mode)
> +               == sizeof (mode_t),
> +               "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");
> +
> +#if __IPC_TIME64 == 0
> +typedef struct msqid_ds msgctl_arg_t;
> +#else
> +# include <struct_kernel_msqid64_ds.h>
> +
> +static void
> +msqid64_to_kmsqid64 (const struct __msqid64_ds *msqid64,
> +                    struct kernel_msqid64_ds *kmsqid)
> +{
> +  kmsqid->msg_perm       = msqid64->msg_perm;
> +  kmsqid->msg_stime      = msqid64->msg_stime;
> +  kmsqid->msg_stime_high = msqid64->msg_stime >> 32;
> +  kmsqid->msg_rtime      = msqid64->msg_rtime;
> +  kmsqid->msg_rtime_high = msqid64->msg_rtime >> 32;
> +  kmsqid->msg_ctime      = msqid64->msg_ctime;
> +  kmsqid->msg_ctime_high = msqid64->msg_ctime >> 32;
> +  kmsqid->msg_qnum       = msqid64->msg_qnum;
> +  kmsqid->msg_qbytes     = msqid64->msg_qbytes;
> +  kmsqid->msg_lspid      = msqid64->msg_lspid;
> +  kmsqid->msg_lrpid      = msqid64->msg_lrpid;
> +}
> +
> +static void
> +kmsqid64_to_msqid64 (const struct kernel_msqid64_ds *kmsqid,
> +                    struct __msqid64_ds *msqid64)
> +{
> +  msqid64->msg_perm   = kmsqid->msg_perm;
> +  msqid64->msg_stime  = kmsqid->msg_stime
> +                       | ((__time64_t) kmsqid->msg_stime_high << 32);
> +  msqid64->msg_rtime  = kmsqid->msg_rtime
> +                       | ((__time64_t) kmsqid->msg_rtime_high << 32);
> +  msqid64->msg_ctime  = kmsqid->msg_ctime
> +                       | ((__time64_t) kmsqid->msg_ctime_high << 32);
> +  msqid64->msg_qnum   = kmsqid->msg_qnum;
> +  msqid64->msg_qbytes = kmsqid->msg_qbytes;
> +  msqid64->msg_lspid  = kmsqid->msg_lspid;
> +  msqid64->msg_lrpid  = kmsqid->msg_lrpid;
> +}
> +
> +typedef struct kernel_msqid64_ds msgctl_arg_t;
>  #endif
>
>  static int
> -msgctl_syscall (int msqid, int cmd, struct msqid_ds *buf)
> +msgctl_syscall (int msqid, int cmd, msgctl_arg_t *buf)
>  {
>  #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
>    return INLINE_SYSCALL_CALL (msgctl, msqid, cmd | __IPC_64, buf);
> @@ -43,46 +82,118 @@ msgctl_syscall (int msqid, int cmd, struct msqid_ds *buf)
>  }
>
>  int
> -__new_msgctl (int msqid, int cmd, struct msqid_ds *buf)
> +__msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf)
>  {
> -  /* POSIX states ipc_perm mode should have type of mode_t.  */
> -  _Static_assert (sizeof ((struct msqid_ds){0}.msg_perm.mode)
> -                 == sizeof (mode_t),
> -                 "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");
> -
> -#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -  struct msqid_ds tmpds;
> -  if (cmd == IPC_SET)
> +#if __IPC_TIME64
> +  struct kernel_msqid64_ds ksemid, *arg = NULL;
> +  if (buf != NULL)
>      {
> -      tmpds = *buf;
> -      tmpds.msg_perm.mode *= 0x10000U;
> -      buf = &tmpds;
> +      msqid64_to_kmsqid64 (buf, &ksemid);
> +      arg = &ksemid;
>      }
> +# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> +  if (cmd == IPC_SET)
> +    arg->msg_perm.mode *= 0x10000U;
> +# endif
> +#else
> +  msgctl_arg_t *arg = buf;
>  #endif
>
> -  int ret = msgctl_syscall (msqid, cmd, buf);
> +  int ret = msgctl_syscall (msqid, cmd, arg);
> +  if (ret < 0)
> +    return ret;
>
> -  if (ret >= 0)
> +  switch (cmd)
>      {
> -      switch (cmd)
> -       {
> -       case IPC_STAT:
> -       case MSG_STAT:
> -       case MSG_STAT_ANY:
> +    case IPC_STAT:
> +    case MSG_STAT:
> +    case MSG_STAT_ANY:
>  #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -         buf->msg_perm.mode >>= 16;
> +      arg->msg_perm.mode >>= 16;
>  #else
> -         /* Old Linux kernel versions might not clear the mode padding.  */
> -         if (sizeof ((struct msqid_ds){0}.msg_perm.mode)
> -             != sizeof (__kernel_mode_t))
> -           buf->msg_perm.mode &= 0xFFFF;
> +      /* Old Linux kernel versions might not clear the mode padding.  */
> +      if (sizeof ((struct msqid_ds){0}.msg_perm.mode)
> +          != sizeof (__kernel_mode_t))
> +       arg->msg_perm.mode &= 0xFFFF;
> +#endif
> +
> +#if __IPC_TIME64
> +      kmsqid64_to_msqid64 (arg, buf);
>  #endif
> -       }
>      }
>
>    return ret;
>  }
> -versioned_symbol (libc, __new_msgctl, msgctl, DEFAULT_VERSION);
> +#if __TIMESIZE != 64
> +libc_hidden_def (__msgctl64)
> +
> +static void
> +msqid_to_msqid64 (struct __msqid64_ds *mq64, const struct msqid_ds *mq)
> +{
> +  mq64->msg_perm   = mq->msg_perm;
> +  mq64->msg_stime  = mq->msg_stime
> +                    | ((__time64_t) mq->__msg_stime_high << 32);
> +  mq64->msg_rtime  = mq->msg_rtime
> +                    | ((__time64_t) mq->__msg_rtime_high << 32);
> +  mq64->msg_ctime  = mq->msg_ctime
> +                    | ((__time64_t) mq->__msg_ctime_high << 32);
> +  mq64->msg_qnum   = mq->msg_qnum;
> +  mq64->msg_qbytes = mq->msg_qbytes;
> +  mq64->msg_lspid  = mq->msg_lspid;
> +  mq64->msg_lrpid  = mq->msg_lrpid;
> +}
> +
> +static void
> +msqid64_to_msqid (struct msqid_ds *mq, const struct __msqid64_ds *mq64)
> +{
> +  mq->msg_perm         = mq64->msg_perm;
> +  mq->msg_stime        = mq64->msg_stime;
> +  mq->__msg_stime_high = 0;
> +  mq->msg_rtime        = mq64->msg_rtime;
> +  mq->__msg_rtime_high = 0;
> +  mq->msg_ctime        = mq64->msg_ctime;
> +  mq->__msg_ctime_high = 0;
> +  mq->msg_qnum         = mq64->msg_qnum;
> +  mq->msg_qbytes       = mq64->msg_qbytes;
> +  mq->msg_lspid        = mq64->msg_lspid;
> +  mq->msg_lrpid        = mq64->msg_lrpid;
> +}
> +
> +int
> +__msgctl (int msqid, int cmd, struct msqid_ds *buf)
> +{
> +  struct __msqid64_ds msqid64, *buf64 = NULL;
> +  if (buf != NULL)
> +    {
> +      msqid_to_msqid64 (&msqid64, buf);
> +      buf64 = &msqid64;
> +    }
> +
> +  int ret = __msgctl64 (msqid, cmd, buf64);
> +  if (ret < 0)
> +    return ret;
> +
> +  switch (cmd)
> +    {
> +    case IPC_STAT:
> +    case MSG_STAT:
> +    case MSG_STAT_ANY:
> +      if (buf64 != NULL)
> +        msqid64_to_msqid (buf, buf64);
> +    }
> +
> +  return ret;
> +}
> +#endif
> +
> +#ifndef DEFAULT_VERSION
> +# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
> +#  define DEFAULT_VERSION GLIBC_2_2
> +# else
> +#  define DEFAULT_VERSION GLIBC_2_31
> +# endif
> +#endif
> +versioned_symbol (libc, __msgctl, msgctl, DEFAULT_VERSION);
>
>  #if defined __ASSUME_SYSVIPC_BROKEN_MODE_T \
>      && SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_31)
> @@ -90,7 +201,7 @@ int
>  attribute_compat_text_section
>  __msgctl_mode16 (int msqid, int cmd, struct msqid_ds *buf)
>  {
> -  return msgctl_syscall (msqid, cmd, buf);
> +  return msgctl_syscall (msqid, cmd, (msgctl_arg_t *) buf);
>  }
>  compat_symbol (libc, __msgctl_mode16, msgctl, GLIBC_2_2);
>  #endif
> diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
> index 4ae2fbcbdc..35cc51f733 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
> @@ -26,11 +26,11 @@ struct msqid_ds
>  {
>    struct ipc_perm msg_perm;    /* structure describing operation permission */
>  #if __TIMESIZE == 32
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_stime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_rtime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>    __time_t msg_ctime;          /* time of last change */
>  #else
>    __time_t msg_stime;          /* time of last msgsnd command */
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..69a63ee27a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long msg_stime_high;
> +  unsigned long msg_stime;
> +  unsigned long msg_rtime_high;
> +  unsigned long msg_rtime;
> +  unsigned long msg_ctime_high;
> +  unsigned long msg_ctime;
> +  unsigned long msg_cbytes;
> +  unsigned long msg_qnum;
> +  unsigned long msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c
> index 90460e6310..005c00ea75 100644
> --- a/sysdeps/unix/sysv/linux/semctl.c
> +++ b/sysdeps/unix/sysv/linux/semctl.c
> @@ -196,19 +196,11 @@ libc_hidden_def (__semctl64)
>
>  /* The 64-bit time_t semid_ds version might have a different layout and
>     internal field alignment.  */
> -static void
> -semid64_ds_to_semid_ds (struct semid_ds *ds, const struct __semid64_ds *ds64)
> -{
> -  ds->sem_perm = ds64->sem_perm;
> -  ds->sem_otime = ds64->sem_otime;
> -  ds->sem_ctime = ds64->sem_ctime;
> -  ds->sem_nsems = ds64->sem_nsems;
> -}
>
>  static void
> -semid_ds_to_semid64_ds (struct __semid64_ds *ds64, const struct semid_ds *ds)
> +semid_to_semid64 (struct __semid64_ds *ds64, const struct semid_ds *ds)
>  {
> -  ds64->sem_perm = ds->sem_perm;
> +  ds64->sem_perm  = ds->sem_perm;
>    ds64->sem_otime = ds->sem_otime
>                     | ((__time64_t) ds->__sem_otime_high << 32);
>    ds64->sem_ctime = ds->sem_ctime
> @@ -216,6 +208,17 @@ semid_ds_to_semid64_ds (struct __semid64_ds *ds64, const struct semid_ds *ds)
>    ds64->sem_nsems = ds->sem_nsems;
>  }
>
> +static void
> +semid64_to_semid (struct semid_ds *ds, const struct __semid64_ds *ds64)
> +{
> +  ds->sem_perm         = ds64->sem_perm;
> +  ds->sem_otime        = ds64->sem_otime;
> +  ds->__sem_otime_high = 0;
> +  ds->sem_ctime        = ds64->sem_ctime;
> +  ds->__sem_ctime_high = 0;
> +  ds->sem_nsems        = ds64->sem_nsems;
> +}
> +
>  static union semun64
>  semun_to_semun64 (int cmd, union semun semun, struct __semid64_ds *semid64)
>  {
> @@ -232,7 +235,7 @@ semun_to_semun64 (int cmd, union semun semun, struct __semid64_ds *semid64)
>      case IPC_STAT:
>      case IPC_SET:
>        r.buf = semid64;
> -      semid_ds_to_semid64_ds (r.buf, semun.buf);
> +      semid_to_semid64 (r.buf, semun.buf);
>  # ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
>        if (cmd == IPC_SET)
>         r.buf->sem_perm.mode *= 0x10000U;
> @@ -282,7 +285,7 @@ __semctl (int semid, int semnum, int cmd, ...)
>      case IPC_STAT:
>      case SEM_STAT:
>      case SEM_STAT_ANY:
> -      semid64_ds_to_semid_ds (arg.buf, arg64.buf);
> +      semid64_to_semid (arg.buf, arg64.buf);
>      }
>
>    return ret;
> diff --git a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
> index 71980839c7..502c23d91e 100644
> --- a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
> @@ -26,11 +26,11 @@ struct msqid_ds
>  {
>    struct ipc_perm msg_perm;    /* structure describing operation permission */
>  #if __TIMESIZE == 32
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_stime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_rtime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>    __time_t msg_ctime;          /* time of last change */
>  #else
>    __time_t msg_stime;          /* time of last msgsnd command */
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..69a63ee27a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long msg_stime_high;
> +  unsigned long msg_stime;
> +  unsigned long msg_rtime_high;
> +  unsigned long msg_rtime;
> +  unsigned long msg_ctime_high;
> +  unsigned long msg_ctime;
> +  unsigned long msg_cbytes;
> +  unsigned long msg_qnum;
> +  unsigned long msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..b88d910adc
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,19 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  It is only used
> +   for 32-bit architectures on 64-bit time_t msgctl64 implementation.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long int msg_stime;
> +  unsigned long int msg_stime_high;
> +  unsigned long int msg_rtime;
> +  unsigned long int msg_rtime_high;
> +  unsigned long int msg_ctime;
> +  unsigned long int msg_ctime_high;
> +  unsigned long int msg_cbytes;
> +  unsigned long int msg_qnum;
> +  unsigned long int msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long int __unused4;
> +  unsigned long int __unused5;
> +};
> --
> 2.25.1
>

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

* Re: [PATCH v2] sysv: linux: Add 64-bit time_t variant for shmctl
  2020-07-08 15:32     ` [PATCH v2] " Adhemerval Zanella
  2020-07-08 17:02       ` Carlos O'Donell
@ 2020-07-08 18:01       ` Alistair Francis
  2020-07-10 17:13       ` Joseph Myers
  2 siblings, 0 replies; 41+ messages in thread
From: Alistair Francis @ 2020-07-08 18:01 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: GNU C Library

On Wed, Jul 8, 2020 at 8:33 AM Adhemerval Zanella via Libc-alpha
<libc-alpha@sourceware.org> wrote:
>
> This is a small updated version that basically does:
>
>   git mv include/sys/shm.h sysdeps/unix/sysv/linux/include/sys/shm.h
>
> It basically avoids a build failure on Hurd (since it does not provide
> struct_shmid64_ds.h).
>
> ---
>
> To provide a y2038 safe interface a new symbol __shmctl64 is added
> and __shmctl is change to call it instead (it adds some extra buffer
> coping for the 32 bit time_t implementation).
>
> Two two new structures are added:
>
>   1. kernel_shmid64_ds: used internally only on 32-bit architectures
>      to issue the syscall.  A handful of architectures (hppa, i386,
>      mips, powerpc32, and sparc32) require specific implementations
>      due to their kernel ABI.
>
>   2. shmid_ds64: this is only for __TIMESIZE != 64 to use along with
>      the 64-bit semctl.  It is different than the kernel struct because
>      the exported 64-bit time_t might require different alignment
>      depending on the architecture ABI.
>
> So the resulting implementation does:
>
>   1. For 64-bit architectures it assumes shmid_ds already contains
>      64-bit time_t fields and will result in just the __shmctl symbol
>      using the __shmctl64 code.  The shmid_ds argument is passed as-is
>      to the syscall.
>
>   2. For 32-bit architectures with default 64-bit time_t (newer ABIs
>      such riscv32 or arc), it will also result in only one exported
>      symbol but with the required high/low time handling.
>
>   3. Finally for 32-bit architecture with both 32-bit and 64-bit time_t
>      support we follow the already set way to provide one symbol with
>      64-bit time_t support and implement the 32-bit time_t support
>      using of the 64-bit one.
>
>      The default 32-bit symbol will allocate and copy the shmid_ds
>      over multiple buffers, but this should be deprecated in favor
>      of the __shmctl64 anyway.
>
> Checked on i686-linux-gnu and x86_64-linux-gnu.  I also did some sniff
> tests on powerpc, powerpc64, mips, mips64, armhf, sparcv9, and
> sparc64.
>
> Tested-by: Carlos O'Donell <carlos@redhat.com>
> Reviewed-by: Carlos O'Donell <carlos@redhat.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

For the whole series:

Tested-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  include/sys/shm.h                             |   1 -
>  .../sysv/linux/bits/types/struct_shmid64_ds.h |  37 ++++
>  .../sysv/linux/bits/types/struct_shmid_ds.h   |   6 +-
>  .../linux/hppa/bits/types/struct_shmid_ds.h   |   6 +-
>  .../linux/hppa/struct_kernel_shmid64_ds.h     |  18 ++
>  .../linux/i386/struct_kernel_shmid64_ds.h     |  17 ++
>  sysdeps/unix/sysv/linux/include/sys/shm.h     |  17 ++
>  .../linux/mips/bits/types/struct_shmid_ds.h   |   6 +-
>  .../linux/mips/struct_kernel_shmid64_ds.h     |  27 +++
>  .../powerpc/bits/types/struct_shmid_ds.h      |   6 +-
>  .../linux/powerpc/struct_kernel_shmid64_ds.h  |  18 ++
>  sysdeps/unix/sysv/linux/shmctl.c              | 180 ++++++++++++++----
>  .../linux/sparc/bits/types/struct_shmid_ds.h  |   6 +-
>  .../linux/sparc/struct_kernel_shmid64_ds.h    |  17 ++
>  .../sysv/linux/struct_kernel_shmid64_ds.h     |  17 ++
>  15 files changed, 329 insertions(+), 50 deletions(-)
>  delete mode 100644 include/sys/shm.h
>  create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/include/sys/shm.h
>  create mode 100644 sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h
>
> diff --git a/include/sys/shm.h b/include/sys/shm.h
> deleted file mode 100644
> index 1878fcc5be..0000000000
> --- a/include/sys/shm.h
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysvipc/sys/shm.h>
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h
> new file mode 100644
> index 0000000000..f71e0d28ff
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h
> @@ -0,0 +1,37 @@
> +/* Generic implementation of the shared memory struct shmid_ds.
> +   Copyright (C) 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_SHM_H
> +# error "Never include <bits/types/struct_shmid_ds.h> directly; use <sys/shm.h> instead."
> +#endif
> +
> +#if __TIMESIZE == 64
> +# define __shmid64_ds shmid_ds
> +#else
> +struct __shmid64_ds
> +{
> +  struct ipc_perm shm_perm;    /* operation permission struct */
> +  size_t shm_segsz;            /* size of segment in bytes */
> +  __time64_t shm_atime;                /* time of last shmat() */
> +  __time64_t shm_dtime;                /* time of last shmdt() */
> +  __time64_t shm_ctime;                /* time of last change by shmctl() */
> +  __pid_t shm_cpid;            /* pid of creator */
> +  __pid_t shm_lpid;            /* pid of last shmop */
> +  shmatt_t shm_nattch;         /* number of current attaches */
> +};
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
> index 61ed4a08c3..836a7d50e9 100644
> --- a/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h
> @@ -27,11 +27,11 @@ struct shmid_ds
>      size_t shm_segsz;                  /* size of segment in bytes */
>  #if __TIMESIZE == 32
>      __time_t shm_atime;                        /* time of last shmat() */
> -    unsigned long int __glibc_reserved1;
> +    unsigned long int __shm_atime_high;
>      __time_t shm_dtime;                        /* time of last shmdt() */
> -    unsigned long int __glibc_reserved2;
> +    unsigned long int __shm_dtime_high;
>      __time_t shm_ctime;                        /* time of last change by shmctl() */
> -    unsigned long int __glibc_reserved3;
> +    unsigned long int __shm_ctime_high;
>  #else
>      __time_t shm_atime;                        /* time of last shmat() */
>      __time_t shm_dtime;                        /* time of last shmdt() */
> diff --git a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
> index 1ebf222eac..1abed1e149 100644
> --- a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
> +++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h
> @@ -25,11 +25,11 @@ struct shmid_ds
>    {
>      struct ipc_perm shm_perm;          /* operation permission struct */
>  #if __TIMESIZE == 32
> -    unsigned long int __glibc_reserved1;
> +    unsigned long int __shm_atime_high;
>      __time_t shm_atime;                        /* time of last shmat() */
> -    unsigned long int __glibc_reserved2;
> +    unsigned long int __shm_dtime_high;
>      __time_t shm_dtime;                        /* time of last shmdt() */
> -    unsigned long int __glibc_reserved3;
> +    unsigned long int __shm_ctime_high;
>      __time_t shm_ctime;                        /* time of last change by shmctl() */
>      unsigned long int __glibc_reserved4;
>  #else
> diff --git a/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h
> new file mode 100644
> index 0000000000..4d09fc7f62
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
> +struct kernel_shmid64_ds
> +{
> +  struct ipc_perm shm_perm;            /* operation permission struct */
> +  unsigned long int shm_atime_high;
> +  unsigned long int shm_atime;         /* time of last shmat() */
> +  unsigned long int shm_dtime_high;
> +  unsigned long int shm_dtime;         /* time of last shmdt() */
> +  unsigned long int shm_ctime_high;
> +  unsigned long int shm_ctime;         /* time of last change by shmctl() */
> +  unsigned long int __pad;
> +  size_t shm_segsz;                    /* size of segment in bytes */
> +  __pid_t shm_cpid;                    /* pid of creator */
> +  __pid_t shm_lpid;                    /* pid of last shmop */
> +  shmatt_t shm_nattch;         /* number of current attaches */
> +  unsigned long int __unused1;
> +  unsigned long int __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h
> new file mode 100644
> index 0000000000..6a0a0d9c71
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h
> @@ -0,0 +1,17 @@
> +/* Analogous to kernel struct compat_shmid64_ds used on shmctl.  */
> +struct kernel_shmid64_ds
> +{
> +  struct ipc_perm shm_perm;
> +  size_t shm_segsz;
> +  unsigned long int shm_atime;
> +  unsigned long int shm_atime_high;
> +  unsigned long int shm_dtime;
> +  unsigned long int shm_dtime_high;
> +  unsigned long int shm_ctime;
> +  unsigned long int shm_ctime_high;
> +  __pid_t shm_cpid;
> +  __pid_t shm_lpid;
> +  unsigned long int shm_nattch;
> +  unsigned long int __unused4;
> +  unsigned long int __unused5;
> +};
> diff --git a/sysdeps/unix/sysv/linux/include/sys/shm.h b/sysdeps/unix/sysv/linux/include/sys/shm.h
> new file mode 100644
> index 0000000000..530a1cdfc9
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/include/sys/shm.h
> @@ -0,0 +1,17 @@
> +#ifndef _SYS_SHM_H
> +#include <sysvipc/sys/shm.h>
> +
> +#ifndef _ISOMAC
> +
> +# include <bits/types/struct_shmid64_ds.h>
> +
> +# if __TIMESIZE == 64
> +#  define __shmctl64 __shmctl
> +# else
> +extern int __shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf);
> +libc_hidden_proto (__shmctl64);
> +# endif
> +
> +#endif /* _ISOMAC  */
> +
> +#endif /* _SYS_SHM_H  */
> diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
> index 8e13928980..58090e2fcb 100644
> --- a/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
> +++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h
> @@ -38,9 +38,9 @@ struct shmid_ds
>      __pid_t shm_lpid;                  /* pid of last shmop */
>      shmatt_t shm_nattch;               /* number of current attaches */
>  #if __TIMESIZE == 32
> -    unsigned short int __glibc_reserved1;
> -    unsigned short int __glibc_reserved2;
> -    unsigned short int __glibc_reserved3;
> +    unsigned short int __shm_atime_high;
> +    unsigned short int __shm_dtime_high;
> +    unsigned short int __shm_ctime_high;
>      unsigned short int __glibc_reserved4;
>  #else
>      __syscall_ulong_t __glibc_reserved5;
> diff --git a/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h
> new file mode 100644
> index 0000000000..a4baa5614f
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h
> @@ -0,0 +1,27 @@
> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
> +struct kernel_shmid64_ds
> +{
> +  struct ipc_perm shm_perm;
> +  size_t shm_segsz;
> +#if __TIMESIZE == 64
> +  long int shm_atime;
> +  long int shm_dtime;
> +  long int shm_ctime;
> +#else
> +  unsigned long int shm_atime;
> +  unsigned long int shm_dtime;
> +  unsigned long int shm_ctime;
> +#endif
> +  __pid_t shm_cpid;
> +  __pid_t shm_lpid;
> +  unsigned long int shm_nattch;
> +#if __TIMESIZE == 64
> +  unsigned long int __unused1;
> +  unsigned long int __unused2;
> +#else
> +  unsigned short int shm_atime_high;
> +  unsigned short int shm_dtime_high;
> +  unsigned short int shm_ctime_high;
> +  unsigned short int __ununsed1;
> +#endif
> +};
> diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
> index b0816fb16a..39b3e5fd3e 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
> +++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h
> @@ -25,11 +25,11 @@ struct shmid_ds
>    {
>      struct ipc_perm shm_perm;          /* operation permission struct */
>  #if __TIMESIZE == 32
> -    unsigned long int __glibc_reserved1;
> +    unsigned long int __shm_atime_high;
>      __time_t shm_atime;                        /* time of last shmat() */
> -    unsigned long int __glibc_reserved2;
> +    unsigned long int __shm_dtime_high;
>      __time_t shm_dtime;                        /* time of last shmdt() */
> -    unsigned long int __glibc_reserved3;
> +    unsigned long int __shm_ctime_high;
>      __time_t shm_ctime;                        /* time of last change by shmctl() */
>      unsigned long int __glibc_reserved4;
>  #else
> diff --git a/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
> new file mode 100644
> index 0000000000..ae3f3987ac
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
> +struct kernel_shmid64_ds
> +{
> +  struct ipc_perm shm_perm;
> +  unsigned long int shm_atime_high;
> +  unsigned long int shm_atime;
> +  unsigned long int shm_dtime_high;
> +  unsigned long int shm_dtime;
> +  unsigned long int shm_ctime_high;
> +  unsigned long int shm_ctime;
> +  unsigned long int __ununsed1;
> +  size_t shm_segsz;
> +  __pid_t shm_cpid;
> +  __pid_t shm_lpid;
> +  unsigned long int shm_nattch;
> +  unsigned long int __unused2;
> +  unsigned long int __unused3;
> +};
> diff --git a/sysdeps/unix/sysv/linux/shmctl.c b/sysdeps/unix/sysv/linux/shmctl.c
> index f41b359b8b..aaf3946054 100644
> --- a/sysdeps/unix/sysv/linux/shmctl.c
> +++ b/sysdeps/unix/sysv/linux/shmctl.c
> @@ -24,16 +24,55 @@
>  #include <errno.h>
>  #include <linux/posix_types.h>  /* For __kernel_mode_t.  */
>
> -#ifndef DEFAULT_VERSION
> -# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -#  define DEFAULT_VERSION GLIBC_2_2
> -# else
> -#  define DEFAULT_VERSION GLIBC_2_31
> -# endif
> +/* POSIX states ipc_perm mode should have type of mode_t.  */
> +_Static_assert (sizeof ((struct shmid_ds){0}.shm_perm.mode)
> +               == sizeof (mode_t),
> +               "sizeof (shmid_ds.shm_perm.mode) != sizeof (mode_t)");
> +
> +#if __IPC_TIME64 == 0
> +typedef struct shmid_ds shmctl_arg_t;
> +#else
> +# include <struct_kernel_shmid64_ds.h>
> +
> +static void
> +shmid64_to_kshmid64 (const struct __shmid64_ds *shmid64,
> +                    struct kernel_shmid64_ds *kshmid)
> +{
> +  kshmid->shm_perm       = shmid64->shm_perm;
> +  kshmid->shm_segsz      = shmid64->shm_segsz;
> +  kshmid->shm_atime      = shmid64->shm_atime;
> +  kshmid->shm_atime_high = shmid64->shm_atime >> 32;
> +  kshmid->shm_dtime      = shmid64->shm_dtime;
> +  kshmid->shm_dtime_high = shmid64->shm_dtime >> 32;
> +  kshmid->shm_ctime      = shmid64->shm_ctime;
> +  kshmid->shm_ctime_high = shmid64->shm_ctime >> 32;
> +  kshmid->shm_cpid       = shmid64->shm_cpid;
> +  kshmid->shm_lpid       = shmid64->shm_lpid;
> +  kshmid->shm_nattch     = shmid64->shm_nattch;
> +}
> +
> +static void
> +kshmid64_to_shmid64 (const struct kernel_shmid64_ds *kshmid,
> +                    struct __shmid64_ds *shmid64)
> +{
> +  shmid64->shm_perm   = kshmid->shm_perm;
> +  shmid64->shm_segsz  = kshmid->shm_segsz;
> +  shmid64->shm_atime  = kshmid->shm_atime
> +                       | ((__time64_t) kshmid->shm_atime_high << 32);
> +  shmid64->shm_dtime  = kshmid->shm_dtime
> +                       | ((__time64_t) kshmid->shm_dtime_high << 32);
> +  shmid64->shm_ctime     = kshmid->shm_ctime
> +                       | ((__time64_t) kshmid->shm_ctime_high << 32);
> +  shmid64->shm_cpid   = kshmid->shm_cpid;
> +  shmid64->shm_lpid   = kshmid->shm_lpid;
> +  shmid64->shm_nattch = kshmid->shm_nattch;
> +}
> +
> +typedef struct kernel_shmid64_ds shmctl_arg_t;
>  #endif
>
>  static int
> -shmctl_syscall (int shmid, int cmd, struct shmid_ds *buf)
> +shmctl_syscall (int shmid, int cmd, shmctl_arg_t *buf)
>  {
>  #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
>    return INLINE_SYSCALL_CALL (shmctl, shmid, cmd | __IPC_64, buf);
> @@ -45,46 +84,119 @@ shmctl_syscall (int shmid, int cmd, struct shmid_ds *buf)
>
>  /* Provide operations to control over shared memory segments.  */
>  int
> -__new_shmctl (int shmid, int cmd, struct shmid_ds *buf)
> +__shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf)
>  {
> -  /* POSIX states ipc_perm mode should have type of mode_t.  */
> -  _Static_assert (sizeof ((struct shmid_ds){0}.shm_perm.mode)
> -                 == sizeof (mode_t),
> -                 "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");
> -
> -#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -  struct shmid_ds tmpds;
> -  if (cmd == IPC_SET)
> +#if __IPC_TIME64
> +  struct kernel_shmid64_ds kshmid, *arg = NULL;
> +  if (buf != NULL)
>      {
> -      tmpds = *buf;
> -      tmpds.shm_perm.mode *= 0x10000U;
> -      buf = &tmpds;
> +      shmid64_to_kshmid64 (buf, &kshmid);
> +      arg = &kshmid;
>      }
> +# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> +  if (cmd == IPC_SET)
> +      arg->shm_perm.mode *= 0x10000U;
> +# endif
> +#else
> +  shmctl_arg_t *arg = buf;
>  #endif
>
> -  int ret = shmctl_syscall (shmid, cmd, buf);
> +  int ret = shmctl_syscall (shmid, cmd, arg);
> +  if (ret < 0)
> +    return ret;
>
> -  if (ret >= 0)
> +  switch (cmd)
>      {
> -      switch (cmd)
> -       {
> -        case IPC_STAT:
> -        case SHM_STAT:
> -        case SHM_STAT_ANY:
> +      case IPC_STAT:
> +      case SHM_STAT:
> +      case SHM_STAT_ANY:
>  #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -          buf->shm_perm.mode >>= 16;
> +        arg->shm_perm.mode >>= 16;
>  #else
> -         /* Old Linux kernel versions might not clear the mode padding.  */
> -         if (sizeof ((struct shmid_ds){0}.shm_perm.mode)
> -             != sizeof (__kernel_mode_t))
> -           buf->shm_perm.mode &= 0xFFFF;
> +      /* Old Linux kernel versions might not clear the mode padding.  */
> +      if (sizeof ((struct shmid_ds){0}.shm_perm.mode)
> +         != sizeof (__kernel_mode_t))
> +       arg->shm_perm.mode &= 0xFFFF;
> +#endif
> +
> +#if __IPC_TIME64
> +      kshmid64_to_shmid64 (arg, buf);
>  #endif
> -       }
>      }
>
>    return ret;
>  }
> -versioned_symbol (libc, __new_shmctl, shmctl, DEFAULT_VERSION);
> +#if __TIMESIZE != 64
> +libc_hidden_def (__shmctl64)
> +
> +static void
> +shmid_to_shmid64 (struct __shmid64_ds *shm64, const struct shmid_ds *shm)
> +{
> +  shm64->shm_perm   = shm->shm_perm;
> +  shm64->shm_segsz  = shm->shm_segsz;
> +  shm64->shm_atime  = shm->shm_atime
> +                       | ((__time64_t) shm->__shm_atime_high << 32);
> +  shm64->shm_dtime  = shm->shm_dtime
> +                       | ((__time64_t) shm->__shm_dtime_high << 32);
> +  shm64->shm_ctime     = shm->shm_ctime
> +                       | ((__time64_t) shm->__shm_ctime_high << 32);
> +  shm64->shm_cpid   = shm->shm_cpid;
> +  shm64->shm_lpid   = shm->shm_lpid;
> +  shm64->shm_nattch = shm->shm_nattch;
> +}
> +
> +static void
> +shmid64_to_shmid (struct shmid_ds *shm, const struct __shmid64_ds *shm64)
> +{
> +  shm->shm_perm         = shm64->shm_perm;
> +  shm->shm_segsz        = shm64->shm_segsz;
> +  shm->shm_atime        = shm64->shm_atime;
> +  shm->__shm_atime_high = 0;
> +  shm->shm_dtime        = shm64->shm_dtime;
> +  shm->__shm_dtime_high = 0;
> +  shm->shm_ctime        = shm64->shm_ctime;
> +  shm->__shm_ctime_high = 0;
> +  shm->shm_cpid         = shm64->shm_cpid;
> +  shm->shm_lpid         = shm64->shm_lpid;
> +  shm->shm_nattch       = shm64->shm_nattch;
> +}
> +
> +int
> +__shmctl (int shmid, int cmd, struct shmid_ds *buf)
> +{
> +  struct __shmid64_ds shmid64, *buf64 = NULL;
> +  if (buf != NULL)
> +    {
> +      shmid_to_shmid64 (&shmid64, buf);
> +      buf64 = &shmid64;
> +    }
> +
> +  int ret = __shmctl64 (shmid, cmd, buf64);
> +  if (ret < 0)
> +    return ret;
> +
> +  switch (cmd)
> +    {
> +      case IPC_STAT:
> +      case SHM_STAT:
> +      case SHM_STAT_ANY:
> +       if (buf64 != NULL)
> +         shmid64_to_shmid (buf, buf64);
> +    }
> +
> +  return ret;
> +}
> +#endif
> +
> +#ifndef DEFAULT_VERSION
> +# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
> +#  define DEFAULT_VERSION GLIBC_2_2
> +# else
> +#  define DEFAULT_VERSION GLIBC_2_31
> +# endif
> +#endif
> +
> +versioned_symbol (libc, __shmctl, shmctl, DEFAULT_VERSION);
>
>  #if defined __ASSUME_SYSVIPC_BROKEN_MODE_T \
>      && SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_31)
> @@ -92,7 +204,7 @@ int
>  attribute_compat_text_section
>  __shmctl_mode16 (int shmid, int cmd, struct shmid_ds *buf)
>  {
> -  return shmctl_syscall (shmid, cmd, buf);
> +  return shmctl_syscall (shmid, cmd, (shmctl_arg_t *) buf);
>  }
>  compat_symbol (libc, __shmctl_mode16, shmctl, GLIBC_2_2);
>  #endif
> diff --git a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h
> index d5fb61d374..cab3a2686f 100644
> --- a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h
> +++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h
> @@ -25,11 +25,11 @@ struct shmid_ds
>    {
>      struct ipc_perm shm_perm;          /* operation permission struct */
>  #if __TIMESIZE == 32
> -    unsigned long int __glibc_reserved1;
> +    unsigned long int __shm_atime_high;
>      __time_t shm_atime;                        /* time of last shmat() */
> -    unsigned long int __glibc_reserved2;
> +    unsigned long int __shm_dtime_high;
>      __time_t shm_dtime;                        /* time of last shmdt() */
> -    unsigned long int __glibc_reserved3;
> +    unsigned long int __shm_ctime_high;
>      __time_t shm_ctime;                        /* time of last change by shmctl() */
>  #else
>      __time_t shm_atime;                        /* time of last shmat() */
> diff --git a/sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h
> new file mode 100644
> index 0000000000..333a410641
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h
> @@ -0,0 +1,17 @@
> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
> +struct kernel_shmid64_ds
> +{
> +  struct ipc_perm shm_perm;
> +  unsigned long int shm_atime_high;
> +  unsigned long int shm_atime;
> +  unsigned long int shm_dtime_high;
> +  unsigned long int shm_dtime;
> +  unsigned long int shm_ctime_high;
> +  unsigned long int shm_ctime;
> +  size_t shm_segsz;
> +  __pid_t shm_cpid;
> +  __pid_t shm_lpid;
> +  unsigned long int shm_nattch;
> +  unsigned long int __unused1;
> +  unsigned long int __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h
> new file mode 100644
> index 0000000000..6fe67afccb
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h
> @@ -0,0 +1,17 @@
> +/* Analogous to kernel struct shmid64_ds used on shmctl.  */
> +struct kernel_shmid64_ds
> +{
> +  struct ipc_perm shm_perm;
> +  size_t shm_segsz;
> +  unsigned long int shm_atime;
> +  unsigned long int shm_atime_high;
> +  unsigned long int shm_dtime;
> +  unsigned long int shm_dtime_high;
> +  unsigned long int shm_ctime;
> +  unsigned long int shm_ctime_high;
> +  __pid_t shm_cpid;
> +  __pid_t shm_lpid;
> +  unsigned long int shm_nattch;
> +  unsigned long int __unused1;
> +  unsigned long int __unused2;
> +};
> --
> 2.25.1
>

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

* Re: [PATCH 4/7] sysv: linux: Add 64-bit time_t variant for msgctl
  2020-07-02 21:39   ` Alistair Francis
@ 2020-07-08 18:07     ` Adhemerval Zanella
  0 siblings, 0 replies; 41+ messages in thread
From: Adhemerval Zanella @ 2020-07-08 18:07 UTC (permalink / raw)
  To: Alistair Francis; +Cc: GNU C Library, Stepan Golosunov, Alistair Francis

On Thu, Jul 2, 2020 at 6:49 PM Alistair Francis <alistair23@gmail.com> wrote:
> >  #if defined __ASSUME_SYSVIPC_BROKEN_MODE_T \
> >      && SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_31)
> > @@ -90,7 +201,7 @@ int
> >  attribute_compat_text_section
> >  __msgctl_mode16 (int msqid, int cmd, struct msqid_ds *buf)
> >  {
> > -  return msgctl_syscall (msqid, cmd, buf);
> > +  return msgctl_syscall (msqid, cmd, (msgctl_arg_t *) buf);
> >  }
> >  compat_symbol (libc, __msgctl_mode16, msgctl, GLIBC_2_2);
> >  #endif
>
> Shouldn't everything below here be in a separate patch?

Sorry, I just saw you reply now. Yes, It has wrongly bled to this
patch. I will fix it.

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

* Re: [PATCH v2] sysv: linux: Add 64-bit time_t variant for shmctl
  2020-07-08 15:32     ` [PATCH v2] " Adhemerval Zanella
  2020-07-08 17:02       ` Carlos O'Donell
  2020-07-08 18:01       ` Alistair Francis
@ 2020-07-10 17:13       ` Joseph Myers
  2020-07-10 17:49         ` Adhemerval Zanella
  2 siblings, 1 reply; 41+ messages in thread
From: Joseph Myers @ 2020-07-10 17:13 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

On Wed, 8 Jul 2020, Adhemerval Zanella via Libc-alpha wrote:

> This is a small updated version that basically does:
> 
>   git mv include/sys/shm.h sysdeps/unix/sysv/linux/include/sys/shm.h
> 
> It basically avoids a build failure on Hurd (since it does not provide
> struct_shmid64_ds.h).

The build failure for Hurd is still present if there are no previously 
installed headers (so "compilers" build with build-many-glibcs.py).

https://sourceware.org/pipermail/libc-testresults/2020q3/006455.html

In file included from programs/locarchive.c:40:
../include/sys/shm.h:1:15: fatal error: sys/shm.h: No such file or 
directory
    1 | #include_next <sys/shm.h>
      |               ^~~~~~~~~~~

It's necessary to include the sysvipc/ path explicitly from include/, 
using #include_next won't work (or if it appears to work, will include a 
header from a previously installed glibc, not the one from the source 
tree).  I think you should have bits/types/struct_shmid64_ds.h for Hurd, 
even if initially nothing actually uses that type for Hurd.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [PATCH v2] sysv: linux: Add 64-bit time_t variant for shmctl
  2020-07-10 17:13       ` Joseph Myers
@ 2020-07-10 17:49         ` Adhemerval Zanella
  2020-07-10 17:57           ` Joseph Myers
  0 siblings, 1 reply; 41+ messages in thread
From: Adhemerval Zanella @ 2020-07-10 17:49 UTC (permalink / raw)
  To: Joseph Myers; +Cc: libc-alpha



On 10/07/2020 14:13, Joseph Myers wrote:
> On Wed, 8 Jul 2020, Adhemerval Zanella via Libc-alpha wrote:
> 
>> This is a small updated version that basically does:
>>
>>   git mv include/sys/shm.h sysdeps/unix/sysv/linux/include/sys/shm.h
>>
>> It basically avoids a build failure on Hurd (since it does not provide
>> struct_shmid64_ds.h).
> 
> The build failure for Hurd is still present if there are no previously 
> installed headers (so "compilers" build with build-many-glibcs.py).
> 
> https://sourceware.org/pipermail/libc-testresults/2020q3/006455.html
> 
> In file included from programs/locarchive.c:40:
> ../include/sys/shm.h:1:15: fatal error: sys/shm.h: No such file or 
> directory
>     1 | #include_next <sys/shm.h>
>       |               ^~~~~~~~~~~
> 
> It's necessary to include the sysvipc/ path explicitly from include/, 
> using #include_next won't work (or if it appears to work, will include a 
> header from a previously installed glibc, not the one from the source 
> tree).  I think you should have bits/types/struct_shmid64_ds.h for Hurd, 
> even if initially nothing actually uses that type for Hurd.
> 

Would be better to just add a Hurd specific sys/{msg,sem,shm.h}.h that
includes sysvipc/sys/{msg,sem,shm}.h? I has the advantage of not tying any
possible sysvipc support hurd might add to an specific internal ABI (such
as to provide the time64 support) and make the Linux specific localized in
Linux sysdeps folders.

Something like:

diff --git a/sysdeps/hurd/include/sys/msg.h b/sysdeps/hurd/include/sys/msg.h
new file mode 100644
index 0000000000..0f8026dda1
--- /dev/null
+++ b/sysdeps/hurd/include/sys/msg.h
@@ -0,0 +1 @@
+#include <sysvipc/sys/msg.h>
diff --git a/sysdeps/hurd/include/sys/sem.h b/sysdeps/hurd/include/sys/sem.h
new file mode 100644
index 0000000000..b0fb201bd0
--- /dev/null
+++ b/sysdeps/hurd/include/sys/sem.h
@@ -0,0 +1 @@
+#include <sysvipc/sys/sem.h>
diff --git a/sysdeps/hurd/include/sys/shm.h b/sysdeps/hurd/include/sys/shm.h
new file mode 100644
index 0000000000..1878fcc5be
--- /dev/null
+++ b/sysdeps/hurd/include/sys/shm.h
@@ -0,0 +1 @@
+#include <sysvipc/sys/shm.h>

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

* Re: [PATCH v2] sysv: linux: Add 64-bit time_t variant for shmctl
  2020-07-10 17:49         ` Adhemerval Zanella
@ 2020-07-10 17:57           ` Joseph Myers
  2020-07-10 17:59             ` Adhemerval Zanella
  0 siblings, 1 reply; 41+ messages in thread
From: Joseph Myers @ 2020-07-10 17:57 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

On Fri, 10 Jul 2020, Adhemerval Zanella wrote:

> Would be better to just add a Hurd specific sys/{msg,sem,shm.h}.h that
> includes sysvipc/sys/{msg,sem,shm}.h? I has the advantage of not tying any

I expect that would work as well.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [PATCH v2] sysv: linux: Add 64-bit time_t variant for shmctl
  2020-07-10 17:57           ` Joseph Myers
@ 2020-07-10 17:59             ` Adhemerval Zanella
  0 siblings, 0 replies; 41+ messages in thread
From: Adhemerval Zanella @ 2020-07-10 17:59 UTC (permalink / raw)
  To: Joseph Myers; +Cc: libc-alpha



On 10/07/2020 14:57, Joseph Myers wrote:
> On Fri, 10 Jul 2020, Adhemerval Zanella wrote:
> 
>> Would be better to just add a Hurd specific sys/{msg,sem,shm.h}.h that
>> includes sysvipc/sys/{msg,sem,shm}.h? I has the advantage of not tying any
> 
> I expect that would work as well.
> 

Ack, I will fire up a build-many-glibcs.py hurd build and send a patch.

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

end of thread, other threads:[~2020-07-10 17:59 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-30 19:24 [PATCH 1/7] sysv: linux: Add 64-bit time_t variant for semctl Adhemerval Zanella
2020-06-30 19:24 ` [PATCH 2/7] sysvipc: Split out linux struct semid_ds Adhemerval Zanella
2020-07-02 21:20   ` Alistair Francis
2020-07-07 19:01   ` Carlos O'Donell
2020-06-30 19:24 ` [PATCH 3/7] sysvipc: Remove the linux msq-pad.h file Adhemerval Zanella
2020-07-02 21:26   ` Alistair Francis
2020-07-07 19:05   ` Carlos O'Donell
2020-06-30 19:24 ` [PATCH 4/7] sysv: linux: Add 64-bit time_t variant for msgctl Adhemerval Zanella
2020-07-02 21:39   ` Alistair Francis
2020-07-08 18:07     ` Adhemerval Zanella
2020-07-07 19:51   ` Carlos O'Donell
2020-07-08 15:32     ` [PATCH v2] " Adhemerval Zanella
2020-07-08 17:04       ` Carlos O'Donell
2020-07-08 17:56       ` Alistair Francis
2020-06-30 19:24 ` [PATCH 5/7] sysvipc: Split out linux struct shmid_ds Adhemerval Zanella
2020-07-02 21:40   ` Alistair Francis
2020-07-07 19:52   ` Carlos O'Donell
2020-06-30 19:24 ` [PATCH 6/7] sysvipc: Remove the linux shm-pad.h file Adhemerval Zanella
2020-07-07 19:57   ` Carlos O'Donell
2020-06-30 19:24 ` [PATCH 7/7] sysv: linux: Add 64-bit time_t variant for shmctl Adhemerval Zanella
2020-07-01  2:28   ` Alistair Francis
2020-07-01 12:19     ` Adhemerval Zanella
2020-07-01 15:48       ` Alistair Francis
2020-07-01 16:35         ` Adhemerval Zanella
2020-07-01 17:07           ` Adhemerval Zanella
2020-07-01 20:59             ` Vineet Gupta
2020-07-01 23:00             ` Alistair Francis
2020-07-02 21:41               ` Alistair Francis
2020-07-07 21:33   ` Carlos O'Donell
2020-07-08 15:32     ` [PATCH v2] " Adhemerval Zanella
2020-07-08 17:02       ` Carlos O'Donell
2020-07-08 18:01       ` Alistair Francis
2020-07-10 17:13       ` Joseph Myers
2020-07-10 17:49         ` Adhemerval Zanella
2020-07-10 17:57           ` Joseph Myers
2020-07-10 17:59             ` Adhemerval Zanella
2020-07-02 19:01 ` [PATCH 1/7] sysv: linux: Add 64-bit time_t variant for semctl Alistair Francis
2020-07-07  3:32 ` Carlos O'Donell
2020-07-07 14:09   ` Adhemerval Zanella
2020-07-08 15:32     ` [PATCH v2] " Adhemerval Zanella
2020-07-08 17:04       ` Carlos O'Donell

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).