aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2020-06-30 14:08:22 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2020-07-07 15:12:52 -0300
commitbdfeee2a1fd2453b2d1e91cbd5ab02111a7adfb6 (patch)
treea33707d11f6069e65f2998a1fa75e5de0b26b89b
parent199dbdcf98de8e8e8361eb98702d0509383c30e2 (diff)
sysv: linux: Add 64-bit time_t variant for shmctl
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.
-rw-r--r--include/sys/shm.h16
-rw-r--r--sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h37
-rw-r--r--sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h6
-rw-r--r--sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h6
-rw-r--r--sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h18
-rw-r--r--sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h17
-rw-r--r--sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h6
-rw-r--r--sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h27
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h6
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h18
-rw-r--r--sysdeps/unix/sysv/linux/shmctl.c180
-rw-r--r--sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h6
-rw-r--r--sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h17
-rw-r--r--sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h17
14 files changed, 328 insertions, 49 deletions
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..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;
+};