From: Alistair Francis <alistair.francis@wdc.com>
To: libc-alpha@sourceware.org
Cc: adhemerval.zanella@linaro.org, stepan@golosunov.pp.ru,
alistair23@gmail.com, Alistair Francis <alistair.francis@wdc.com>
Subject: [PATCH v8 2/2] sysv: linux: Pass 64-bit version of semctl syscall
Date: Wed, 13 May 2020 08:22:49 -0700 [thread overview]
Message-ID: <20200513152249.5103-3-alistair.francis@wdc.com> (raw)
In-Reply-To: <20200513152249.5103-1-alistair.francis@wdc.com>
The semctl_syscall() function passes a union semun to the kernel. The
union includes struct semid_ds as a member. On 32-bit architectures the
Linux kernel provides a *_high version of the 32-bit sem_otime and
sem_ctime values. These can be combined to get a 64-bit version of the
time.
This patch adjusts the struct semid_ds to support the *_high versions
of sem_otime and sem_ctime. For 32-bit systems with a 64-bit time_t
this can be used to get a 64-bit time from the two 32-bit values.
Due to alignment differences between 64-bit and 32-bit variables we
also need to set nsems to ensure it's correct.
---
sysdeps/unix/sysv/linux/ipc_priv.h | 4 +++
sysdeps/unix/sysv/linux/semctl.c | 50 +++++++++++++++++++++++++++---
2 files changed, 50 insertions(+), 4 deletions(-)
diff --git a/sysdeps/unix/sysv/linux/ipc_priv.h b/sysdeps/unix/sysv/linux/ipc_priv.h
index 15a6e683a4..a1a7cacd17 100644
--- a/sysdeps/unix/sysv/linux/ipc_priv.h
+++ b/sysdeps/unix/sysv/linux/ipc_priv.h
@@ -43,6 +43,10 @@ struct __old_ipc_perm
unsigned short int __seq; /* Sequence number. */
};
+#define __IPC_TIME64 \
+ (__WORDSIZE == 32 && __TIMESIZE == 64 \
+ && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
+
#define SEMCTL_ARG_ADDRESS(__arg) &__arg.array
#define MSGRCV_ARGS(__msgp, __msgtyp) \
diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c
index 30571af49f..3ed2af89d1 100644
--- a/sysdeps/unix/sysv/linux/semctl.c
+++ b/sysdeps/unix/sysv/linux/semctl.c
@@ -22,6 +22,7 @@
#include <sysdep.h>
#include <shlib-compat.h>
#include <errno.h>
+#include <struct__semid_ds32.h>
#include <linux/posix_types.h> /* For __kernel_mode_t. */
/* Define a `union semun' suitable for Linux here. */
@@ -44,13 +45,54 @@ union semun
static int
semctl_syscall (int semid, int semnum, int cmd, union semun arg)
{
+ int ret;
+#if __IPC_TIME64
+ /* A temporary buffer is used to avoid both an issue where the export
+ semid_ds might not follow the kernel's expected layout (due
+ to {o,c}time{_high} alignment in 64-bit time case) and the issue where
+ some kernel versions might not clear the high bits when returning
+ then {o,c}time{_high} information. */
+ struct __semid_ds32 tmp;
+ struct semid_ds *orig;
+ bool restore = false;
+ if (cmd == IPC_STAT || cmd == SEM_STAT || cmd == SEM_STAT_ANY)
+ {
+ tmp = (struct __semid_ds32) {
+ .sem_perm = arg.buf->sem_perm,
+ .sem_otime = arg.buf->sem_otime,
+ .sem_otime_high = arg.buf->sem_otime >> 32,
+ .sem_ctime = arg.buf->sem_ctime,
+ .sem_ctime_high = arg.buf->sem_ctime >> 32,
+ .sem_nsems = arg.buf->sem_nsems,
+ };
+ orig = arg.buf;
+ arg.buf = (struct semid_ds*) &tmp;
+ restore = true;
+ }
+#endif
+
#ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
- return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64,
- arg.array);
+ ret = INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64,
+ arg.array);
#else
- return INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64,
- SEMCTL_ARG_ADDRESS (arg));
+ ret = INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64,
+ SEMCTL_ARG_ADDRESS (arg));
#endif
+
+#if __IPC_TIME64
+ if (ret >= 0 && restore)
+ {
+ arg.buf = orig;
+ arg.buf->sem_perm = tmp.sem_perm;
+ arg.buf->sem_otime = tmp.sem_otime
+ | ((__time64_t) tmp.sem_otime_high << 32);
+ arg.buf->sem_ctime = tmp.sem_ctime
+ | ((__time64_t) tmp.sem_ctime_high << 32);
+ arg.buf->sem_nsems = tmp.sem_nsems;
+ }
+#endif
+
+ return ret;
}
int
--
2.26.2
next prev parent reply other threads:[~2020-05-13 15:31 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-13 15:22 [PATCH v8 0/2] Support semctl_syscall() for __TIMESIZE==64 Alistair Francis
2020-05-13 15:22 ` [PATCH v8 1/2] sysv: linux: Define the __semid_ds32 struct Alistair Francis
2020-05-13 15:22 ` Alistair Francis [this message]
2020-05-27 15:38 ` [PATCH v8 2/2] sysv: linux: Pass 64-bit version of semctl syscall Andreas Schwab
2020-06-01 1:44 ` Alistair Francis
2020-05-27 1:42 ` [PATCH v8 0/2] Support semctl_syscall() for __TIMESIZE==64 Vineet Gupta
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200513152249.5103-3-alistair.francis@wdc.com \
--to=alistair.francis@wdc.com \
--cc=adhemerval.zanella@linaro.org \
--cc=alistair23@gmail.com \
--cc=libc-alpha@sourceware.org \
--cc=stepan@golosunov.pp.ru \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).