This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH v3 3/3] sysv: linux: Pass 64-bit version of semctl syscall
- From: Alistair Francis <alistair dot francis at wdc dot com>
- To: libc-alpha at sourceware dot org
- Cc: alistair23 at gmail dot com, Alistair Francis <alistair dot francis at wdc dot com>
- Date: Wed, 4 Mar 2020 17:26:05 -0800
- Subject: [PATCH v3 3/3] sysv: linux: Pass 64-bit version of semctl syscall
- Ironport-sdr: 47i9t/MBj3alTz2hRPXi+JaCBGn3GuL7vH0V3ht1rHsjGAPnlVnnS3M76YLsQTCiEJsLx9Z1o3 5VhN0ad18O5985rjrkUSUPNLwueOvuraeeoyUY7PQM3yi8xLx7NJ9/CuQlWhWNjQwm3DVJA6Ol HFRxKalrFhRi1xf474YQssgDmvZTj6MW181VJOLbhWkWY+SYH6H8SW1HawMjy5uZ4q+IJRCGlc xzE7Qz98wjlaN/b3V34pOBV56+DBE2JXVcysjtb2obNyv9kWDrE3dDYWRRp+bAvxzkvG9puf0q zyg=
- Ironport-sdr: yoe9Tf4000E+05KZL+n3B8yD0kjmtbPSgKrvUA+N6glUNzg5K8VaivprpjgQqisab/m77KqruT yH3upz71gQozINMCzVbLB3KyWadvlV69QSwxiUbdMujgCEOAy91s0FT4/QGZTXfu7PTTqW/x9U iY5BI5oLOiU2TxLWPf1qH8sFq6ElXMO8CX4B8lN+VE1ltTcqhP4pD25As3lGyf2WtjHlLQH+Tv /OSt5jncyf2fkBDCW+xuwUcUBRYD6G4Evi7EpE5Ci2dqavfJRwJ8nH7vnjN6N1Cbgc9abr9gbI GwJyTJRy1cEByg0if020yEBN
- Ironport-sdr: 2/nebodbudQbgfB6HaHoGPQMi3/l7IuxeDYKYhV2848QOTpW25sgsjuJh9WeV5o9QoYrfCmrk/ l124vAHoFb2IjNkzwkmur2CtEXDwRP4avkdCwDz8rgPQKU9SONiyEXs+cbWeBtk/lWxgCNxIiL zSsPf/qaoiWEuWhXRuGB6jcxOjh2opPuFjjtKOqGVWQOfQTlArcsa6OMrIXjO+KSREHy9dNgHR UEo0Nlz7YGYFXUSY9SJPFczJqY3v18GT8je3XMl6WnmnHF78+FHUAoPSoogiDbS7XD2rl9wDSu En0=
- References: <20200305012605.26870-1-alistair.francis@wdc.com>
- Wdcironportexception: Internal
The semctl_syscall() function passes a union semun to the kernel. The
union includes struct semid_ds as a member. On 32-bit architectures the
Linux kernel provides a *_high version of the 32-bit sem_otime and
sem_ctime values. These can be combined to get a 64-bit version of the
time.
This patch adjusts the struct semid_ds to support the *_high versions
of sem_otime and sem_ctime. For 32-bit systems with a 64-bit time_t
this can be used to get a 64-bit time from the two 32-bit values.
We protect this new code via the __IPC_TIME64 marco, which is only true
for 32-bit architectures with a 64-bit time_t.
---
bits/ipc.h | 6 ++++-
sysdeps/gnu/bits/ipc.h | 6 ++++-
sysdeps/unix/sysv/linux/bits/ipc.h | 6 ++++-
sysdeps/unix/sysv/linux/bits/semid_ds_t.h | 15 +++++++++++
.../unix/sysv/linux/hppa/bits/semid_ds_t.h | 15 +++++++++++
.../unix/sysv/linux/mips/bits/semid_ds_t.h | 13 ++++++++++
.../unix/sysv/linux/powerpc/bits/semid_ds_t.h | 15 +++++++++++
sysdeps/unix/sysv/linux/semctl.c | 25 ++++++++++++++++---
.../unix/sysv/linux/sparc/bits/semid_ds_t.h | 15 +++++++++++
sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h | 15 +++++++++++
10 files changed, 124 insertions(+), 7 deletions(-)
diff --git a/bits/ipc.h b/bits/ipc.h
index e2981fd5c3..9ac8485193 100644
--- a/bits/ipc.h
+++ b/bits/ipc.h
@@ -29,7 +29,11 @@
/* Control commands for `msgctl', `semctl', and `shmctl'. */
#define IPC_RMID 0 /* remove identifier */
#define IPC_SET 1 /* set `ipc_perm' options */
-#define IPC_STAT 2 /* get `ipc_perm' options */
+#if __TIMESIZE == 64 && __WORDSIZE == 32
+# define IPC_STAT 0x102 /* Get `ipc_perm' options. */
+#else
+# define IPC_STAT 2 /* Get `ipc_perm' options. */
+#endif
/* Special key values. */
#define IPC_PRIVATE ((key_t) 0) /* private key */
diff --git a/sysdeps/gnu/bits/ipc.h b/sysdeps/gnu/bits/ipc.h
index 47df305e1c..328c11a0d7 100644
--- a/sysdeps/gnu/bits/ipc.h
+++ b/sysdeps/gnu/bits/ipc.h
@@ -29,7 +29,11 @@
/* Control commands for `msgctl', `semctl', and `shmctl'. */
#define IPC_RMID 0 /* Remove identifier. */
#define IPC_SET 1 /* Set `ipc_perm' options. */
-#define IPC_STAT 2 /* Get `ipc_perm' options. */
+#if __TIMESIZE == 64 && __WORDSIZE == 32
+# define IPC_STAT 0x102 /* Get `ipc_perm' options. */
+#else
+# define IPC_STAT 2 /* Get `ipc_perm' options. */
+#endif
#ifdef __USE_GNU
# define IPC_INFO 3 /* See ipcs. */
#endif
diff --git a/sysdeps/unix/sysv/linux/bits/ipc.h b/sysdeps/unix/sysv/linux/bits/ipc.h
index 085dd628ac..44449de62f 100644
--- a/sysdeps/unix/sysv/linux/bits/ipc.h
+++ b/sysdeps/unix/sysv/linux/bits/ipc.h
@@ -29,7 +29,11 @@
/* Control commands for `msgctl', `semctl', and `shmctl'. */
#define IPC_RMID 0 /* Remove identifier. */
#define IPC_SET 1 /* Set `ipc_perm' options. */
-#define IPC_STAT 2 /* Get `ipc_perm' options. */
+#if __TIMESIZE == 64 && __WORDSIZE == 32
+# define IPC_STAT 0x102 /* Get `ipc_perm' options. */
+#else
+# define IPC_STAT 2 /* Get `ipc_perm' options. */
+#endif
#ifdef __USE_GNU
# define IPC_INFO 3 /* See ipcs. */
#endif
diff --git a/sysdeps/unix/sysv/linux/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/bits/semid_ds_t.h
index d9d902ed0d..b135301356 100644
--- a/sysdeps/unix/sysv/linux/bits/semid_ds_t.h
+++ b/sysdeps/unix/sysv/linux/bits/semid_ds_t.h
@@ -20,6 +20,21 @@
# error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead."
#endif
+#if __WORDSIZE == 32
+/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
+ * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */
+struct __semid_ds32 {
+ struct ipc_perm sem_perm; /* operation permission struct */
+ __syscall_ulong_t sem_otime; /* last semop() time */
+ __syscall_ulong_t sem_otime_high; /* last semop() time high */
+ __syscall_ulong_t sem_ctime; /* last time changed by semctl() */
+ __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */
+ __syscall_ulong_t sem_nsems; /* number of semaphores in set */
+ __syscall_ulong_t __glibc_reserved3;
+ __syscall_ulong_t __glibc_reserved4;
+};
+#endif
+
/* Data structure describing a set of semaphores. */
#if __TIMESIZE == 32
struct semid_ds
diff --git a/sysdeps/unix/sysv/linux/hppa/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/hppa/bits/semid_ds_t.h
index 39c0e53f38..3613c5ec94 100644
--- a/sysdeps/unix/sysv/linux/hppa/bits/semid_ds_t.h
+++ b/sysdeps/unix/sysv/linux/hppa/bits/semid_ds_t.h
@@ -20,6 +20,21 @@
# error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead."
#endif
+#if __WORDSIZE == 32
+/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
+ * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */
+struct __semid_ds32 {
+ struct ipc_perm sem_perm; /* operation permission struct */
+ __syscall_ulong_t sem_otime_high; /* last semop() time high */
+ __syscall_ulong_t sem_otime; /* last semop() time */
+ __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */
+ __syscall_ulong_t sem_ctime; /* last time changed by semctl() */
+ __syscall_ulong_t sem_nsems; /* number of semaphores in set */
+ __syscall_ulong_t __glibc_reserved3;
+ __syscall_ulong_t __glibc_reserved4;
+};
+#endif
+
/* Data structure describing a set of semaphores. */
#if __TIMESIZE == 32
struct semid_ds
diff --git a/sysdeps/unix/sysv/linux/mips/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/mips/bits/semid_ds_t.h
index 1ab16492dd..e26906a67f 100644
--- a/sysdeps/unix/sysv/linux/mips/bits/semid_ds_t.h
+++ b/sysdeps/unix/sysv/linux/mips/bits/semid_ds_t.h
@@ -20,6 +20,19 @@
# error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead."
#endif
+#if __WORDSIZE == 32
+/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
+ * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */
+struct __semid_ds32 {
+ struct ipc_perm sem_perm; /* operation permission struct */
+ __syscall_ulong_t sem_otime; /* last semop time */
+ __syscall_ulong_t sem_ctime; /* last change time */
+ __syscall_ulong_t sem_nsems; /* number of semaphores in set */
+ __syscall_ulong_t sem_otime_high;
+ __syscall_ulong_t sem_ctime_high;
+};
+#endif
+
/* Data structure describing a set of semaphores. */
struct semid_ds
{
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/powerpc/bits/semid_ds_t.h
index 79b4cba939..ec2ff552eb 100644
--- a/sysdeps/unix/sysv/linux/powerpc/bits/semid_ds_t.h
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/semid_ds_t.h
@@ -20,6 +20,21 @@
# error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead."
#endif
+#if __WORDSIZE == 32
+/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
+ * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */
+struct __semid_ds32 {
+ struct ipc_perm sem_perm; /* operation permission struct */
+ __syscall_ulong_t sem_otime_high; /* last semop() time high */
+ __syscall_ulong_t sem_otime; /* last semop() time */
+ __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */
+ __syscall_ulong_t sem_ctime; /* last time changed by semctl() */
+ __syscall_ulong_t sem_nsems; /* number of semaphores in set */
+ __syscall_ulong_t __glibc_reserved3;
+ __syscall_ulong_t __glibc_reserved4;
+};
+#endif
+
/* Data structure describing a set of semaphores. */
#if __TIMESIZE == 32
struct semid_ds
diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c
index 0c3eb0932f..3ac6d01b84 100644
--- a/sysdeps/unix/sysv/linux/semctl.c
+++ b/sysdeps/unix/sysv/linux/semctl.c
@@ -23,11 +23,16 @@
#include <shlib-compat.h>
#include <errno.h>
+#define __IPC_TIME64 (IPC_STAT & __IPC_64)
+
/* Define a `union semun' suitable for Linux here. */
union semun
{
int val; /* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */
+#if __WORDSIZE == 32
+ struct __semid_ds32 *buf32; /* 32-bit buffer for IPC_STAT & IPC_SET */
+#endif
unsigned short int *array; /* array for GETALL & SETALL */
struct seminfo *__buf; /* buffer for IPC_INFO */
};
@@ -43,13 +48,25 @@ union semun
static int
semctl_syscall (int semid, int semnum, int cmd, union semun arg)
{
+ int ret;
#ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
- return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64,
- arg.array);
+ ret = INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64,
+ arg.array);
#else
- return INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64,
- SEMCTL_ARG_ADDRESS (arg));
+ ret = INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64,
+ SEMCTL_ARG_ADDRESS (arg));
+#endif
+
+#if __IPC_TIME64
+ if (ret == 0 && (cmd & __IPC_TIME64))
+ {
+ arg.buf->sem_ctime = arg.buf32->sem_ctime |
+ ((time_t) arg.buf32->sem_ctime_high << 32);
+ arg.buf->sem_otime = arg.buf32->sem_otime |
+ ((time_t) arg.buf32->sem_otime_high << 32);
+ }
#endif
+ return ret;
}
int
diff --git a/sysdeps/unix/sysv/linux/sparc/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/sparc/bits/semid_ds_t.h
index f8de676e79..b08fb8a79e 100644
--- a/sysdeps/unix/sysv/linux/sparc/bits/semid_ds_t.h
+++ b/sysdeps/unix/sysv/linux/sparc/bits/semid_ds_t.h
@@ -20,6 +20,21 @@
# error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead."
#endif
+#if __WORDSIZE == 32
+/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
+ * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */
+struct __semid_ds32 {
+ struct ipc_perm sem_perm; /* operation permission struct */
+ __syscall_ulong_t sem_otime_high; /* last semop() time high */
+ __syscall_ulong_t sem_otime; /* last semop() time */
+ __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */
+ __syscall_ulong_t sem_ctime; /* last time changed by semctl() */
+ __syscall_ulong_t sem_nsems; /* number of semaphores in set */
+ __syscall_ulong_t __glibc_reserved3;
+ __syscall_ulong_t __glibc_reserved4;
+};
+#endif
+
/* Data structure describing a set of semaphores. */
#if __TIMESIZE == 32
struct semid_ds
diff --git a/sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h
index 42694069d5..c7b9adce88 100644
--- a/sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h
+++ b/sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h
@@ -20,6 +20,21 @@
# error "Never include <bits/semid_ds_t.h> directly; use <sys/sem.h> instead."
#endif
+#if __WORDSIZE == 32
+/* This is the "new" y2038 types defined after the 5.1 kernel. It allows
+ * the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */
+struct __semid_ds32 {
+ struct ipc_perm sem_perm; /* operation permission struct */
+ __syscall_ulong_t sem_otime; /* last semop() time */
+ __syscall_ulong_t sem_otime_high; /* last semop() time high */
+ __syscall_ulong_t sem_ctime; /* last time changed by semctl() */
+ __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */
+ __syscall_ulong_t sem_nsems; /* number of semaphores in set */
+ __syscall_ulong_t __glibc_reserved3;
+ __syscall_ulong_t __glibc_reserved4;
+};
+#endif
+
/* Data structure describing a set of semaphores. */
struct semid_ds
{
--
2.25.1